diff --git a/pkg/api/meta/interfaces.go b/pkg/api/meta/interfaces.go index 9674a015365..dd1dba33d0f 100644 --- a/pkg/api/meta/interfaces.go +++ b/pkg/api/meta/interfaces.go @@ -46,6 +46,10 @@ type Interface interface { SetResourceVersion(version string) SelfLink() string SetSelfLink(selfLink string) + Labels() map[string]string + SetLabels(labels map[string]string) + Annotations() map[string]string + SetAnnotations(annotations map[string]string) } // MetadataAccessor lets you work with object and list metadata from any of the versioned or @@ -73,6 +77,12 @@ type MetadataAccessor interface { SelfLink(obj runtime.Object) (string, error) SetSelfLink(obj runtime.Object, selfLink string) error + Labels(obj runtime.Object) (map[string]string, error) + SetLabels(obj runtime.Object, labels map[string]string) error + + Annotations(obj runtime.Object) (map[string]string, error) + SetAnnotations(obj runtime.Object, annotations map[string]string) error + runtime.ResourceVersioner } diff --git a/pkg/api/meta/meta.go b/pkg/api/meta/meta.go index 1ecb441f7c5..54dcf5679fc 100644 --- a/pkg/api/meta/meta.go +++ b/pkg/api/meta/meta.go @@ -185,6 +185,40 @@ func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error { return nil } +func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) { + accessor, err := Accessor(obj) + if err != nil { + return nil, err + } + return accessor.Labels(), nil +} + +func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error { + accessor, err := Accessor(obj) + if err != nil { + return err + } + accessor.SetLabels(labels) + return nil +} + +func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) { + accessor, err := Accessor(obj) + if err != nil { + return nil, err + } + return accessor.Annotations(), nil +} + +func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error { + accessor, err := Accessor(obj) + if err != nil { + return err + } + accessor.SetAnnotations(annotations) + return nil +} + func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) { accessor, err := Accessor(obj) if err != nil { @@ -212,6 +246,8 @@ type genericAccessor struct { kind *string resourceVersion *string selfLink *string + labels *map[string]string + annotations *map[string]string } func (a genericAccessor) Namespace() string { @@ -288,6 +324,28 @@ func (a genericAccessor) SetSelfLink(selfLink string) { *a.selfLink = selfLink } +func (a genericAccessor) Labels() map[string]string { + if a.labels == nil { + return nil + } + return *a.labels +} + +func (a genericAccessor) SetLabels(labels map[string]string) { + *a.labels = labels +} + +func (a genericAccessor) Annotations() map[string]string { + if a.annotations == nil { + return nil + } + return *a.annotations +} + +func (a genericAccessor) SetAnnotations(annotations map[string]string) { + *a.annotations = annotations +} + // fieldPtr puts the address of fieldName, which must be a member of v, // into dest, which must be an address of a variable to which this field's // address can be assigned. @@ -340,6 +398,12 @@ func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error { if err := fieldPtr(v, "SelfLink", &a.selfLink); err != nil { return err } + if err := fieldPtr(v, "Labels", &a.labels); err != nil { + return err + } + if err := fieldPtr(v, "Annotations", &a.annotations); err != nil { + return err + } return nil } diff --git a/pkg/api/meta/meta_test.go b/pkg/api/meta/meta_test.go index 8ed0f8a960a..18dfd50abe4 100644 --- a/pkg/api/meta/meta_test.go +++ b/pkg/api/meta/meta_test.go @@ -17,6 +17,7 @@ limitations under the License. package meta import ( + "reflect" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -25,14 +26,16 @@ import ( func TestGenericTypeMeta(t *testing.T) { type TypeMeta struct { - Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` - Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` - Name string `json:"name,omitempty" yaml:"name,omitempty"` - UID string `json:"uid,omitempty" yaml:"uid,omitempty"` - CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` - SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` - APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` + UID string `json:"uid,omitempty" yaml:"uid,omitempty"` + CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` + SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` + ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` + APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` } type Object struct { TypeMeta `json:",inline" yaml:",inline"` @@ -46,11 +49,13 @@ func TestGenericTypeMeta(t *testing.T) { Kind: "b", ResourceVersion: "1", SelfLink: "some/place/only/we/know", + Labels: map[string]string{"foo": "bar"}, + Annotations: map[string]string{"x": "y"}, }, } accessor, err := Accessor(&j) if err != nil { - t.Fatalf("new err: %v", err) + t.Fatalf("unexpected error: %v", err) } if e, a := "bar", accessor.Namespace(); e != a { t.Errorf("expected %v, got %v", e, a) @@ -107,14 +112,16 @@ func TestGenericTypeMeta(t *testing.T) { } type InternalTypeMeta struct { - Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` - Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` - Name string `json:"name,omitempty" yaml:"name,omitempty"` - UID string `json:"uid,omitempty" yaml:"uid,omitempty"` - CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` - SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` - APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` + UID string `json:"uid,omitempty" yaml:"uid,omitempty"` + CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` + SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` + ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` + APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` } type InternalObject struct { TypeMeta InternalTypeMeta `json:",inline" yaml:",inline"` @@ -132,6 +139,8 @@ func TestGenericTypeMetaAccessor(t *testing.T) { Kind: "b", ResourceVersion: "1", SelfLink: "some/place/only/we/know", + Labels: map[string]string{"foo": "bar"}, + Annotations: map[string]string{"x": "y"}, }, } accessor := NewAccessor() @@ -184,6 +193,20 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if e, a := "some/place/only/we/know", selfLink; e != a { t.Errorf("expected %v, got %v", e, a) } + labels, err := accessor.Labels(j) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if e, a := 1, len(labels); e != a { + t.Errorf("expected %v, got %v", e, a) + } + annotations, err := accessor.Annotations(j) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if e, a := 1, len(annotations); e != a { + t.Errorf("expected %v, got %v", e, a) + } if err := accessor.SetNamespace(j, "baz"); err != nil { t.Errorf("unexpected error: %v", err) @@ -206,6 +229,13 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if err := accessor.SetSelfLink(j, "google.com"); err != nil { t.Errorf("unexpected error: %v", err) } + if err := accessor.SetLabels(j, map[string]string{}); err != nil { + t.Errorf("unexpected error: %v", err) + } + var nilMap map[string]string + if err := accessor.SetAnnotations(j, nilMap); err != nil { + t.Errorf("unexpected error: %v", err) + } // Prove that accessor changes the original object. if e, a := "baz", j.TypeMeta.Namespace; e != a { @@ -229,6 +259,12 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if e, a := "google.com", j.TypeMeta.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := map[string]string{}, j.TypeMeta.Labels; !reflect.DeepEqual(e, a) { + t.Errorf("expected %#v, got %#v", e, a) + } + if e, a := nilMap, j.TypeMeta.Annotations; !reflect.DeepEqual(e, a) { + t.Errorf("expected %#v, got %#v", e, a) + } } func TestGenericObjectMeta(t *testing.T) { @@ -237,12 +273,14 @@ func TestGenericObjectMeta(t *testing.T) { APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` } type ObjectMeta struct { - Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` - Name string `json:"name,omitempty" yaml:"name,omitempty"` - UID string `json:"uid,omitempty" yaml:"uid,omitempty"` - CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` - SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` + UID string `json:"uid,omitempty" yaml:"uid,omitempty"` + CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` + SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` + ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` } type Object struct { TypeMeta `json:",inline" yaml:",inline"` @@ -259,11 +297,13 @@ func TestGenericObjectMeta(t *testing.T) { UID: "uid", ResourceVersion: "1", SelfLink: "some/place/only/we/know", + Labels: map[string]string{"foo": "bar"}, + Annotations: map[string]string{"a": "b"}, }, } accessor, err := Accessor(&j) if err != nil { - t.Fatalf("new err: %v", err) + t.Fatalf("unexpected error: %v", err) } if e, a := "bar", accessor.Namespace(); e != a { t.Errorf("expected %v, got %v", e, a) @@ -286,6 +326,12 @@ func TestGenericObjectMeta(t *testing.T) { if e, a := "some/place/only/we/know", accessor.SelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 1, len(accessor.Labels()); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 1, len(accessor.Annotations()); e != a { + t.Errorf("expected %v, got %v", e, a) + } accessor.SetNamespace("baz") accessor.SetName("bar") @@ -294,6 +340,8 @@ func TestGenericObjectMeta(t *testing.T) { accessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") + accessor.SetLabels(map[string]string{"other": "label"}) + accessor.SetAnnotations(map[string]string{"c": "d"}) // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { @@ -317,6 +365,12 @@ func TestGenericObjectMeta(t *testing.T) { 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) + } } func TestGenericListMeta(t *testing.T) { @@ -344,7 +398,7 @@ func TestGenericListMeta(t *testing.T) { } accessor, err := Accessor(&j) if err != nil { - t.Fatalf("new err: %v", err) + t.Fatalf("unexpected error: %v", err) } if e, a := "", accessor.Name(); e != a { t.Errorf("expected %v, got %v", e, a)