diff --git a/pkg/kapp/diff/explicit_versioned_ref.go b/pkg/kapp/diff/explicit_versioned_ref.go new file mode 100644 index 000000000..4c15a018b --- /dev/null +++ b/pkg/kapp/diff/explicit_versioned_ref.go @@ -0,0 +1,70 @@ +// Copyright 2020 VMware, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package diff + +import ( + "fmt" +) + +type VersionedRefDesc struct { + Namespace string `json:"namespace"` + APIGroup string `json:"apiGroup"` + Kind string `json:"kind"` + Name string `json:"name"` +} + +type ExplicitVersionedRefAnn struct { + References []VersionedRefDesc `json:"references"` +} + +type ExplicitVersionedRef struct { + Resource VersionedResource + Annotation ExplicitVersionedRefAnn +} + +const ( + explicitReferenceKey = "kapp.k14s.io/versioned-explicit-ref" +) + +func NewExplicitVersionedRef(res VersionedResource, annotation ExplicitVersionedRefAnn) *ExplicitVersionedRef { + return &ExplicitVersionedRef{res, annotation} +} + +func (e *ExplicitVersionedRef) IsReferenced() bool { + refList := e.refStringList() + resRef := e.resourceRefString() + + for _, v := range refList { + if v == resRef { + return true + } + } + + return false +} + +func (e *ExplicitVersionedRef) refStringList() []string { + list := []string{} + for _, v := range e.Annotation.References { + if v.APIGroup == "core" { + v.APIGroup = "" + } + + list = append(list, fmt.Sprintf("%s/%s/%s/%s", v.Namespace, v.APIGroup, v.Kind, v.Name)) + } + return list +} + +func (e *ExplicitVersionedRef) resourceRefString() string { + return e.Resource.UniqVersionedKey().String() +} + +/* +Annotation with a list of references in JSON format: + +kapp.k14s.io/versioned-explicit-ref: '{ "references": [ { "namespace": , "apiGroup": , "kind" : , "name": } ] }' + +"namespace" need not be assigned a value for cluster-scoped resources. +"apiGroup" need not be assigned a value for resources belonging to "core" API group. +*/ diff --git a/pkg/kapp/diff/versioned_resource.go b/pkg/kapp/diff/versioned_resource.go index 2b17e3797..079422f5c 100644 --- a/pkg/kapp/diff/versioned_resource.go +++ b/pkg/kapp/diff/versioned_resource.go @@ -83,11 +83,35 @@ func (d VersionedResource) updateAffected(rule ctlconf.TemplateRule, rs []ctlres ReplacementFunc: d.buildObjRefReplacementFunc(affectedObjRef), } + resourceExplicitKey := fmt.Sprintf("%s.%s", explicitReferenceKey, ctlres.NewUniqueResourceKey(d.res).String()) + explicitReferenceMod := ctlres.StringMapAppendMod{ + ResourceMatcher: ctlres.AllMatcher{}, + Path: ctlres.NewPathFromStrings([]string{"metadata", "labels"}), + KVs: map[string]string{ + resourceExplicitKey: d.res.Name(), + }, + } + for _, res := range rs { err := mod.Apply(res) if err != nil { return err } + + if val, found := res.Annotations()[explicitReferenceKey]; found { + annotation := ExplicitVersionedRefAnn{} + err := json.Unmarshal([]byte(val), &annotation) + if err != nil { + return fmt.Errorf("Error unmarshalling explicit references : %s", err) + } + + if NewExplicitVersionedRef(d, annotation).IsReferenced() { + err = explicitReferenceMod.Apply(res) + if err != nil { + return err + } + } + } } }