Skip to content

Commit 4f21d60

Browse files
committed
helper methods, types, and unit tests for transformer annotations
1 parent 77b1af2 commit 4f21d60

File tree

10 files changed

+428
-15
lines changed

10 files changed

+428
-15
lines changed

api/internal/target/kusttarget.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func (kt *KustTarget) accumulateFile(
497497
if err != nil {
498498
return errors.Wrapf(err, "cannot add path annotation for '%s'", path)
499499
}
500-
err = resources.AnnotateAll(utils.OriginAnnotation, originAnno)
500+
err = resources.AnnotateAll(utils.OriginAnnotationKey, originAnno)
501501
if err != nil || originAnno == "" {
502502
return errors.Wrapf(err, "cannot add path annotation for '%s'", path)
503503
}

api/internal/utils/annotations.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package utils
33
import "sigs.k8s.io/kustomize/api/konfig"
44

55
const (
6+
// build annotations
67
BuildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds"
78
BuildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames"
89
BuildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes"
@@ -17,7 +18,9 @@ const (
1718
BuildAnnotationAllowNameChange = konfig.ConfigAnnoDomain + "/allowNameChange"
1819
BuildAnnotationAllowKindChange = konfig.ConfigAnnoDomain + "/allowKindChange"
1920

20-
OriginAnnotation = "config.kubernetes.io/origin"
21+
// for keeping track of origin and transformer data
22+
OriginAnnotationKey = "config.kubernetes.io/origin"
23+
TransformerAnnotationKey = "config.kubernetes.io/transformations"
2124

2225
Enabled = "enabled"
2326
)

api/krusty/buildmetadata_test.go renamed to api/krusty/originannotation_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/stretchr/testify/assert"
1212
"sigs.k8s.io/kustomize/api/internal/utils"
1313
"sigs.k8s.io/kustomize/api/krusty"
14-
_ "sigs.k8s.io/kustomize/api/krusty"
1514
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
1615
"sigs.k8s.io/kustomize/kyaml/filesys"
1716
)

api/resmap/resmap.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ type Transformer interface {
2121
Transform(m ResMap) error
2222
}
2323

24+
// A TransformerWithProperties contains a Transformer and stores
25+
// some of its properties
26+
type TransformerWithProperties struct {
27+
Transformer
28+
Origin *resource.Origin
29+
}
30+
2431
// A Generator creates an instance of ResMap.
2532
type Generator interface {
2633
Generate() (ResMap, error)
@@ -144,10 +151,24 @@ type ResMap interface {
144151
AbsorbAll(ResMap) error
145152

146153
// AddOriginAnnotation will add the provided origin as
147-
// an annotation to all resources in the Resmap, if
154+
// an origin annotation to all resources in the ResMap, if
148155
// the origin is not nil.
149156
AddOriginAnnotation(origin *resource.Origin) error
150157

158+
// RemoveOriginAnnotation will remove the origin annotation
159+
// from all resources in the ResMap
160+
RemoveOriginAnnotations() error
161+
162+
// AddTransformerAnnotation will add the provided origin as
163+
// an origin annotation if the resource doesn't have one; a
164+
// transformer annotation otherwise; to all resources in
165+
// ResMap
166+
AddTransformerAnnotation(origin *resource.Origin) error
167+
168+
// RemoveTransformerAnnotation will remove the transformer annotation
169+
// from all resources in the ResMap
170+
RemoveTransformerAnnotations() error
171+
151172
// AnnotateAll annotates all resources in the ResMap with
152173
// the provided key value pair.
153174
AnnotateAll(key string, value string) error

api/resmap/reswrangler.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,50 @@ func (m *resWrangler) AddOriginAnnotation(origin *resource.Origin) error {
503503
return nil
504504
}
505505

506+
// RemoveOriginAnnotation implements ResMap
507+
func (m *resWrangler) RemoveOriginAnnotations() error {
508+
for _, res := range m.rList {
509+
if err := res.SetOrigin(nil); err != nil {
510+
return err
511+
}
512+
}
513+
return nil
514+
}
515+
516+
// AddTransformerAnnotation implements ResMap
517+
func (m *resWrangler) AddTransformerAnnotation(origin *resource.Origin) error {
518+
for _, res := range m.rList {
519+
or, err := res.GetOrigin()
520+
if err != nil {
521+
return err
522+
}
523+
if or == nil {
524+
// the resource does not have an origin annotation, so
525+
// we assume that the transformer generated the resource
526+
// rather than modifying it
527+
err = res.SetOrigin(origin)
528+
} else {
529+
// the resource already has an origin annotation, so we
530+
// record the provided origin as a transformation
531+
err = res.AddTransformation(origin)
532+
}
533+
if err != nil {
534+
return err
535+
}
536+
}
537+
return nil
538+
}
539+
540+
// RemoveTransformerAnnotations implements ResMap
541+
func (m *resWrangler) RemoveTransformerAnnotations() error {
542+
for _, res := range m.rList {
543+
if err := res.ClearTransformations(); err != nil {
544+
return err
545+
}
546+
}
547+
return nil
548+
}
549+
506550
func (m *resWrangler) appendReplaceOrMerge(res *resource.Resource) error {
507551
id := res.CurId()
508552
matches := m.GetMatchingResourcesByAnyId(id.Equals)

api/resmap/reswrangler_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,34 @@ import (
2626
var depProvider = provider.NewDefaultDepProvider()
2727
var rf = depProvider.GetResourceFactory()
2828
var rmF = NewFactory(rf)
29+
var origin1 = &resource.Origin{
30+
Repo: "github.com/myrepo",
31+
Ref: "master",
32+
ConfiguredIn: "config.yaml",
33+
ConfiguredBy: yaml.ResourceIdentifier{
34+
TypeMeta: yaml.TypeMeta{
35+
APIVersion: "builtin",
36+
Kind: "Generator",
37+
},
38+
NameMeta: yaml.NameMeta{
39+
Name: "my-name",
40+
Namespace: "my-namespace",
41+
},
42+
},
43+
}
44+
var origin2 = &resource.Origin{
45+
ConfiguredIn: "../base/config.yaml",
46+
ConfiguredBy: yaml.ResourceIdentifier{
47+
TypeMeta: yaml.TypeMeta{
48+
APIVersion: "builtin",
49+
Kind: "Generator",
50+
},
51+
NameMeta: yaml.NameMeta{
52+
Name: "my-name",
53+
Namespace: "my-namespace",
54+
},
55+
},
56+
}
2957

3058
func doAppend(t *testing.T, w ResMap, r *resource.Resource) {
3159
err := w.Append(r)
@@ -1527,6 +1555,67 @@ $patch: delete
15271555
}
15281556
}
15291557

1558+
func TestOriginAnnotations(t *testing.T) {
1559+
w := New()
1560+
for i := 0; i < 3; i++ {
1561+
assert.NoError(t, w.Append(makeCm(i)))
1562+
}
1563+
// this should add an origin annotation to every resource
1564+
assert.NoError(t, w.AddOriginAnnotation(origin1))
1565+
resources := w.Resources()
1566+
for _, res := range resources {
1567+
or, err := res.GetOrigin()
1568+
assert.NoError(t, err)
1569+
assert.Equal(t, origin1, or)
1570+
}
1571+
// this should not overwrite the existing origin annotations
1572+
assert.NoError(t, w.AddOriginAnnotation(origin2))
1573+
for _, res := range resources {
1574+
or, err := res.GetOrigin()
1575+
assert.NoError(t, err)
1576+
assert.Equal(t, origin1, or)
1577+
}
1578+
// this should remove origin annotations from all resources
1579+
assert.NoError(t, w.RemoveOriginAnnotations())
1580+
for _, res := range resources {
1581+
or, err := res.GetOrigin()
1582+
assert.NoError(t, err)
1583+
assert.Nil(t, or)
1584+
}
1585+
}
1586+
1587+
func TestTransformerAnnotations(t *testing.T) {
1588+
w := New()
1589+
for i := 0; i < 3; i++ {
1590+
assert.NoError(t, w.Append(makeCm(i)))
1591+
}
1592+
// this should add an origin annotation to every resource
1593+
assert.NoError(t, w.AddTransformerAnnotation(origin1))
1594+
resources := w.Resources()
1595+
for _, res := range resources {
1596+
or, err := res.GetOrigin()
1597+
assert.NoError(t, err)
1598+
assert.Equal(t, origin1, or)
1599+
}
1600+
// this should add a transformer annotation to every resource
1601+
assert.NoError(t, w.AddTransformerAnnotation(origin2))
1602+
for _, res := range resources {
1603+
or, err := res.GetOrigin()
1604+
assert.NoError(t, err)
1605+
assert.Equal(t, origin1, or)
1606+
tr, err := res.GetTransformations()
1607+
assert.NoError(t, err)
1608+
assert.Equal(t, resource.Transformations{origin2}, tr)
1609+
}
1610+
// remove transformer annotations from all resources
1611+
assert.NoError(t, w.RemoveTransformerAnnotations())
1612+
for _, res := range resources {
1613+
tr, err := res.GetTransformations()
1614+
assert.NoError(t, err)
1615+
assert.Nil(t, tr)
1616+
}
1617+
}
1618+
15301619
// baseResource produces a base object which used to test
15311620
// patch transformation
15321621
// Also the structure is matching the Deployment syntax

api/resource/origin.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,31 @@ import (
1111
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
1212
)
1313

14-
// Origin retains information about where resources in the output
15-
// of `kustomize build` originated from
14+
// Origin retains information about the origin of resources and transformer configs
15+
// that contributed to the output of `kustomize build`
1616
type Origin struct {
1717
// Path is the path to the resource. If a local resource, this path is
1818
// rooted from the directory upon which `kustomize build` was invoked. If a
1919
// remote resource, this path is rooted from the root of the remote repo.
2020
Path string `json:"path,omitempty" yaml:"path,omitempty"`
2121

22-
// Repo is the remote repository that the resource originated from if it is
22+
// Repo is the remote repository that the resource or transformer originated from if it is
2323
// not from a local file
2424
Repo string `json:"repo,omitempty" yaml:"repo,omitempty"`
2525

26-
// Ref is the ref of the remote repository that the resource originated from
26+
// Ref is the ref of the remote repository that the resource or transformer originated from
2727
// if it is not from a local file
2828
Ref string `json:"ref,omitempty" yaml:"ref,omitempty"`
2929

3030
// The following fields only apply to resources that have been
31-
// generated by fields other than the `resources` field.
31+
// generated by fields other than the `resources` field, or to transformer
32+
// configs.
3233

33-
// ConfiguredIn is the file path to the generator config that created the
34+
// ConfiguredIn is the file path to the generator or transformer config that created the
3435
// resource
3536
ConfiguredIn string `json:"configuredIn,omitempty" yaml:"configuredIn,omitempty"`
3637

37-
// ConfiguredBy is the ObjectReference of the generator config
38+
// ConfiguredBy is the ObjectReference of the generator or transformer config
3839
ConfiguredBy kyaml.ResourceIdentifier `json:"configuredBy,omitempty" yaml:"configuredBy,omitempty"`
3940
}
4041

@@ -67,6 +68,17 @@ func (origin *Origin) String() (string, error) {
6768
return string(anno), err
6869
}
6970

71+
// Transformations is a list of Origin
72+
type Transformations []*Origin
73+
74+
// String returns a string version of Transformations
75+
func (transformations *Transformations) String() (string, error) {
76+
anno, err := kyaml.Marshal(transformations)
77+
return string(anno), err
78+
}
79+
80+
// OriginFromCustomPlugin takes a custom plugin defined as a resource
81+
// and returns an origin object to describe it
7082
func OriginFromCustomPlugin(res *Resource) (*Origin, error) {
7183
origin, err := res.GetOrigin()
7284
if err != nil {

api/resource/origin_test.go

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/stretchr/testify/assert"
1010
. "sigs.k8s.io/kustomize/api/resource"
11+
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
1112
)
1213

1314
func TestOriginAppend(t *testing.T) {
@@ -78,6 +79,82 @@ repo: github.com/kubernetes-sigs/kustomize/examples/multibases/dev/
7879
for _, test := range tests {
7980
actual, err := test.in.String()
8081
assert.NoError(t, err)
81-
assert.Equal(t, actual, test.expected)
82+
assert.Equal(t, test.expected, actual)
83+
}
84+
}
85+
86+
func TestTransformationsString(t *testing.T) {
87+
origin1 := &Origin{
88+
Repo: "github.com/myrepo",
89+
Ref: "master",
90+
ConfiguredIn: "config.yaml",
91+
ConfiguredBy: kyaml.ResourceIdentifier{
92+
TypeMeta: kyaml.TypeMeta{
93+
APIVersion: "builtin",
94+
Kind: "Generator",
95+
},
96+
NameMeta: kyaml.NameMeta{
97+
Name: "my-name",
98+
Namespace: "my-namespace",
99+
},
100+
},
101+
}
102+
origin2 := &Origin{
103+
ConfiguredIn: "../base/config.yaml",
104+
ConfiguredBy: kyaml.ResourceIdentifier{
105+
TypeMeta: kyaml.TypeMeta{
106+
APIVersion: "builtin",
107+
Kind: "Generator",
108+
},
109+
NameMeta: kyaml.NameMeta{
110+
Name: "my-name",
111+
Namespace: "my-namespace",
112+
},
113+
},
114+
}
115+
tests := []struct {
116+
in Transformations
117+
expected string
118+
}{
119+
{
120+
in: Transformations{origin1},
121+
expected: `- repo: github.com/myrepo
122+
ref: master
123+
configuredIn: config.yaml
124+
configuredBy:
125+
apiVersion: builtin
126+
kind: Generator
127+
name: my-name
128+
namespace: my-namespace
129+
`,
130+
},
131+
{
132+
in: Transformations{origin1, origin2},
133+
expected: `- repo: github.com/myrepo
134+
ref: master
135+
configuredIn: config.yaml
136+
configuredBy:
137+
apiVersion: builtin
138+
kind: Generator
139+
name: my-name
140+
namespace: my-namespace
141+
- configuredIn: ../base/config.yaml
142+
configuredBy:
143+
apiVersion: builtin
144+
kind: Generator
145+
name: my-name
146+
namespace: my-namespace
147+
`,
148+
},
149+
{
150+
in: Transformations{},
151+
expected: `[]
152+
`,
153+
},
154+
}
155+
for _, test := range tests {
156+
actual, err := test.in.String()
157+
assert.NoError(t, err)
158+
assert.Equal(t, test.expected, actual)
82159
}
83160
}

0 commit comments

Comments
 (0)