Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modify client function to update both labels and annotations #1360

Merged
merged 1 commit into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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