diff --git a/api/ifc/ifc.go b/api/ifc/ifc.go index 1d12b3eae..b17da2c59 100644 --- a/api/ifc/ifc.go +++ b/api/ifc/ifc.go @@ -44,8 +44,10 @@ type Kunstructured interface { // Several uses. Copy() Kunstructured - // Used by Resource.Replace, in turned used by resWrangler.AbsorbAll, - // called by runGenerators to merge maps. Hmm. + // Used by Resource.Replace, which in turn is used in many places, e.g. + // - resource.Resource.Merge + // - resWrangler.appendReplaceOrMerge (AbsorbAll) + // - api.internal.k8sdeps.transformer.patch.conflictdetector GetAnnotations() map[string]string // Used by ResAccumulator and ReplacementTransformer. @@ -63,7 +65,8 @@ type Kunstructured interface { // Used by Resource.CurId and resource factory. GetName() string - // Used by special case code used by ResMap.SubsetThatCouldBeReferencedByResource + // Used by special case code in + // ResMap.SubsetThatCouldBeReferencedByResource GetSlice(path string) ([]interface{}, error) // GetString returns the value of a string field. diff --git a/api/resid/gvk.go b/api/resid/gvk.go index d8ff6610d..4b5ab0e77 100644 --- a/api/resid/gvk.go +++ b/api/resid/gvk.go @@ -22,8 +22,15 @@ func FromKind(k string) Gvk { } } -// GvkFromString makes a Gvk with a string, -// which is constructed by String() function +// ParseGroupVersion parses a KRM metadata apiVersion field. +func ParseGroupVersion(apiVersion string) (group, version string) { + if i := strings.Index(apiVersion, "/"); i > -1 { + return apiVersion[:i], apiVersion[i+1:] + } + return "", apiVersion +} + +// GvkFromString makes a Gvk from the output of Gvk.String(). func GvkFromString(s string) Gvk { values := strings.Split(s, fieldSep) g := values[0] diff --git a/api/resid/gvk_test.go b/api/resid/gvk_test.go index 440109d9e..5ef2bf6dc 100644 --- a/api/resid/gvk_test.go +++ b/api/resid/gvk_test.go @@ -113,6 +113,30 @@ func TestString(t *testing.T) { } } +func TestParseGroupVersion(t *testing.T) { + tests := []struct { + input string + g string + v string + }{ + {input: "", g: "", v: ""}, + {input: "v1", g: "", v: "v1"}, + {input: "apps/v1", g: "apps", v: "v1"}, + {input: "/v1", g: "", v: "v1"}, + {input: "apps/", g: "apps", v: ""}, + {input: "/apps/", g: "", v: "apps/"}, + } + for _, tc := range tests { + g, v := ParseGroupVersion(tc.input) + if g != tc.g { + t.Errorf("%s: expected group '%s', got '%s'", tc.input, tc.g, g) + } + if v != tc.v { + t.Errorf("%s: expected version '%s', got '%s'", tc.input, tc.v, v) + } + } +} + func TestSelectByGVK(t *testing.T) { type testCase struct { description string diff --git a/api/resource/resource.go b/api/resource/resource.go index 109276c72..61a2aee8c 100644 --- a/api/resource/resource.go +++ b/api/resource/resource.go @@ -14,55 +14,9 @@ import ( "sigs.k8s.io/yaml" ) -// Resource is a representation of a Kubernetes Resource Model object paired -// with metadata used by kustomize. -// -// At time of writing Resource is changing from being based on an object -// sitting behind -// -// sigs.k8s.io/kustomize/api/ifc.Unstructured -// -// to being based on an instance of -// -// sigs.k8s.io/kustomize/kyaml/yaml.RNode -// -// Ultimately, use of the Resource struct in kustomize should be entirely -// replaced by instances of RNode for direct use in kyaml, with all metadata -// stored directly in the RNodes as short-lived annotations, to be deleted -// before final output as part of a final filtration step. Using annotations -// will allow pipelined KRM Config Functions to share metadata that would -// otherwise be hidden in kustomize-only structures. -// -// ifc.Unstructured is an interface hiding an instance of -// sigs.k8s.io/kustomize/api/k8sdeps/kunstruct.UnstructAdapter -// which in turn adapts an instance of -// k8s.io/apimachinery/pkg/apis/meta/v1/unstructured -// to the ifc.Unstructured interface. This latter code handles -// mutations in the old code. -// -// The rule in kustomize development has been -// api/ -// k8sdeps/ ifc/ krusty/ theRest/ -// -// 1) Depend on k8s.io/ only via sigs.k8s.io/kustomize/api/k8sdeps. -// -// 2) Instances created in k8sdeps/ can only be injected into theRest/ -// behind interfaces defined in ifc/, arranged by a small bit of code -// in krusty/. Nothing in theRest/ can import k8sdeps/. -// -// This was to allow for importing kustomize code into kubectl, which also -// depends on k8s.io/apimachinery, albeit via a strange, old arrangement -// predating Go modules. The idea was to copy the k8sdeps/ tree into kubectl -// via a large PR, and depend on the rest via vendoring (and a small copy of -// krusty/ code). Over 2019, however, kubectl underwent large code changes -// including a switch to Go modules, and an attempt to extract it from the -// k8s repo, and this made large kustomize integration PRs hard to get through -// code review. -// -// The new plan is to eliminate k8sdeps/ entirely, along with its k8s.io/ -// dependence, switch to kyaml, and thus allow kustomize to be imported into -// kubectl via normal Go module imports. -// +// Resource is a representation of a Kubernetes Resource Model (KRM) object +// paired with metadata used by kustomize. +// For more history, see sigs.k8s.io/kustomize/api/ifc.Unstructured type Resource struct { kunStr ifc.Kunstructured originalName string @@ -75,7 +29,7 @@ type Resource struct { } func (r *Resource) ResetPrimaryData(incoming *Resource) { - r.kunStr = incoming.kunStr.Copy() + r.kunStr = incoming.Copy() } func (r *Resource) GetAnnotations() map[string]string { @@ -173,7 +127,7 @@ type ResCtxMatcher func(ResCtx) bool // DeepCopy returns a new copy of resource func (r *Resource) DeepCopy() *Resource { rc := &Resource{ - kunStr: r.kunStr.Copy(), + kunStr: r.Copy(), } rc.copyOtherFields(r) return rc @@ -181,11 +135,10 @@ func (r *Resource) DeepCopy() *Resource { // Replace performs replace with other resource. func (r *Resource) Replace(other *Resource) { - r.kunStr.SetLabels(mergeStringMaps(other.kunStr.GetLabels(), r.kunStr.GetLabels())) - r.kunStr.SetAnnotations( - mergeStringMaps(other.kunStr.GetAnnotations(), r.kunStr.GetAnnotations())) - r.kunStr.SetName(other.GetName()) - r.kunStr.SetNamespace(other.GetNamespace()) + r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels())) + r.SetAnnotations(mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) + r.SetName(other.GetName()) + r.SetNamespace(other.GetNamespace()) r.copyOtherFields(other) } @@ -226,7 +179,7 @@ func (r *Resource) KunstructEqual(o *Resource) bool { // Merge performs merge with other resource. func (r *Resource) Merge(other *Resource) { r.Replace(other) - mergeConfigmap(r.kunStr.Map(), other.Map(), r.Map()) + mergeConfigmap(r.Map(), other.Map(), r.Map()) } func (r *Resource) copyRefBy() []resid.ResId { @@ -352,7 +305,7 @@ func (r *Resource) setOriginalNs(n string) *Resource { // String returns resource as JSON. func (r *Resource) String() string { - bs, err := r.kunStr.MarshalJSON() + bs, err := r.MarshalJSON() if err != nil { return "<" + err.Error() + ">" } @@ -362,7 +315,7 @@ func (r *Resource) String() string { // AsYAML returns the resource in Yaml form. // Easier to read than JSON. func (r *Resource) AsYAML() ([]byte, error) { - json, err := r.kunStr.MarshalJSON() + json, err := r.MarshalJSON() if err != nil { return nil, err } @@ -387,7 +340,7 @@ func (r *Resource) NeedHashSuffix() bool { // GetNamespace returns the namespace the resource thinks it's in. func (r *Resource) GetNamespace() string { - namespace, _ := r.kunStr.GetString("metadata.namespace") + namespace, _ := r.GetString("metadata.namespace") // if err, namespace is empty, so no need to check. return namespace } @@ -397,7 +350,7 @@ func (r *Resource) GetNamespace() string { // TODO: compute this once and save it in the resource. func (r *Resource) OrgId() resid.ResId { return resid.NewResIdWithNamespace( - r.kunStr.GetGvk(), r.GetOriginalName(), r.GetOriginalNs()) + r.GetGvk(), r.GetOriginalName(), r.GetOriginalNs()) } // CurId returns a ResId for the resource using the @@ -405,7 +358,7 @@ func (r *Resource) OrgId() resid.ResId { // This should be unique in any ResMap. func (r *Resource) CurId() resid.ResId { return resid.NewResIdWithNamespace( - r.kunStr.GetGvk(), r.kunStr.GetName(), r.GetNamespace()) + r.GetGvk(), r.GetName(), r.GetNamespace()) } // GetRefBy returns the ResIds that referred to current resource diff --git a/cmd/config/go.sum b/cmd/config/go.sum index 2eefbef24..712cb5346 100644 --- a/cmd/config/go.sum +++ b/cmd/config/go.sum @@ -615,8 +615,6 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= -sigs.k8s.io/cli-utils v0.18.0 h1:PPFUhhwKsdMiYYm1DY9lZursNWSAEj8FYgMCZKVvOkQ= -sigs.k8s.io/cli-utils v0.18.0/go.mod h1:B7KdqkSkHNIUn3cFbaR4aKUZMKtr+Benboi1w/HW/Fg= sigs.k8s.io/cli-utils v0.19.0 h1:lAoR5okhSV/dIusodaQp5VbDpHMcKnvjqKYHU+AB3a4= sigs.k8s.io/cli-utils v0.19.0/go.mod h1:B7KdqkSkHNIUn3cFbaR4aKUZMKtr+Benboi1w/HW/Fg= sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg= diff --git a/kustomize/go.sum b/kustomize/go.sum index f5b591a41..849400f19 100644 --- a/kustomize/go.sum +++ b/kustomize/go.sum @@ -742,8 +742,8 @@ modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= -sigs.k8s.io/cli-utils v0.18.0 h1:PPFUhhwKsdMiYYm1DY9lZursNWSAEj8FYgMCZKVvOkQ= -sigs.k8s.io/cli-utils v0.18.0/go.mod h1:B7KdqkSkHNIUn3cFbaR4aKUZMKtr+Benboi1w/HW/Fg= +sigs.k8s.io/cli-utils v0.19.0 h1:lAoR5okhSV/dIusodaQp5VbDpHMcKnvjqKYHU+AB3a4= +sigs.k8s.io/cli-utils v0.19.0/go.mod h1:B7KdqkSkHNIUn3cFbaR4aKUZMKtr+Benboi1w/HW/Fg= sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg= sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=