func TestControllerRoleLabel(t *testing.T) { roles := ControllerRoles() for i := range roles { role := roles[i] accessor, err := meta.Accessor(&role) if err != nil { t.Fatalf("unexpected error: %v", err) } if got, want := accessor.GetLabels(), map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"}; !reflect.DeepEqual(got, want) { t.Errorf("ClusterRole: %s GetLabels() = %s, want %s", accessor.GetName(), got, want) } } rolebindings := ControllerRoleBindings() for i := range rolebindings { rolebinding := rolebindings[i] accessor, err := meta.Accessor(&rolebinding) if err != nil { t.Fatalf("unexpected error: %v", err) } if got, want := accessor.GetLabels(), map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"}; !reflect.DeepEqual(got, want) { t.Errorf("ClusterRoleBinding: %s GetLabels() = %s, want %s", accessor.GetName(), got, want) } } }
func isChangingOwnerReference(newObj, oldObj runtime.Object) bool { newMeta, err := meta.Accessor(newObj) if err != nil { // if we don't have objectmeta, we don't have the object reference return false } if oldObj == nil { return len(newMeta.GetOwnerReferences()) > 0 } oldMeta, err := meta.Accessor(oldObj) if err != nil { // if we don't have objectmeta, we don't have the object reference return false } // compare the old and new. If they aren't the same, then we're trying to change an ownerRef oldOwners := oldMeta.GetOwnerReferences() newOwners := newMeta.GetOwnerReferences() if len(oldOwners) != len(newOwners) { return true } for i := range oldOwners { if !api.Semantic.DeepEqual(oldOwners[i], newOwners[i]) { return true } } return false }
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 := runtime.Encode(testapi.Default.Codec(), 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 := runtime.Encode(testapi.Default.Codec(), currentObj) if err != nil { t.Fatal(err) } return currentAccessor.GetName(), current }
func TestNoOpUpdates(t *testing.T) { destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() newPod := func() *api.Pod { return &api.Pod{ ObjectMeta: metav1.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(genericapirequest.NewDefaultContext(), newPod()); err != nil { t.Fatalf("Unexpected error: %v", err) } createdPod, err := registry.Get(genericapirequest.NewDefaultContext(), "foo", &metav1.GetOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } var updateResult runtime.Object p := newPod() if updateResult, _, err = registry.Update(genericapirequest.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(genericapirequest.NewDefaultContext(), "foo", &metav1.GetOptions{}) 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) { objName, err := controller.KeyFunc(obj) if err != nil { return false, fmt.Errorf("Couldn't get key for object %+v: %v", obj, err) } oldObj, found, err := store.Get(obj) if err != nil { return false, fmt.Errorf("Error finding %s %q in controller cache: %v", className, objName, err) } objAccessor, err := meta.Accessor(obj) if err != nil { return false, 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 }
// updateAnnotations updates annotations of obj func (o AnnotateOptions) updateAnnotations(obj runtime.Object) error { accessor, err := meta.Accessor(obj) if err != nil { return err } if !o.overwrite { if err := validateNoAnnotationOverwrites(accessor, o.newAnnotations); err != nil { return err } } annotations := accessor.GetAnnotations() if annotations == nil { annotations = make(map[string]string) } for key, value := range o.newAnnotations { annotations[key] = value } for _, annotation := range o.removeAnnotations { delete(annotations, annotation) } accessor.SetAnnotations(annotations) if len(o.resourceVersion) != 0 { accessor.SetResourceVersion(o.resourceVersion) } return nil }
func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, labels map[string]string, remove []string) error { accessor, err := meta.Accessor(obj) if err != nil { return err } if !overwrite { if err := validateNoOverwrites(accessor, labels); err != nil { return err } } objLabels := accessor.GetLabels() if objLabels == nil { objLabels = make(map[string]string) } for key, value := range labels { objLabels[key] = value } for _, label := range remove { delete(objLabels, label) } accessor.SetLabels(objLabels) if len(resourceVersion) != 0 { accessor.SetResourceVersion(resourceVersion) } return nil }
// BenchmarkAccessorSetFastPath shows the interface fast path func BenchmarkAccessorSetFastPath(b *testing.B) { obj := &api.Pod{ TypeMeta: metav1.TypeMeta{APIVersion: "/a", Kind: "b"}, ObjectMeta: metav1.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"}, }, } 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() }
// updateTaints updates taints of obj func (o TaintOptions) updateTaints(obj runtime.Object) error { accessor, err := meta.Accessor(obj) if err != nil { return err } if !o.overwrite { if err := validateNoTaintOverwrites(accessor, o.taintsToAdd); err != nil { return err } } annotations := accessor.GetAnnotations() if annotations == nil { annotations = make(map[string]string) } newTaints, err := reorganizeTaints(accessor, o.overwrite, o.taintsToAdd, o.taintsToRemove) if err != nil { return err } taintsData, err := json.Marshal(newTaints) if err != nil { return err } annotations[v1.TaintsAnnotationKey] = string(taintsData) accessor.SetAnnotations(annotations) return nil }
func TestParseFederationReplicaSetReference(t *testing.T) { successPrefs := []string{ `{"rebalance": true, "clusters": { "k8s-1": {"minReplicas": 10, "maxReplicas": 20, "weight": 2}, "*": {"weight": 1} }}`, } failedPrefes := []string{ `{`, // bad json } rs := newReplicaSetWithReplicas("rs-1", 100) accessor, _ := meta.Accessor(rs) anno := accessor.GetAnnotations() if anno == nil { anno = make(map[string]string) accessor.SetAnnotations(anno) } for _, prefString := range successPrefs { anno[FedReplicaSetPreferencesAnnotation] = prefString pref, err := parseFederationReplicaSetReference(rs) assert.NotNil(t, pref) assert.Nil(t, err) } for _, prefString := range failedPrefes { anno[FedReplicaSetPreferencesAnnotation] = prefString pref, err := parseFederationReplicaSetReference(rs) assert.Nil(t, pref) assert.NotNil(t, err) } }
// 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 GetPodFromTemplate(template *v1.PodTemplateSpec, parentObject runtime.Object, controllerRef *metav1.OwnerReference) (*v1.Pod, error) { desiredLabels := getPodsLabelSet(template) desiredFinalizers := getPodsFinalizers(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 := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: desiredLabels, Annotations: desiredAnnotations, GenerateName: prefix, Finalizers: desiredFinalizers, }, } if controllerRef != nil { pod.OwnerReferences = append(pod.OwnerReferences, *controllerRef) } clone, err := api.Scheme.DeepCopy(&template.Spec) if err != nil { return nil, err } pod.Spec = *clone.(*v1.PodSpec) return pod, nil }
// MetaNamespaceIndexFunc is a default index function that indexes based on an object's namespace func MetaNamespaceIndexFunc(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.GetNamespace()}, nil }
func (t *tracker) Delete(gvk schema.GroupVersionKind, ns, name string) error { if err := checkNamespace(gvk, ns); err != nil { return err } t.lock.Lock() defer t.lock.Unlock() found := false for i, existingObj := range t.objects[gvk] { objMeta, err := meta.Accessor(existingObj) if err != nil { return err } if objMeta.GetNamespace() == ns && objMeta.GetName() == name { t.objects[gvk] = append(t.objects[gvk][:i], t.objects[gvk][i+1:]...) found = true break } } if found { return nil } return errors.NewNotFound(schema.GroupResource{Group: gvk.Group, Resource: gvk.Kind}, name) }
func shouldOrphanDependents(e *event, accessor metav1.Object) bool { // The delta_fifo may combine the creation and update of the object into one // event, so we need to check AddEvent as well. if e.oldObj == nil { if accessor.GetDeletionTimestamp() == nil { return false } } else { oldAccessor, err := meta.Accessor(e.oldObj) if err != nil { utilruntime.HandleError(fmt.Errorf("cannot access oldObj: %v", err)) return false } // ignore the event if it's not updating DeletionTimestamp from non-nil to nil. if accessor.GetDeletionTimestamp() == nil || oldAccessor.GetDeletionTimestamp() != nil { return false } } finalizers := accessor.GetFinalizers() for _, finalizer := range finalizers { if finalizer == v1.FinalizerOrphan { return true } } return false }
func (r RealPodControl) createPods(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error { pod, err := GetPodFromTemplate(template, object, controllerRef) if err != nil { return err } if len(nodeName) != 0 { pod.Spec.NodeName = nodeName } if labels.Set(pod.Labels).AsSelectorPreValidated().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, v1.EventTypeWarning, FailedCreatePodReason, "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, v1.EventTypeNormal, SuccessfulCreatePodReason, "Created pod: %v", newPod.Name) } return nil }
func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selector, appendFn AppendFunc) error { if namespace == v1.NamespaceAll { for _, m := range indexer.List() { metadata, err := meta.Accessor(m) if err != nil { return err } if selector.Matches(labels.Set(metadata.GetLabels())) { appendFn(m) } } return nil } items, err := indexer.Index(NamespaceIndex, &metav1.ObjectMeta{Namespace: namespace}) if err != nil { // Ignore error; do slow search without index. glog.Warningf("can not retrieve list of objects using index : %v", err) for _, m := range indexer.List() { metadata, err := meta.Accessor(m) if err != nil { return err } if metadata.GetNamespace() == namespace && selector.Matches(labels.Set(metadata.GetLabels())) { appendFn(m) } } return nil } for _, m := range items { metadata, err := meta.Accessor(m) if err != nil { return err } if selector.Matches(labels.Set(metadata.GetLabels())) { appendFn(m) } } return 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 NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { meta, err := meta.Accessor(obj) if err != nil { return "", err } name := meta.GetName() if msgs := path.IsValidPathSegmentName(name); len(msgs) != 0 { return "", fmt.Errorf("invalid name: %v", msgs) } return prefix + "/" + meta.GetNamespace() + "/" + name, nil }
func (t *tracker) Add(obj runtime.Object) error { if meta.IsListType(obj) { return t.addList(obj, false) } objMeta, err := meta.Accessor(obj) if err != nil { return err } return t.add(obj, objMeta.GetNamespace(), false) }
// Revision returns the revision number of the input object. func Revision(obj runtime.Object) (int64, error) { acc, err := meta.Accessor(obj) if err != nil { return 0, err } v, ok := acc.GetAnnotations()[RevisionAnnotation] if !ok { return 0, nil } return strconv.ParseInt(v, 10, 64) }
func (t *Tester) createObject(ctx genericapirequest.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) }
// ObjectResourceVersion implements Versioner func (a APIObjectVersioner) ObjectResourceVersion(obj runtime.Object) (uint64, error) { accessor, err := meta.Accessor(obj) if err != nil { return 0, err } version := accessor.GetResourceVersion() if len(version) == 0 { return 0, nil } return strconv.ParseUint(version, 10, 64) }
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 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) } }
// UpdateObject implements Versioner func (a APIObjectVersioner) UpdateObject(obj runtime.Object, resourceVersion uint64) error { accessor, err := meta.Accessor(obj) if err != nil { return err } versionString := "" if resourceVersion != 0 { versionString = strconv.FormatUint(resourceVersion, 10) } accessor.SetResourceVersion(versionString) return nil }
func (t *Tester) getObject(ctx genericapirequest.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(), &metav1.GetOptions{}) if err != nil { return nil, err } return result, nil }
func (t *testRESTStrategy) PrepareForCreate(ctx genericapirequest.Context, 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 ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error { for _, m := range store.List() { metadata, err := meta.Accessor(m) if err != nil { return err } if selector.Matches(labels.Set(metadata.GetLabels())) { appendFn(m) } } return nil }
// 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 }