func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, kind string) (string, []byte) { originalAccessor, err := meta.Accessor(originalObj) if err != nil { t.Fatal(err) } originalLabels := originalAccessor.GetLabels() originalLabels["DELETE_ME"] = "DELETE_ME" originalAccessor.SetLabels(originalLabels) original, err := json.Marshal(originalObj) if err != nil { t.Fatal(err) } currentAccessor, err := meta.Accessor(currentObj) if err != nil { t.Fatal(err) } currentAnnotations := currentAccessor.GetAnnotations() if currentAnnotations == nil { currentAnnotations = make(map[string]string) } currentAnnotations[annotations.LastAppliedConfigAnnotation] = string(original) currentAccessor.SetAnnotations(currentAnnotations) current, err := json.Marshal(currentObj) if err != nil { t.Fatal(err) } return currentAccessor.GetName(), current }
func TestNoOpUpdates(t *testing.T) { server, registry := NewTestGenericStoreRegistry(t) defer server.Terminate(t) newPod := func() *api.Pod { return &api.Pod{ ObjectMeta: api.ObjectMeta{ Namespace: api.NamespaceDefault, Name: "foo", Labels: map[string]string{"prepare_create": "true"}, }, Spec: api.PodSpec{NodeName: "machine"}, } } var err error var createResult runtime.Object if createResult, err = registry.Create(api.NewDefaultContext(), newPod()); err != nil { t.Fatalf("Unexpected error: %v", err) } createdPod, err := registry.Get(api.NewDefaultContext(), "foo") if err != nil { t.Fatalf("Unexpected error: %v", err) } var updateResult runtime.Object p := newPod() if updateResult, _, err = registry.Update(api.NewDefaultContext(), p.Name, rest.DefaultUpdatedObjectInfo(p, api.Scheme)); err != nil { t.Fatalf("Unexpected error: %v", err) } // Check whether we do not return empty result on no-op update. if !reflect.DeepEqual(createResult, updateResult) { t.Errorf("no-op update should return a correct value, got: %#v", updateResult) } updatedPod, err := registry.Get(api.NewDefaultContext(), "foo") if err != nil { t.Fatalf("Unexpected error: %v", err) } createdMeta, err := meta.Accessor(createdPod) if err != nil { t.Fatalf("Unexpected error: %v", err) } updatedMeta, err := meta.Accessor(updatedPod) if err != nil { t.Fatalf("Unexpected error: %v", err) } if createdMeta.GetResourceVersion() != updatedMeta.GetResourceVersion() { t.Errorf("no-op update should be ignored and not written to etcd") } }
// storeObjectUpdate updates given cache with a new object version from Informer // callback (i.e. with events from etcd) or with an object modified by the // controller itself. Returns "true", if the cache was updated, false if the // object is an old version and should be ignored. func storeObjectUpdate(store cache.Store, obj interface{}, className string) (bool, error) { objAccessor, err := meta.Accessor(obj) if err != nil { return false, fmt.Errorf("Error reading cache of %s: %v", className, err) } objName := objAccessor.GetNamespace() + "/" + objAccessor.GetName() oldObj, found, err := store.Get(obj) if err != nil { return false, fmt.Errorf("Error finding %s %q in controller cache: %v", className, objName, err) } if !found { // This is a new object glog.V(4).Infof("storeObjectUpdate: adding %s %q, version %s", className, objName, objAccessor.GetResourceVersion()) if err = store.Add(obj); err != nil { return false, fmt.Errorf("Error adding %s %q to controller cache: %v", className, objName, err) } return true, nil } oldObjAccessor, err := meta.Accessor(oldObj) if err != nil { return false, err } objResourceVersion, err := strconv.ParseInt(objAccessor.GetResourceVersion(), 10, 64) if err != nil { return false, fmt.Errorf("Error parsing ResourceVersion %q of %s %q: %s", objAccessor.GetResourceVersion(), className, objName, err) } oldObjResourceVersion, err := strconv.ParseInt(oldObjAccessor.GetResourceVersion(), 10, 64) if err != nil { return false, fmt.Errorf("Error parsing old ResourceVersion %q of %s %q: %s", oldObjAccessor.GetResourceVersion(), className, objName, err) } // Throw away only older version, let the same version pass - we do want to // get periodic sync events. if oldObjResourceVersion > objResourceVersion { glog.V(4).Infof("storeObjectUpdate: ignoring %s %q version %s", className, objName, objAccessor.GetResourceVersion()) return false, nil } glog.V(4).Infof("storeObjectUpdate updating %s %q with version %s", className, objName, objAccessor.GetResourceVersion()) if err = store.Update(obj); err != nil { return false, fmt.Errorf("Error updating %s %q in controller cache: %v", className, objName, err) } return true, nil }
// BenchmarkAccessorSetReflection provides a baseline for accessor performance func BenchmarkAccessorSetReflection(b *testing.B) { obj := &InternalObject{ InternalTypeMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", APIVersion: "a", Kind: "b", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"x": "y"}, }, } b.ResetTimer() for i := 0; i < b.N; i++ { acc, err := meta.Accessor(obj) if err != nil { b.Fatal(err) } acc.SetNamespace("something") } b.StopTimer() }
// getChangeCause returns the change-cause annotation of the input object func getChangeCause(obj runtime.Object) string { accessor, err := meta.Accessor(obj) if err != nil { return "" } return accessor.GetAnnotations()[ChangeCauseAnnotation] }
func (r RealPodControl) createPods(nodeName, namespace string, template *api.PodTemplateSpec, object runtime.Object) error { pod, err := GetPodFromTemplate(template, object) if err != nil { return err } if len(nodeName) != 0 { pod.Spec.NodeName = nodeName } if labels.Set(pod.Labels).AsSelector().Empty() { return fmt.Errorf("unable to create pods, no labels") } if newPod, err := r.KubeClient.Core().Pods(namespace).Create(pod); err != nil { r.Recorder.Eventf(object, api.EventTypeWarning, "FailedCreate", "Error creating: %v", err) return fmt.Errorf("unable to create pods: %v", err) } else { accessor, err := meta.Accessor(object) if err != nil { glog.Errorf("parentObject does not have ObjectMeta, %v", err) return nil } glog.V(4).Infof("Controller %v created pod %v", accessor.GetName(), newPod.Name) r.Recorder.Eventf(object, api.EventTypeNormal, "SuccessfulCreate", "Created pod: %v", newPod.Name) } return nil }
// UsageStats calculates latest observed usage stats for all objects func (g *GenericEvaluator) UsageStats(options quota.UsageStatsOptions) (quota.UsageStats, error) { // default each tracked resource to zero result := quota.UsageStats{Used: api.ResourceList{}} for _, resourceName := range g.MatchedResourceNames { result.Used[resourceName] = resource.MustParse("0") } list, err := g.ListFuncByNamespace(options.Namespace, api.ListOptions{}) if err != nil { return result, fmt.Errorf("%s: Failed to list %v: %v", g.Name, g.GroupKind(), err) } _, err = meta.Accessor(list) if err != nil { return result, fmt.Errorf("%s: Unable to understand list result %#v", g.Name, list) } items, err := meta.ExtractList(list) if err != nil { return result, fmt.Errorf("%s: Unable to understand list result %#v (%v)", g.Name, list, err) } for _, item := range items { // need to verify that the item matches the set of scopes matchesScopes := true for _, scope := range options.Scopes { if !g.MatchesScope(scope, item) { matchesScopes = false } } // only count usage if there was a match if matchesScopes { result.Used = quota.Add(result.Used, g.Usage(item)) } } return result, nil }
// nameIndexFunc is an index function that indexes based on an object's name func nameIndexFunc(obj interface{}) ([]string, error) { meta, err := meta.Accessor(obj) if err != nil { return []string{""}, fmt.Errorf("object has no meta: %v", err) } return []string{meta.GetName()}, nil }
// watchHandler watches w and keeps *resourceVersion up to date. func (r *Reflector) watchHandler(w watch.Interface, resourceVersion *string, errc chan error, stopCh <-chan struct{}) error { start := time.Now() eventCount := 0 // Stopping the watcher should be idempotent and if we return from this function there's no way // we're coming back in with the same watch interface. defer w.Stop() loop: for { select { case <-stopCh: return errorStopRequested case err := <-errc: return err case event, ok := <-w.ResultChan(): if !ok { break loop } if event.Type == watch.Error { return apierrs.FromObject(event.Object) } if e, a := r.expectedType, reflect.TypeOf(event.Object); e != nil && e != a { utilruntime.HandleError(fmt.Errorf("%s: expected type %v, but watch event object had type %v", r.name, e, a)) continue } meta, err := meta.Accessor(event.Object) if err != nil { utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event)) continue } newResourceVersion := meta.GetResourceVersion() switch event.Type { case watch.Added: r.store.Add(event.Object) case watch.Modified: r.store.Update(event.Object) case watch.Deleted: // TODO: Will any consumers need access to the "last known // state", which is passed in event.Object? If so, may need // to change this. r.store.Delete(event.Object) default: utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event)) } *resourceVersion = newResourceVersion r.setLastSyncResourceVersion(newResourceVersion) eventCount++ } } watchDuration := time.Now().Sub(start) if watchDuration < 1*time.Second && eventCount == 0 { glog.V(4).Infof("%s: Unexpected watch close - watch lasted less than a second and no items received", r.name) return errors.New("very short watch") } glog.V(4).Infof("%s: Watch close - %v total %v items received", r.name, r.expectedType, eventCount) return nil }
func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { meta, err := meta.Accessor(obj) if err != nil { return "", err } name := meta.GetName() if msgs := validation.IsValidPathSegmentName(name); len(msgs) != 0 { return "", fmt.Errorf("invalid name: %v", msgs) } return prefix + "/" + name, nil }
// ObjectReplenenishmentDeleteFunc will replenish on every delete func ObjectReplenishmentDeleteFunc(options *ReplenishmentControllerOptions) func(obj interface{}) { return func(obj interface{}) { metaObject, err := meta.Accessor(obj) if err != nil { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.Errorf("replenishment controller could not get object from tombstone %+v, could take up to %v before quota is replenished", obj, options.ResyncPeriod()) utilruntime.HandleError(err) return } metaObject, err = meta.Accessor(tombstone.Obj) if err != nil { glog.Errorf("replenishment controller tombstone contained object that is not a meta %+v, could take up to %v before quota is replenished", tombstone.Obj, options.ResyncPeriod()) utilruntime.HandleError(err) return } } options.ReplenishmentFunc(options.GroupKind, metaObject.GetNamespace(), nil) } }
func (t *Tester) createObject(ctx api.Context, obj runtime.Object) error { accessor, err := meta.Accessor(obj) if err != nil { return err } key, err := t.storage.KeyFunc(ctx, accessor.GetName()) if err != nil { return err } return t.storage.Storage.Create(ctx, key, obj, nil, 0) }
func testGetOwnerReferences(t *testing.T) { obj, expected := getObjectMetaAndOwnerRefereneces() accessor, err := meta.Accessor(&obj) if err != nil { t.Error(err) } references := accessor.GetOwnerReferences() if !reflect.DeepEqual(references, expected) { t.Errorf("expect %#v\n got %#v", expected, references) } }
func (t *testRESTStrategy) PrepareForCreate(obj runtime.Object) { metaObj, err := meta.Accessor(obj) if err != nil { panic(err.Error()) } labels := metaObj.GetLabels() if labels == nil { labels = map[string]string{} } labels["prepare_create"] = "true" metaObj.SetLabels(labels) }
func (t *Tester) getObject(ctx api.Context, obj runtime.Object) (runtime.Object, error) { accessor, err := meta.Accessor(obj) if err != nil { return nil, err } result, err := t.storage.Get(ctx, accessor.GetName()) if err != nil { return nil, err } return result, nil }
func testSetOwnerReferences(t *testing.T) { expected, references := getObjectMetaAndOwnerRefereneces() obj := MyAPIObject2{} accessor, err := meta.Accessor(&obj) if err != nil { t.Error(err) } accessor.SetOwnerReferences(references) if e, a := expected.ObjectMeta.OwnerReferences, obj.ObjectMeta.OwnerReferences; !reflect.DeepEqual(e, a) { t.Errorf("expect %#v\n got %#v", e, a) } }
func TestFiltering(t *testing.T) { server, etcdStorage := newEtcdTestStorage(t, testapi.Default.Codec(), etcdtest.PathPrefix()) defer server.Terminate(t) cacher := newTestCacher(etcdStorage) defer cacher.Stop() // Ensure that the cacher is initialized, before creating any pods, // so that we are sure that all events will be present in cacher. syncWatcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", "0", storage.Everything) if err != nil { t.Fatalf("Unexpected error: %v", err) } syncWatcher.Stop() podFoo := makeTestPod("foo") podFoo.Labels = map[string]string{"filter": "foo"} podFooFiltered := makeTestPod("foo") podFooPrime := makeTestPod("foo") podFooPrime.Labels = map[string]string{"filter": "foo"} podFooPrime.Spec.NodeName = "fakeNode" fooCreated := updatePod(t, etcdStorage, podFoo, nil) fooFiltered := updatePod(t, etcdStorage, podFooFiltered, fooCreated) fooUnfiltered := updatePod(t, etcdStorage, podFoo, fooFiltered) _ = updatePod(t, etcdStorage, podFooPrime, fooUnfiltered) deleted := api.Pod{} if err := etcdStorage.Delete(context.TODO(), etcdtest.AddPrefix("pods/ns/foo"), &deleted, nil); err != nil { t.Errorf("Unexpected error: %v", err) } // Set up Watch for object "podFoo" with label filter set. selector := labels.SelectorFromSet(labels.Set{"filter": "foo"}) filter := func(obj runtime.Object) bool { metadata, err := meta.Accessor(obj) if err != nil { t.Errorf("Unexpected error: %v", err) return false } return selector.Matches(labels.Set(metadata.GetLabels())) } watcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", fooCreated.ResourceVersion, filter) if err != nil { t.Fatalf("Unexpected error: %v", err) } defer watcher.Stop() verifyWatchEvent(t, watcher, watch.Deleted, podFooFiltered) verifyWatchEvent(t, watcher, watch.Added, podFoo) verifyWatchEvent(t, watcher, watch.Modified, podFooPrime) verifyWatchEvent(t, watcher, watch.Deleted, podFooPrime) }
// MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make // keys for API objects which implement meta.Interface. // The key uses the format <namespace>/<name> unless <namespace> is empty, then // it's just <name>. // // TODO: replace key-as-string with a key-as-struct so that this // packing/unpacking won't be necessary. func MetaNamespaceKeyFunc(obj interface{}) (string, error) { if key, ok := obj.(ExplicitKey); ok { return string(key), nil } meta, err := meta.Accessor(obj) if err != nil { return "", fmt.Errorf("object has no meta: %v", err) } if len(meta.GetNamespace()) > 0 { return meta.GetNamespace() + "/" + meta.GetName(), nil } return meta.GetName(), nil }
func hasUID(obj runtime.Object) (bool, error) { if obj == nil { return false, nil } accessor, err := meta.Accessor(obj) if err != nil { return false, errors.NewInternalError(err) } if len(accessor.GetUID()) == 0 { return false, nil } return true, nil }
func (r RealPodControl) DeletePod(namespace string, podID string, object runtime.Object) error { accessor, err := meta.Accessor(object) if err != nil { return fmt.Errorf("object does not have ObjectMeta, %v", err) } if err := r.KubeClient.Core().Pods(namespace).Delete(podID, nil); err != nil { r.Recorder.Eventf(object, api.EventTypeWarning, "FailedDelete", "Error deleting: %v", err) return fmt.Errorf("unable to delete pods: %v", err) } else { glog.V(4).Infof("Controller %v deleted pod %v", accessor.GetName(), podID) r.Recorder.Eventf(object, api.EventTypeNormal, "SuccessfulDelete", "Deleted pod: %v", podID) } return nil }
func objectToVersionedRuntimeObject(obj interface{}) (runtime.Object, uint64, error) { object, ok := obj.(runtime.Object) if !ok { return nil, 0, fmt.Errorf("obj does not implement runtime.Object interface: %v", obj) } meta, err := meta.Accessor(object) if err != nil { return nil, 0, err } resourceVersion, err := parseResourceVersion(meta.GetResourceVersion()) if err != nil { return nil, 0, err } return object, resourceVersion, nil }
//CreateObjList will create a list from the array of objects func CreateObjList(prefix string, helper storage.Interface, items []runtime.Object) error { for i := range items { obj := items[i] meta, err := meta.Accessor(obj) if err != nil { return err } err = CreateObj(helper, path.Join(prefix, meta.GetName()), obj, obj, 0) if err != nil { return err } items[i] = obj } return nil }
// Preconditions satisfies the UpdatedObjectInfo interface. func (i *defaultUpdatedObjectInfo) Preconditions() *api.Preconditions { // Attempt to get the UID out of the object accessor, err := meta.Accessor(i.obj) if err != nil { // If no UID can be read, no preconditions are possible return nil } // If empty, no preconditions needed uid := accessor.GetUID() if len(uid) == 0 { return nil } return &api.Preconditions{UID: &uid} }
func (t *Tester) emitObject(obj runtime.Object, action string) error { ctx := t.tester.TestContext() var err error switch action { case etcdstorage.EtcdCreate: err = t.createObject(ctx, obj) case etcdstorage.EtcdDelete: accessor, err := meta.Accessor(obj) if err != nil { return err } _, err = t.storage.Delete(ctx, accessor.GetName(), nil) default: err = fmt.Errorf("unexpected action: %v", action) } return err }
func extractResourceName(a Attributes) (name string, resource unversioned.GroupResource, err error) { name = "Unknown" resource = a.GetResource().GroupResource() obj := a.GetObject() if obj != nil { accessor, err := meta.Accessor(obj) if err != nil { return "", unversioned.GroupResource{}, err } // this is necessary because name object name generation has not occurred yet if len(accessor.GetName()) > 0 { name = accessor.GetName() } else if len(accessor.GetGenerateName()) > 0 { name = accessor.GetGenerateName() } } return name, resource, nil }
func GetPodFromTemplate(template *api.PodTemplateSpec, parentObject runtime.Object) (*api.Pod, error) { desiredLabels := getPodsLabelSet(template) desiredAnnotations, err := getPodsAnnotationSet(template, parentObject) if err != nil { return nil, err } accessor, err := meta.Accessor(parentObject) if err != nil { return nil, fmt.Errorf("parentObject does not have ObjectMeta, %v", err) } prefix := getPodsPrefix(accessor.GetName()) pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Labels: desiredLabels, Annotations: desiredAnnotations, GenerateName: prefix, }, } if err := api.Scheme.Convert(&template.Spec, &pod.Spec); err != nil { return nil, fmt.Errorf("unable to convert pod template: %v", err) } return pod, nil }
// GetModifiedConfiguration retrieves the modified configuration of the object. // If annotate is true, it embeds the result as an anotation in the modified // configuration. If an object was read from the command input, it will use that // version of the object. Otherwise, it will use the version from the server. func GetModifiedConfiguration(info *resource.Info, annotate bool, codec runtime.Encoder) ([]byte, error) { // First serialize the object without the annotation to prevent recursion, // then add that serialization to it as the annotation and serialize it again. var modified []byte if info.VersionedObject != nil { // If an object was read from input, use that version. accessor, err := meta.Accessor(info.VersionedObject) if err != nil { return nil, err } // Get the current annotations from the object. annots := accessor.GetAnnotations() if annots == nil { annots = map[string]string{} } original := annots[annotations.LastAppliedConfigAnnotation] delete(annots, annotations.LastAppliedConfigAnnotation) accessor.SetAnnotations(annots) // TODO: this needs to be abstracted - there should be no assumption that versioned object // can be marshalled to JSON. modified, err = json.Marshal(info.VersionedObject) if err != nil { return nil, err } if annotate { annots[annotations.LastAppliedConfigAnnotation] = string(modified) accessor.SetAnnotations(annots) // TODO: this needs to be abstracted - there should be no assumption that versioned object // can be marshalled to JSON. modified, err = json.Marshal(info.VersionedObject) if err != nil { return nil, err } } // Restore the object to its original condition. annots[annotations.LastAppliedConfigAnnotation] = original accessor.SetAnnotations(annots) } else { // Otherwise, use the server side version of the object. accessor := info.Mapping.MetadataAccessor // Get the current annotations from the object. annots, err := accessor.Annotations(info.Object) if err != nil { return nil, err } if annots == nil { annots = map[string]string{} } original := annots[annotations.LastAppliedConfigAnnotation] delete(annots, annotations.LastAppliedConfigAnnotation) if err := accessor.SetAnnotations(info.Object, annots); err != nil { return nil, err } modified, err = runtime.Encode(codec, info.Object) if err != nil { return nil, err } if annotate { annots[annotations.LastAppliedConfigAnnotation] = string(modified) if err := info.Mapping.MetadataAccessor.SetAnnotations(info.Object, annots); err != nil { return nil, err } modified, err = runtime.Encode(codec, info.Object) if err != nil { return nil, err } } // Restore the object to its original condition. annots[annotations.LastAppliedConfigAnnotation] = original if err := info.Mapping.MetadataAccessor.SetAnnotations(info.Object, annots); err != nil { return nil, err } } return modified, nil }
func TestAPIObjectMeta(t *testing.T) { j := &api.Pod{ TypeMeta: unversioned.TypeMeta{APIVersion: "/a", Kind: "b"}, ObjectMeta: api.ObjectMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"x": "y"}, Finalizers: []string{ "finalizer.1", "finalizer.2", }, }, } var _ meta.Object = &j.ObjectMeta var _ meta.ObjectMetaAccessor = j accessor, err := meta.Accessor(j) if err != nil { t.Fatalf("unexpected error: %v", err) } if accessor != meta.Object(&j.ObjectMeta) { t.Fatalf("should have returned the same pointer: %#v %#v", accessor, j) } if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetNamespace("baz") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") accessor.SetFinalizers([]string{"finalizer.3"}) // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "generate", j.GenerateName; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := types.UID("other"), j.UID; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("d") typeAccessor.SetKind("e") if e, a := "d", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "e", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } }
func TestGenericObjectMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` APIVersion string `json:"apiVersion,omitempty"` } type ObjectMeta struct { Namespace string `json:"namespace,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` Finalizers []string `json:"finalizers,omitempty"` OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"` } type Object struct { TypeMeta `json:",inline"` ObjectMeta `json:"metadata"` } j := Object{ TypeMeta{ APIVersion: "a", Kind: "b", }, ObjectMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"a": "b"}, Finalizers: []string{ "finalizer.1", "finalizer.2", }, }, } accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 1, len(accessor.GetLabels()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 1, len(accessor.GetAnnotations()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetNamespace("baz") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") accessor.SetLabels(map[string]string{"other": "label"}) accessor.SetAnnotations(map[string]string{"c": "d"}) accessor.SetFinalizers([]string{"finalizer.3"}) // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "generate", j.GenerateName; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "other", j.UID; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := map[string]string{"other": "label"}, j.Labels; !reflect.DeepEqual(e, a) { t.Errorf("expected %#v, got %#v", e, a) } if e, a := map[string]string{"c": "d"}, j.Annotations; !reflect.DeepEqual(e, a) { t.Errorf("expected %#v, got %#v", e, a) } if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } }
func TestGenericListMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` APIVersion string `json:"apiVersion,omitempty"` } type ListMeta struct { SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` } type Object struct { TypeMeta `json:",inline"` ListMeta `json:"metadata"` } j := Object{ TypeMeta{ APIVersion: "a", Kind: "b", }, ListMeta{ ResourceVersion: "1", SelfLink: "some/place/only/we/know", }, } accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetName("bar") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") // Prove that accessor changes the original object. if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } }