Use name from server when displaying create/update

Allows generated names from files to be displayed so users can
interact with them.
This commit is contained in:
Clayton Coleman 2015-02-06 11:57:52 -05:00
parent bb6b332a8b
commit 52c6c60b15
8 changed files with 82 additions and 42 deletions

View File

@ -232,7 +232,7 @@ Examples:
$ cat pod.json | kubectl update -f -
<update a pod based on the json passed into stdin>
$ kubectl update pods my-pod --patch='{ "apiVersion": "v1beta1", "desiredState": { "manifest": [{ "cpu": 100 }]}}'
<update a pod by downloading it, applying the patch, then updating, requires apiVersion be specified>

View File

@ -67,11 +67,12 @@ Examples:
if err := schema.ValidateBytes(data); err != nil {
return err
}
if err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, data); err != nil {
obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, data)
if err != nil {
return err
}
count++
// TODO: if generation of names added to server side, change this to use the server's name
info.Refresh(obj, true)
fmt.Fprintf(out, "%s\n", info.Name)
return nil
})

View File

@ -26,6 +26,7 @@ import (
func TestCreateObject(t *testing.T) {
pods, _ := testData()
pods.Items[0].Name = "redis-master"
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
@ -81,13 +82,15 @@ func TestCreateMultipleObject(t *testing.T) {
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
cmd.Run(cmd, []string{})
if buf.String() != "redis-master\nfrontend\n" {
// Names should come from the REST response, NOT the files
if buf.String() != "foo\nbaz\n" {
t.Errorf("unexpected output: %s", buf.String())
}
}
func TestCreateDirectory(t *testing.T) {
pods, svc := testData()
pods.Items[0].Name = "redis-master"
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
@ -114,7 +117,7 @@ func TestCreateDirectory(t *testing.T) {
cmd.Flags().Set("filename", "../../../examples/guestbook")
cmd.Run(cmd, []string{})
if buf.String() != "frontend-controller\nfrontend\nredis-master\nredis-master\nredis-slave-controller\nredisslave\n" {
if buf.String() != "baz\nbaz\nbaz\nredis-master\nbaz\nbaz\n" {
t.Errorf("unexpected output: %s", buf.String())
}
}

View File

@ -42,7 +42,7 @@ Examples:
$ cat pod.json | kubectl update -f -
<update a pod based on the json passed into stdin>
$ kubectl update pods my-pod --patch='{ "apiVersion": "v1beta1", "desiredState": { "manifest": [{ "cpu": 100 }]}}'
<update a pod by downloading it, applying the patch, then updating, requires apiVersion be specified>`,
Run: func(cmd *cobra.Command, args []string) {
@ -67,29 +67,32 @@ Examples:
if len(flags.Filenames) != 0 && len(patch) != 0 {
usageError(cmd, "Can not specify both --filename and --patch")
}
if len(flags.Filenames) > 0 {
err := r.Visit(func(info *resource.Info) error {
data, err := info.Mapping.Codec.Encode(info.Object)
if err != nil {
return err
}
if err := schema.ValidateBytes(data); err != nil {
return err
}
if err := resource.NewHelper(info.Client, info.Mapping).
Update(info.Namespace, info.Name, true, data); err != nil {
return err
}
fmt.Fprintf(out, "%s\n", info.Name)
return nil
})
checkErr(err)
} else {
// TODO: Make patching work with -f, updating with patched JSON input files
// TODO: Make patching work with -f, updating with patched JSON input files
if len(flags.Filenames) == 0 {
name := updateWithPatch(cmd, args, f, patch)
fmt.Fprintf(out, "%s\n", name)
return
}
err = r.Visit(func(info *resource.Info) error {
data, err := info.Mapping.Codec.Encode(info.Object)
if err != nil {
return err
}
if err := schema.ValidateBytes(data); err != nil {
return err
}
obj, err := resource.NewHelper(info.Client, info.Mapping).Update(info.Namespace, info.Name, true, data)
if err != nil {
return err
}
info.Refresh(obj, true)
fmt.Fprintf(out, "%s\n", info.Name)
return nil
})
checkErr(err)
},
}
cmd.Flags().VarP(&flags.Filenames, "filename", "f", "Filename, directory, or URL to file to use to update the resource")
@ -115,7 +118,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string
data, err := helper.Codec.Encode(obj)
checkErr(err)
err = helper.Update(namespace, name, true, data)
obj, err = helper.Update(namespace, name, true, data)
checkErr(err)
return name
}

View File

@ -67,7 +67,7 @@ func TestUpdateObject(t *testing.T) {
cmd.Run(cmd, []string{})
// uses the name from the file, not the response
if buf.String() != "redis-master\n" {
if buf.String() != "foo\n" {
t.Errorf("unexpected output: %s", buf.String())
}
}
@ -104,7 +104,7 @@ func TestUpdateMultipleObject(t *testing.T) {
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
cmd.Run(cmd, []string{})
if buf.String() != "redis-master\nfrontend\n" {
if buf.String() != "foo\nbaz\n" {
t.Errorf("unexpected output: %s", buf.String())
}
}
@ -139,7 +139,7 @@ func TestUpdateDirectory(t *testing.T) {
cmd.Flags().Set("namespace", "test")
cmd.Run(cmd, []string{})
if buf.String() != "frontend-controller\nfrontend\nredis-master\nredis-master\nredis-slave-controller\nredisslave\n" {
if buf.String() != "qux\nbaz\nbaz\nfoo\nqux\nbaz\n" {
t.Errorf("unexpected output: %s", buf.String())
}
}

View File

@ -95,7 +95,7 @@ func (m *Helper) Delete(namespace, name string) error {
Error()
}
func (m *Helper) Create(namespace string, modify bool, data []byte) error {
func (m *Helper) Create(namespace string, modify bool, data []byte) (runtime.Object, error) {
if modify {
obj, err := m.Codec.Decode(data)
if err != nil {
@ -111,11 +111,11 @@ func (m *Helper) Create(namespace string, modify bool, data []byte) error {
}
if version != "" {
if err := m.Versioner.SetResourceVersion(obj, ""); err != nil {
return err
return nil, err
}
newData, err := m.Codec.Encode(obj)
if err != nil {
return err
return nil, err
}
data = newData
}
@ -124,11 +124,11 @@ func (m *Helper) Create(namespace string, modify bool, data []byte) error {
return createResource(m.RESTClient, m.Resource, namespace, data)
}
func createResource(c RESTClient, resource, namespace string, data []byte) error {
return c.Post().Namespace(namespace).Resource(resource).Body(data).Do().Error()
func createResource(c RESTClient, resource, namespace string, data []byte) (runtime.Object, error) {
return c.Post().Namespace(namespace).Resource(resource).Body(data).Do().Get()
}
func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) error {
func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (runtime.Object, error) {
c := m.RESTClient
obj, err := m.Codec.Decode(data)
@ -152,14 +152,14 @@ func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) err
}
serverVersion, err := m.Versioner.ResourceVersion(serverObj)
if err != nil {
return err
return nil, err
}
if err := m.Versioner.SetResourceVersion(obj, serverVersion); err != nil {
return err
return nil, err
}
newData, err := m.Codec.Encode(obj)
if err != nil {
return err
return nil, err
}
data = newData
}
@ -167,6 +167,6 @@ func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) err
return updateResource(c, m.Resource, namespace, name, data)
}
func updateResource(c RESTClient, resource, namespace, name string, data []byte) error {
return c.Put().Namespace(namespace).Resource(resource).Name(name).Body(data).Do().Error()
func updateResource(c RESTClient, resource, namespace, name string, data []byte) (runtime.Object, error) {
return c.Put().Namespace(namespace).Resource(resource).Name(name).Body(data).Do().Get()
}

View File

@ -193,7 +193,7 @@ func TestHelperCreate(t *testing.T) {
if test.Object != nil {
data = []byte(runtime.EncodeOrDie(testapi.Codec(), test.Object))
}
err := modifier.Create("bar", test.Modify, data)
_, err := modifier.Create("bar", test.Modify, data)
if (err != nil) != test.Err {
t.Errorf("%d: unexpected error: %t %v", i, test.Err, err)
}
@ -448,7 +448,7 @@ func TestHelperUpdate(t *testing.T) {
if test.Object != nil {
data = []byte(runtime.EncodeOrDie(testapi.Codec(), test.Object))
}
err := modifier.Update("bar", "foo", test.Overwrite, data)
_, err := modifier.Update("bar", "foo", test.Overwrite, data)
if (err != nil) != test.Err {
t.Errorf("%d: unexpected error: %t %v", i, test.Err, err)
}

View File

@ -87,6 +87,7 @@ func (i *Info) Visit(fn VisitorFunc) error {
return fn(i)
}
// Get retrieves the object from the Namespace and Name fields
func (i *Info) Get() error {
obj, err := NewHelper(i.Client, i.Mapping).Get(i.Namespace, i.Name)
if err != nil {
@ -97,6 +98,38 @@ func (i *Info) Get() error {
return nil
}
// Refresh updates the object with another object. If ignoreError is set
// the Object will be updated even if name, namespace, or resourceVersion
// attributes cannot be loaded from the object.
func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error {
name, err := i.Mapping.MetadataAccessor.Name(obj)
if err != nil {
if !ignoreError {
return err
}
} else {
i.Name = name
}
namespace, err := i.Mapping.MetadataAccessor.Namespace(obj)
if err != nil {
if !ignoreError {
return err
}
} else {
i.Namespace = namespace
}
version, err := i.Mapping.MetadataAccessor.ResourceVersion(obj)
if err != nil {
if !ignoreError {
return err
}
} else {
i.ResourceVersion = version
}
i.Object = obj
return nil
}
// Watch returns server changes to this object after it was retrieved.
func (i *Info) Watch(resourceVersion string) (watch.Interface, error) {
return NewHelper(i.Client, i.Mapping).WatchSingle(i.Namespace, i.Name, resourceVersion)