func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, kind string) (string, []byte) { originalMeta, err := api.ObjectMetaFor(originalObj) if err != nil { t.Fatal(err) } originalMeta.Labels["DELETE_ME"] = "DELETE_ME" original, err := json.Marshal(originalObj) if err != nil { t.Fatal(err) } currentMeta, err := api.ObjectMetaFor(currentObj) if err != nil { t.Fatal(err) } if currentMeta.Annotations == nil { currentMeta.Annotations = map[string]string{} } currentMeta.Annotations[kubectl.LastAppliedConfigAnnotation] = string(original) current, err := json.Marshal(currentObj) if err != nil { t.Fatal(err) } return currentMeta.Name, current }
// TODO: add other common fields that require global validation. func validateCommonFields(obj, old runtime.Object) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return append(allErrs, errors.NewInternalError(err)) } oldObjectMeta, err := api.ObjectMetaFor(old) if err != nil { return append(allErrs, errors.NewInternalError(err)) } allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta)...) return allErrs }
func (t *Tester) getObjectMetaOrFail(obj runtime.Object) *api.ObjectMeta { meta, err := api.ObjectMetaFor(obj) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj) } return meta }
func (t *Tester) getObject(ctx api.Context, obj runtime.Object) (runtime.Object, error) { meta, err := api.ObjectMetaFor(obj) if err != nil { return nil, err } key, err := t.storage.KeyFunc(ctx, meta.Name) if err != nil { return nil, err } key = etcdtest.AddPrefix(key) resp, err := t.fakeClient.Get(key, false, false) if err != nil { return nil, err } result := t.storage.NewFunc() codec, err := getCodec(obj) if err != nil { return nil, err } if err := codec.DecodeInto([]byte(resp.Node.Value), result); err != nil { return nil, err } return result, nil }
func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, labels map[string]string, remove []string) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } if !overwrite { if err := validateNoOverwrites(meta, labels); err != nil { return err } } if meta.Labels == nil { meta.Labels = make(map[string]string) } for key, value := range labels { meta.Labels[key] = value } for _, label := range remove { delete(meta.Labels, label) } if len(resourceVersion) != 0 { meta.ResourceVersion = resourceVersion } return nil }
// updateAnnotations updates annotations of obj func (o AnnotateOptions) updateAnnotations(obj runtime.Object) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } if !o.overwrite { if err := validateNoAnnotationOverwrites(meta, o.newAnnotations); err != nil { return err } } if meta.Annotations == nil { meta.Annotations = make(map[string]string) } for key, value := range o.newAnnotations { meta.Annotations[key] = value } for _, annotation := range o.removeAnnotations { delete(meta.Annotations, annotation) } if len(o.resourceVersion) != 0 { meta.ResourceVersion = o.resourceVersion } return nil }
// ObjectReaction returns a ReactionFunc that takes a generic action string of the form // <verb>-<resource> or <verb>-<subresource>-<resource> and attempts to return a runtime // Object or error that matches the requested action. For instance, list-replicationControllers // should attempt to return a list of replication controllers. This method delegates to the // ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items. // TODO: add support for sub resources func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { _, kind, err := mapper.VersionAndKindForResource(action.GetResource()) if err != nil { return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) } // TODO: have mapper return a Kind for a subresource? switch castAction := action.(type) { case ListAction: resource, err := o.Kind(kind+"List", "") return true, resource, err case GetAction: resource, err := o.Kind(kind, castAction.GetName()) return true, resource, err case DeleteAction: resource, err := o.Kind(kind, castAction.GetName()) return true, resource, err case CreateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { return true, nil, err } resource, err := o.Kind(kind, meta.Name) return true, resource, err case UpdateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { return true, nil, err } resource, err := o.Kind(kind, meta.Name) return true, resource, err default: return false, nil, fmt.Errorf("no reaction implemented for %s", action) } return true, nil, nil } }
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error. func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, string, error) { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return nil, "", errors.NewInternalError(err) } _, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return nil, "", errors.NewInternalError(err) } return objectMeta, kind, nil }
// ObjectResourceVersion implements Versioner func (a APIObjectVersioner) ObjectResourceVersion(obj runtime.Object) (uint64, error) { meta, err := api.ObjectMetaFor(obj) if err != nil { return 0, err } version := meta.ResourceVersion if len(version) == 0 { return 0, nil } return strconv.ParseUint(version, 10, 64) }
func (t *Tester) TestDeleteInvokesValidation(invalid ...runtime.Object) { for i, obj := range invalid { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj) } ctx := t.TestContext() _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil) if !errors.IsInvalid(err) { t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err) } } }
func (t *Tester) TestCreateDiscardsObjectNamespace(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } // Ignore non-empty namespace in object meta objectMeta.Namespace = "not-default" // Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted created, err := t.storage.(rest.Creater).Create(t.TestContext(), copyOrDie(valid)) if err != nil { t.Fatalf("Unexpected error: %v", err) } createdObjectMeta, err := api.ObjectMetaFor(created) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, created) } if createdObjectMeta.Namespace != api.NamespaceNone { t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace) } }
func (t *Tester) TestDeleteNonExist(createFn func() runtime.Object) { existing := createFn() objectMeta, err := api.ObjectMetaFor(existing) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) } context := t.TestContext() t.withStorageError(&etcd.EtcdError{ErrorCode: tools.EtcdErrorCodeNotFound}, func() { _, err := t.storage.(rest.GracefulDeleter).Delete(context, objectMeta.Name, nil) if err == nil || !errors.IsNotFound(err) { t.Fatalf("Unexpected error: %v", err) } }) }
func (t *Tester) TestCreateRejectsMismatchedNamespace(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } objectMeta.Namespace = "not-default" _, err = t.storage.(rest.Creater).Create(t.TestContext(), valid) if err == nil { t.Errorf("Expected an error, but we didn't get one") } else if !strings.Contains(err.Error(), "does not match the namespace sent on the request") { t.Errorf("Expected 'does not match the namespace sent on the request' error, got '%v'", err.Error()) } }
func (t *Tester) TestCreateGeneratesNameReturnsServerTimeout(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } objectMeta.Name = "" objectMeta.GenerateName = "test-" t.withStorageError(errors.NewAlreadyExists("kind", "thing"), func() { _, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) if err == nil || !errors.IsServerTimeout(err) { t.Fatalf("Unexpected error: %v", err) } }) }
func (t *Tester) TestDeleteGracefulUsesZeroOnNil(existing runtime.Object, expectedGrace int64) { objectMeta, err := api.ObjectMetaFor(existing) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) } ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil) if err != nil { t.Errorf("unexpected error: %v", err) } if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) { t.Errorf("unexpected error, object should exist: %v", err) } }
// UpdateObject implements Versioner func (a APIObjectVersioner) UpdateObject(obj runtime.Object, expiration *time.Time, resourceVersion uint64) error { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return err } if expiration != nil { objectMeta.DeletionTimestamp = &unversioned.Time{Time: *expiration} } versionString := "" if resourceVersion != 0 { versionString = strconv.FormatUint(resourceVersion, 10) } objectMeta.ResourceVersion = versionString return nil }
func (t *Tester) TestCreateGeneratesName(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } objectMeta.Name = "" objectMeta.GenerateName = "test-" _, err = t.storage.(rest.Creater).Create(t.TestContext(), valid) if err != nil { t.Fatalf("Unexpected error: %v", err) } if objectMeta.Name == "test-" || !strings.HasPrefix(objectMeta.Name, "test-") { t.Errorf("unexpected name: %#v", valid) } }
func (t *Tester) setObject(ctx api.Context, obj runtime.Object) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } key, err := t.storage.KeyFunc(ctx, meta.Name) if err != nil { return err } key = etcdtest.AddPrefix(key) codec, err := getCodec(obj) if err != nil { return err } _, err = t.fakeClient.Set(key, runtime.EncodeOrDie(codec, obj), 0) return err }
func (t *Tester) TestDeleteNoGraceful(createFn func() runtime.Object, wasGracefulFn func() bool) { existing := createFn() objectMeta, err := api.ObjectMetaFor(existing) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) } ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10)) if err != nil { t.Errorf("unexpected error: %v", err) } if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) { t.Errorf("unexpected error, object should not exist: %v", err) } if wasGracefulFn() { t.Errorf("resource should not support graceful delete") } }
func (t *Tester) TestDeleteGracefulHasDefault(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) { objectMeta, err := api.ObjectMetaFor(existing) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) } ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, &api.DeleteOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); err != nil { t.Errorf("unexpected error, object should exist: %v", err) } if !wasGracefulFn() { t.Errorf("did not gracefully delete resource") } }
func extractKindName(a Attributes) (name, kind string, err error) { name = "Unknown" kind = a.GetKind() obj := a.GetObject() if obj != nil { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return "", "", err } // this is necessary because name object name generation has not occurred yet if len(objectMeta.Name) > 0 { name = objectMeta.Name } else if len(objectMeta.GenerateName) > 0 { name = objectMeta.GenerateName } } return name, kind, nil }
func (t *Tester) TestCreateHasMetadata(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } objectMeta.Name = "" objectMeta.GenerateName = "test-" objectMeta.Namespace = t.TestNamespace() obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) if err != nil { t.Fatalf("Unexpected error: %v", err) } if obj == nil { t.Fatalf("Unexpected object from result: %#v", obj) } if !api.HasObjectMetaSystemFieldValues(objectMeta) { t.Errorf("storage did not populate object meta field values") } }
func (t *Tester) TestCreateResetsUserData(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } now := util.Now() objectMeta.UID = "bad-uid" objectMeta.CreationTimestamp = now obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) if err != nil { t.Fatalf("Unexpected error: %v", err) } if obj == nil { t.Fatalf("Unexpected object from result: %#v", obj) } if objectMeta.UID == "bad-uid" || objectMeta.CreationTimestamp == now { t.Errorf("ObjectMeta did not reset basic fields: %#v", objectMeta) } }
func (r RealPodControl) createPods(nodeName, namespace string, template *api.PodTemplateSpec, object runtime.Object) error { desiredLabels := getPodsLabelSet(template) desiredAnnotations, err := getPodsAnnotationSet(template, object) if err != nil { return err } meta, err := api.ObjectMetaFor(object) if err != nil { return fmt.Errorf("object does not have ObjectMeta, %v", err) } prefix := getPodsPrefix(meta.Name) pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Labels: desiredLabels, Annotations: desiredAnnotations, GenerateName: prefix, }, } if err := api.Scheme.Convert(&template.Spec, &pod.Spec); err != nil { return fmt.Errorf("unable to convert pod template: %v", 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.Pods(namespace).Create(pod); err != nil { r.Recorder.Eventf(object, "FailedCreate", "Error creating: %v", err) return fmt.Errorf("unable to create pods: %v", err) } else { glog.V(4).Infof("Controller %v created pod %v", meta.Name, newPod.Name) r.Recorder.Eventf(object, "SuccessfulCreate", "Created pod: %v", newPod.Name) } return nil }
// Change records the given event (setting the object's resource version) and // sends a watch event with the specified probability. func (f *FakeControllerSource) Change(e watch.Event, watchProbability float64) { f.lock.Lock() defer f.lock.Unlock() objMeta, err := api.ObjectMetaFor(e.Object) if err != nil { panic(err) // this is test code only } resourceVersion := len(f.changes) objMeta.ResourceVersion = strconv.Itoa(resourceVersion) f.changes = append(f.changes, e) key := f.key(objMeta) switch e.Type { case watch.Added, watch.Modified: f.items[key] = e.Object case watch.Deleted: delete(f.items, key) } if rand.Float64() < watchProbability { f.broadcaster.Action(e.Type, e.Object) } }