Skip to content

Commit

Permalink
Added 'versioned-explicit-ref' annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
100mik committed Sep 21, 2021
1 parent 6c75699 commit 69d2f7f
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
90 changes: 90 additions & 0 deletions pkg/kapp/diff/explicit_versioned_ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// 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"`
VersionedNames map[string]string
}

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}
}

// Returns true if the
func (e *ExplicitVersionedRef) IsReferenced() (bool, error) {
references, err := e.refStringList()
if err != nil {
return false, err
}

referenceKey := e.resourceRefString()

for _, v := range references {
if v == referenceKey {
return true, nil
}
}

return false, nil
}

func (e *ExplicitVersionedRef) refStringList() ([]string, error) {
list := []string{}
for _, v := range e.Annotation.References {
v, err := e.validateAndReplaceCoreGroup(v)
if err != nil {
return list, err
}

list = append(list, fmt.Sprintf("%s/%s/%s/%s", v.Namespace, v.APIGroup, v.Kind, v.Name))
}
return list, nil
}

func (e *ExplicitVersionedRef) validateAndReplaceCoreGroup(resourceDescription VersionedRefDesc) (VersionedRefDesc, error) {
// Replacing APIGroup value "core" with an empty string
// Edgecase for resources that are a part of "core"
if resourceDescription.APIGroup == "core" {
resourceDescription.APIGroup = ""
}

if resourceDescription.Kind == "" || resourceDescription.Name == "" {
return resourceDescription, fmt.Errorf("Explicit Reference Error: Name and Kind are required values in an explicit reference")
}
return resourceDescription, nil
}

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": <resource-namespace>, "apiGroup": <resource-apiGroup>, "kind" : <resource-kind>, "name": <resource-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.
*/
42 changes: 42 additions & 0 deletions pkg/kapp/diff/versioned_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,54 @@ func (d VersionedResource) updateAffected(rule ctlconf.TemplateRule, rs []ctlres
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)
}

isTarget, err := NewExplicitVersionedRef(d, annotation).IsReferenced()
if err != nil {
return err
}

if isTarget {
if annotation.VersionedNames == nil {
annotation.VersionedNames = map[string]string{}
}

annotation.VersionedNames[d.UniqVersionedKey().String()] = d.res.Name()

out, err := json.Marshal(annotation)
if err != nil {
return fmt.Errorf("Error marshalling reference annotation: %s", err)
}

err = d.annotationMod(string(out)).Apply(res)
if err != nil {
return err
}
}
}
}
}

return nil
}

func (d VersionedResource) annotationMod(annotation string) ctlres.StringMapAppendMod {
return ctlres.StringMapAppendMod{
ResourceMatcher: ctlres.AllMatcher{},
Path: ctlres.NewPathFromStrings([]string{"metadata", "annotations"}),
KVs: map[string]string{
explicitReferenceKey: annotation,
},
}
}

func (d VersionedResource) buildObjRefReplacementFunc(
affectedObjRef ctlconf.TemplateAffectedObjRef) func(map[string]interface{}) error {

Expand Down

0 comments on commit 69d2f7f

Please sign in to comment.