// Visit implements Visitor func (r *Selector) Visit(fn VisitorFunc) error { list, err := NewHelper(r.Client, r.Mapping).List(r.Namespace, r.ResourceMapping().GroupVersionKind.GroupVersion().String(), r.Selector, r.Export) if err != nil { if errors.IsBadRequest(err) || errors.IsNotFound(err) { if se, ok := err.(*errors.StatusError); ok { // modify the message without hiding this is an API error if r.Selector.Empty() { se.ErrStatus.Message = fmt.Sprintf("Unable to list %q: %v", r.Mapping.Resource, se.ErrStatus.Message) } else { se.ErrStatus.Message = fmt.Sprintf("Unable to find %q that match the selector %q: %v", r.Mapping.Resource, r.Selector, se.ErrStatus.Message) } return se } if r.Selector.Empty() { return fmt.Errorf("Unable to list %q: %v", r.Mapping.Resource, err) } else { return fmt.Errorf("Unable to find %q that match the selector %q: %v", r.Mapping.Resource, r.Selector, err) } } return err } accessor := r.Mapping.MetadataAccessor resourceVersion, _ := accessor.ResourceVersion(list) info := &Info{ Client: r.Client, Mapping: r.Mapping, Namespace: r.Namespace, Object: list, ResourceVersion: resourceVersion, } return fn(info, nil) }
func (t *Tester) testUpdateInvokesValidation(obj runtime.Object, createFn CreateFunc, invalidUpdateFn ...UpdateFunc) { ctx := t.TestContext() foo := copyOrDie(obj) t.setObjectMeta(foo, t.namer(4)) if err := createFn(ctx, foo); err != nil { t.Errorf("unexpected error: %v", err) } for _, update := range invalidUpdateFn { toUpdate := update(copyOrDie(foo)) toUpdateMeta := t.getObjectMetaOrFail(toUpdate) got, created, err := t.storage.(rest.Updater).Update(t.TestContext(), toUpdateMeta.Name, rest.DefaultUpdatedObjectInfo(toUpdate, api.Scheme)) if got != nil || created { t.Errorf("expected nil object and no creation for object: %v", toUpdate) } if !errors.IsInvalid(err) && !errors.IsBadRequest(err) { t.Errorf("expected invalid or bad request error, got %v", err) } } }
func TestPatchWithCreateOnUpdate(t *testing.T) { _, s := framework.RunAMaster(nil) defer s.Close() c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) ns := framework.CreateTestingNamespace("patch-with-create", s, t) defer framework.DeleteTestingNamespace(ns, s, t) endpointTemplate := &v1.Endpoints{ ObjectMeta: metav1.ObjectMeta{ Name: "patchendpoint", Namespace: ns.Name, }, Subsets: []v1.EndpointSubset{ { Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{{Port: 80, Protocol: v1.ProtocolTCP}}, }, }, } patchEndpoint := func(json []byte) (runtime.Object, error) { return c.Core().RESTClient().Patch(types.MergePatchType).Resource("endpoints").Namespace(ns.Name).Name("patchendpoint").Body(json).Do().Get() } // Make sure patch doesn't get to CreateOnUpdate { endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { t.Fatalf("Failed creating endpoint JSON: %v", err) } if obj, err := patchEndpoint(endpointJSON); !apierrors.IsNotFound(err) { t.Errorf("Expected notfound creating from patch, got error=%v and object: %#v", err, obj) } } // Create the endpoint (endpoints set AllowCreateOnUpdate=true) to get a UID and resource version createdEndpoint, err := c.Core().Endpoints(ns.Name).Update(endpointTemplate) if err != nil { t.Fatalf("Failed creating endpoint: %v", err) } // Make sure identity patch is accepted { endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), createdEndpoint) if err != nil { t.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); err != nil { t.Errorf("Failed patching endpoint: %v", err) } } // Make sure patch complains about a mismatched resourceVersion { endpointTemplate.Name = "" endpointTemplate.UID = "" endpointTemplate.ResourceVersion = "1" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { t.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); !apierrors.IsConflict(err) { t.Errorf("Expected error, got %#v", err) } } // Make sure patch complains about mutating the UID { endpointTemplate.Name = "" endpointTemplate.UID = "abc" endpointTemplate.ResourceVersion = "" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { t.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); !apierrors.IsInvalid(err) { t.Errorf("Expected error, got %#v", err) } } // Make sure patch complains about a mismatched name { endpointTemplate.Name = "changedname" endpointTemplate.UID = "" endpointTemplate.ResourceVersion = "" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { t.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); !apierrors.IsBadRequest(err) { t.Errorf("Expected error, got %#v", err) } } // Make sure patch containing originally submitted JSON is accepted { endpointTemplate.Name = "" endpointTemplate.UID = "" endpointTemplate.ResourceVersion = "" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { t.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); err != nil { t.Errorf("Failed patching endpoint: %v", err) } } }