diff --git a/cmd/status/util.go b/cmd/status/util.go index 894c34a..d80ea3e 100644 --- a/cmd/status/util.go +++ b/cmd/status/util.go @@ -7,7 +7,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/cli-utils/pkg/apply/prune" + "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/object" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" @@ -77,7 +77,7 @@ func isValidKubernetesResource(id yaml.ResourceIdentifier) bool { // inventory object label key. func isGroupingObject(labels map[string]string) bool { for key := range labels { - if key == prune.GroupingLabel { + if key == common.InventoryLabel { return true } } diff --git a/pkg/apply/applier_test.go b/pkg/apply/applier_test.go index 919b338..465c708 100644 --- a/pkg/apply/applier_test.go +++ b/pkg/apply/applier_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/kubectl/pkg/scheme" "sigs.k8s.io/cli-utils/pkg/apply/event" "sigs.k8s.io/cli-utils/pkg/apply/prune" + "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/kstatus/polling" pollevent "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event" "sigs.k8s.io/cli-utils/pkg/kstatus/status" @@ -297,7 +298,7 @@ var groupingObjInfo = &resource.Info{ "name": "test-grouping-obj", "namespace": namespace, "labels": map[string]interface{}{ - prune.GroupingLabel: "test-app-label", + common.InventoryLabel: "test-app-label", }, }, }, diff --git a/pkg/apply/prune/grouping.go b/pkg/apply/prune/grouping.go index 1580318..0da4dbf 100644 --- a/pkg/apply/prune/grouping.go +++ b/pkg/apply/prune/grouping.go @@ -22,17 +22,13 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/resource" + "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/object" ) -const ( - GroupingLabel = "cli-utils.sigs.k8s.io/inventory-id" - GroupingHash = "cli-utils.sigs.k8s.io/inventory-hash" -) - -// retrieveInventoryLabel returns the string value of the GroupingLabel +// retrieveInventoryLabel returns the string value of the InventoryLabel // for the passed object. Returns error if the passed object is nil or -// is not a grouping object. +// is not a inventory object. func retrieveInventoryLabel(obj runtime.Object) (string, error) { var inventoryLabel string if obj == nil { @@ -43,9 +39,9 @@ func retrieveInventoryLabel(obj runtime.Object) (string, error) { return "", err } labels := accessor.GetLabels() - inventoryLabel, exists := labels[GroupingLabel] + inventoryLabel, exists := labels[common.InventoryLabel] if !exists { - return "", fmt.Errorf("inventory label does not exist for inventory object: %s", GroupingLabel) + return "", fmt.Errorf("inventory label does not exist for inventory object: %s", common.InventoryLabel) } return strings.TrimSpace(inventoryLabel), nil } @@ -64,8 +60,8 @@ func IsInventoryObject(obj runtime.Object) bool { return false } -// FindInventoryObj returns the "Grouping" object (ConfigMap with -// grouping label) if it exists, and a boolean describing if it was found. +// FindInventoryObj returns the "Inventory" object (ConfigMap with +// inventory label) if it exists, and a boolean describing if it was found. func FindInventoryObj(infos []*resource.Info) (*resource.Info, bool) { for _, info := range infos { if info != nil && IsInventoryObject(info.Object) { @@ -143,7 +139,7 @@ func AddInventoryToGroupingObj(infos []*resource.Info) error { if annotations == nil { annotations = map[string]string{} } - annotations[GroupingHash] = invHashStr + annotations[common.InventoryHash] = invHashStr groupingObj.SetAnnotations(annotations) } return nil @@ -191,7 +187,7 @@ func CreateGroupingObj(groupingObjectTemplate *resource.Info, if annotations == nil { annotations = map[string]string{} } - annotations[GroupingHash] = invHashStr + annotations[common.InventoryHash] = invHashStr groupingObj.SetAnnotations(annotations) // Creates a new Info for the newly created grouping object. @@ -230,8 +226,8 @@ func computeInventoryHash(inventoryMap map[string]string) (string, error) { if err != nil { return "", err } - // Compute the name of the grouping object. It is the name of the - // grouping object template that it is based on with an additional + // Compute the name of the inventory object. It is the name of the + // inventory object template that it is based on with an additional // suffix which is based on the hash of the inventory. return strconv.FormatUint(uint64(invHash), 16), nil } @@ -270,13 +266,13 @@ func RetrieveInventoryFromGroupingObj(infos []*resource.Info) ([]*object.ObjMeta return inventory, nil } -// ClearInventoryObj finds the grouping object in the list of objects, -// and sets an empty inventory. Returns error if the grouping object -// is not Unstructured, the grouping object does not exist, or if -// we can't set the empty inventory on the grouping object. If successful, +// ClearInventoryObj finds the inventory object in the list of objects, +// and sets an empty inventory. Returns error if the inventory object +// is not Unstructured, the inventory object does not exist, or if +// we can't set the empty inventory on the inventory object. If successful, // returns nil. func ClearInventoryObj(infos []*resource.Info) error { - // Initially, find the grouping object ConfigMap (in Unstructured format). + // Initially, find the inventory object ConfigMap (in Unstructured format). var inventoryObj *unstructured.Unstructured for _, info := range infos { obj := info.Object @@ -284,13 +280,13 @@ func ClearInventoryObj(infos []*resource.Info) error { var ok bool inventoryObj, ok = obj.(*unstructured.Unstructured) if !ok { - return fmt.Errorf("grouping object is not an Unstructured: %#v", inventoryObj) + return fmt.Errorf("inventory object is not an Unstructured: %#v", inventoryObj) } break } } if inventoryObj == nil { - return fmt.Errorf("grouping object not found") + return fmt.Errorf("inventory object not found") } // Clears the inventory map of the ConfigMap "data" section. emptyMap := map[string]string{} @@ -306,7 +302,7 @@ func ClearInventoryObj(infos []*resource.Info) error { // calcInventoryHash returns an unsigned int32 representing the hash // of the inventory strings. If there is an error writing bytes to // the hash, then the error is returned; nil is returned otherwise. -// Used to quickly identify the set of resources in the grouping object. +// Used to quickly identify the set of resources in the inventory object. func calcInventoryHash(inv []string) (uint32, error) { h := fnv.New32a() for _, is := range inv { @@ -318,9 +314,9 @@ func calcInventoryHash(inv []string) (uint32, error) { return h.Sum32(), nil } -// retrieveInventoryHash takes a grouping object (encapsulated by +// retrieveInventoryHash takes a inventory object (encapsulated by // a resource.Info), and returns the string representing the hash -// of the grouping inventory; returns empty string if the grouping +// of the inventory set; returns empty string if the inventory // object is not in Unstructured format, or if the hash annotation // does not exist. func retrieveInventoryHash(groupingInfo *resource.Info) string { @@ -329,7 +325,7 @@ func retrieveInventoryHash(groupingInfo *resource.Info) string { if ok { annotations := groupingObj.GetAnnotations() if annotations != nil { - invHash = annotations[GroupingHash] + invHash = annotations[common.InventoryHash] } } return invHash diff --git a/pkg/apply/prune/grouping_test.go b/pkg/apply/prune/grouping_test.go index f18b361..77b0674 100644 --- a/pkg/apply/prune/grouping_test.go +++ b/pkg/apply/prune/grouping_test.go @@ -14,6 +14,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/cli-runtime/pkg/resource" + "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/object" ) @@ -23,7 +24,7 @@ var pod1Name = "pod-1" var pod2Name = "pod-2" var pod3Name = "pod-3" -var testGroupingLabel = "test-app-label" +var testInventoryLabel = "test-app-label" var groupingObj = unstructured.Unstructured{ Object: map[string]interface{}{ @@ -33,7 +34,7 @@ var groupingObj = unstructured.Unstructured{ "name": groupingObjName, "namespace": testNamespace, "labels": map[string]interface{}{ - GroupingLabel: testGroupingLabel, + common.InventoryLabel: testInventoryLabel, }, }, }, @@ -98,7 +99,7 @@ var nonUnstructuredGroupingObj = &corev1.ConfigMap{ Namespace: testNamespace, Name: groupingObjName, Labels: map[string]string{ - GroupingLabel: "true", + common.InventoryLabel: "true", }, }, } @@ -123,7 +124,7 @@ var groupingObjLabelWithSpace = unstructured.Unstructured{ "name": groupingObjName, "namespace": testNamespace, "labels": map[string]interface{}{ - GroupingLabel: "\tgrouping-label ", + common.InventoryLabel: "\tgrouping-label ", }, }, }, @@ -155,7 +156,7 @@ func TestRetrieveGroupingLabel(t *testing.T) { }, { obj: &groupingObj, - groupingLabel: testGroupingLabel, + groupingLabel: testInventoryLabel, isError: false, }, } diff --git a/pkg/apply/prune/prune.go b/pkg/apply/prune/prune.go index 00b9ed5..05179b7 100644 --- a/pkg/apply/prune/prune.go +++ b/pkg/apply/prune/prune.go @@ -23,6 +23,7 @@ import ( "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/validation" "sigs.k8s.io/cli-utils/pkg/apply/event" + "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/object" ) @@ -129,7 +130,7 @@ func (po *PruneOptions) retrievePreviousGroupingObjects(namespace string) error if err != nil { return err } - labelSelector := fmt.Sprintf("%s=%s", GroupingLabel, groupingLabel) + labelSelector := fmt.Sprintf("%s=%s", common.InventoryLabel, groupingLabel) retrievedGroupingInfos, err := po.builder. Unstructured(). // TODO: Check if this validator is necessary. diff --git a/pkg/common/common.go b/pkg/common/common.go new file mode 100644 index 0000000..74121d6 --- /dev/null +++ b/pkg/common/common.go @@ -0,0 +1,21 @@ +// Copyright 2020 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package common + +const ( + // InventoryLabel is the label stored on the ConfigMap + // inventory object. The value of the label is a unique + // identifier (by default a UUID), representing the set of + // objects applied at the same time as the inventory object. + // This inventory object is used for pruning and deletion. + InventoryLabel = "cli-utils.sigs.k8s.io/inventory-id" + // InventoryHash defines an annotation which stores the hash of + // the set of objects applied at the same time as the inventory + // object. This annotation is set on the inventory object at the + // time of the apply. The hash is computed from the sorted strings + // of the applied object's metadata (ObjMetadata). The hash is + // used as a suffix of the inventory object name. Example: + // inventory-1e5824fb + InventoryHash = "cli-utils.sigs.k8s.io/inventory-hash" +) diff --git a/pkg/common/path.go b/pkg/common/path.go index da11af9..4042a52 100644 --- a/pkg/common/path.go +++ b/pkg/common/path.go @@ -9,7 +9,6 @@ import ( "path/filepath" "k8s.io/cli-runtime/pkg/genericclioptions" - "sigs.k8s.io/cli-utils/pkg/apply/prune" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/kio/kioutil" ) @@ -87,7 +86,7 @@ func expandDir(dir string) ([]string, error) { } // If object has inventory label, skip it. labels := meta.Labels - if _, exists := labels[prune.GroupingLabel]; exists { + if _, exists := labels[InventoryLabel]; exists { continue } path := meta.Annotations[kioutil.PathAnnotation]