Skip to content

Commit

Permalink
modify client function to update both labels and annotations (#1360)
Browse files Browse the repository at this point in the history
  • Loading branch information
Liujingfang1 committed Jan 15, 2021
1 parent e3cee45 commit b2aa5c0
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 13 deletions.
41 changes: 31 additions & 10 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,22 @@ import (
"sigs.k8s.io/cli-utils/pkg/object"
)

// client is the client to update object in the API server.
type client struct {
// Client is the client to update object in the API server.
type Client struct {
client dynamic.Interface
restMapper meta.RESTMapper
}

func NewClient(d dynamic.Interface, mapper meta.RESTMapper) *client {
return &client{
// NewClient returns a client to get and update an object.
func NewClient(d dynamic.Interface, mapper meta.RESTMapper) *Client {
return &Client{
client: d,
restMapper: mapper,
}
}

// Update updates an object using dynamic client
func (uc *client) Update(ctx context.Context, meta object.ObjMetadata, obj *unstructured.Unstructured, options *metav1.UpdateOptions) error {
func (uc *Client) Update(ctx context.Context, meta object.ObjMetadata, obj *unstructured.Unstructured, options *metav1.UpdateOptions) error {
r, err := uc.resourceInterface(meta)
if err != nil {
return err
Expand All @@ -44,15 +45,15 @@ func (uc *client) Update(ctx context.Context, meta object.ObjMetadata, obj *unst
}

// Get fetches the requested object into the input obj using dynamic client
func (uc *client) Get(ctx context.Context, meta object.ObjMetadata) (*unstructured.Unstructured, error) {
func (uc *Client) Get(ctx context.Context, meta object.ObjMetadata) (*unstructured.Unstructured, error) {
r, err := uc.resourceInterface(meta)
if err != nil {
return nil, err
}
return r.Get(ctx, meta.Name, metav1.GetOptions{})
}

func (uc *client) resourceInterface(meta object.ObjMetadata) (dynamic.ResourceInterface, error) {
func (uc *Client) resourceInterface(meta object.ObjMetadata) (dynamic.ResourceInterface, error) {
mapping, err := uc.restMapper.RESTMapping(meta.GroupKind)
if err != nil {
return nil, err
Expand All @@ -73,14 +74,14 @@ func ReplaceOwningInventoryID(obj *unstructured.Unstructured, oldID, newID strin
val, found := annotations[key]
if !found || val == oldID {
annotations[key] = newID
return true, UpdateAnnotation(obj, annotations)
return true, updateAnnotations(obj, annotations)
}
return false, nil
}

// UpdateAnnotation updates .metadata.annotations field of obj to use the passed in annotations
// updateAnnotations updates .metadata.annotations field of obj to use the passed in annotations
// as well as updates the last-applied-configuration annotations.
func UpdateAnnotation(obj *unstructured.Unstructured, annotations map[string]string) error {
func updateAnnotations(obj *unstructured.Unstructured, annotations map[string]string) error {
u := getOriginalObj(obj)
if u != nil {
u.SetAnnotations(annotations)
Expand All @@ -94,6 +95,26 @@ func UpdateAnnotation(obj *unstructured.Unstructured, annotations map[string]str
return nil
}

// UpdateLabelsAndAnnotations updates .metadata.labels and .metadata.annotations fields of obj to use
// the passed in labels and annotations.
// It also updates the last-applied-configuration annotations.
func UpdateLabelsAndAnnotations(obj *unstructured.Unstructured, labels, annotations map[string]string) error {
u := getOriginalObj(obj)
if u != nil {
u.SetAnnotations(annotations)
u.SetLabels(labels)
// Since the annotation is updated, we also need to update the
// last applied configuration annotation.
err := util.CreateOrUpdateAnnotation(true, u, scheme.DefaultJSONEncoder())
obj.SetLabels(u.GetLabels())
obj.SetAnnotations(u.GetAnnotations())
return err
}
obj.SetLabels(labels)
obj.SetAnnotations(annotations)
return nil
}

func getOriginalObj(obj *unstructured.Unstructured) *unstructured.Unstructured {
annotations := obj.GetAnnotations()
lastApplied, found := annotations[v1.LastAppliedConfigAnnotation]
Expand Down
32 changes: 29 additions & 3 deletions pkg/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ func TestReplaceOwningInventoryID(t *testing.T) {
}
}

func TestUpdateAnnotation(t *testing.T) {
func TestUpdateLabelsAndAnnotations(t *testing.T) {
testcases := []struct {
name string
labels map[string]string
annotations map[string]string
}{
{
Expand All @@ -93,6 +94,19 @@ func TestUpdateAnnotation(t *testing.T) {
"random-key": "value",
},
},
{
name: "add new labels",
labels: map[string]string{
"old-key": "old-value",
"random-key": "value",
},
},
{
name: "remove existing labels",
labels: map[string]string{
"random-key": "value",
},
},
}

for _, tc := range testcases {
Expand All @@ -103,14 +117,22 @@ func TestUpdateAnnotation(t *testing.T) {
"metadata": map[string]interface{}{
"name": "deployment",
"namespace": "test",
"labels": map[string]interface{}{
"old-key": "old-value",
},
"annotations": map[string]interface{}{
"config.k8s.io/owning-inventory": "old",
},
},
},
}
uCloned := u.DeepCopy()
uCloned.SetAnnotations(tc.annotations)
if tc.annotations != nil {
uCloned.SetAnnotations(tc.annotations)
}
if tc.labels != nil {
uCloned.SetLabels(tc.labels)
}
err := util.CreateOrUpdateAnnotation(true, uCloned, scheme.DefaultJSONEncoder())
if err != nil {
t.Errorf("unexpected error %v", err)
Expand All @@ -119,7 +141,11 @@ func TestUpdateAnnotation(t *testing.T) {
if err != nil {
t.Errorf("unexpected error %v", err)
}
err = UpdateAnnotation(u, tc.annotations)
if tc.labels != nil {
err = UpdateLabelsAndAnnotations(u, tc.labels, u.GetAnnotations())
} else if tc.annotations != nil {
err = UpdateLabelsAndAnnotations(u, u.GetLabels(), tc.annotations)
}
if err != nil {
t.Errorf("unexpected error %v", err)
}
Expand Down

0 comments on commit b2aa5c0

Please sign in to comment.