Merge pull request #3956 from natasha41575/ReplacementPreviousIds

replacements should be able to use previous IDs
This commit is contained in:
Kubernetes Prow Robot
2021-06-09 10:45:26 -07:00
committed by GitHub
5 changed files with 259 additions and 81 deletions

View File

@@ -44,11 +44,17 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.T
t.FieldPaths = []string{types.DefaultReplacementFieldPath}
}
for _, n := range nodes {
id := makeResId(n)
if id.IsSelectedBy(t.Select.ResId) && !rejectId(t.Reject, id) {
err := applyToNode(n, value, t)
if err != nil {
return nil, err
ids, err := utils.MakeResIds(n)
if err != nil {
return nil, err
}
for _, id := range ids {
if id.IsSelectedBy(t.Select.ResId) && !rejectId(t.Reject, &id) {
err := applyToNode(n, value, t)
if err != nil {
return nil, err
}
break
}
}
}
@@ -152,12 +158,19 @@ func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode,
func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) {
var matches []*yaml.RNode
for _, n := range nodes {
if makeResId(n).IsSelectedBy(selector.ResId) {
if len(matches) > 0 {
return nil, fmt.Errorf(
"multiple matches for selector %s", selector)
ids, err := utils.MakeResIds(n)
if err != nil {
return nil, err
}
for _, id := range ids {
if id.IsSelectedBy(selector.ResId) {
if len(matches) > 0 {
return nil, fmt.Errorf(
"multiple matches for selector %s", selector)
}
matches = append(matches, n)
break
}
matches = append(matches, n)
}
}
if len(matches) == 0 {
@@ -165,17 +178,3 @@ func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yam
}
return matches[0], nil
}
// makeResId makes a ResId from an RNode.
func makeResId(n *yaml.RNode) *resid.ResId {
apiVersion := n.Field(yaml.APIVersionField)
var group, version string
if apiVersion != nil {
group, version = resid.ParseGroupVersion(yaml.GetValue(apiVersion.Value))
}
return &resid.ResId{
Gvk: resid.Gvk{Group: group, Version: version, Kind: n.GetKind()},
Name: n.GetName(),
Namespace: n.GetNamespace(),
}
}

View File

@@ -1478,6 +1478,54 @@ spec:
name: third
version: latest
property: third
`,
},
"using a previous ID": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: pre-deploy
annotations:
config.kubernetes.io/previousNames: deploy,deploy
config.kubernetes.io/previousKinds: CronJob,Deployment
config.kubernetes.io/previousNamespaces: default,default
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
replacements: `replacements:
- source:
kind: CronJob
name: deploy
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
name: deploy
fieldPaths:
- spec.template.spec.containers.1.image
`,
expected: `apiVersion: v1
kind: Deployment
metadata:
name: pre-deploy
annotations:
config.kubernetes.io/previousNames: deploy,deploy
config.kubernetes.io/previousKinds: CronJob,Deployment
config.kubernetes.io/previousNamespaces: default,default
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:1.7.9
name: postgresdb
`,
},
}

View File

@@ -0,0 +1,79 @@
package utils
import (
"fmt"
"strings"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
const (
BuildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds"
BuildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames"
BuildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes"
BuildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes"
BuildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces"
// the following are only for patches, to specify whether they can change names
// and kinds of their targets
BuildAnnotationAllowNameChange = konfig.ConfigAnnoDomain + "/allowNameChange"
BuildAnnotationAllowKindChange = konfig.ConfigAnnoDomain + "/allowKindChange"
Allowed = "allowed"
)
// MakeResIds returns all of an RNode's current and previous Ids
func MakeResIds(n *yaml.RNode) ([]resid.ResId, error) {
var result []resid.ResId
apiVersion := n.Field(yaml.APIVersionField)
var group, version string
if apiVersion != nil {
group, version = resid.ParseGroupVersion(yaml.GetValue(apiVersion.Value))
}
result = append(result, resid.NewResIdWithNamespace(
resid.Gvk{Group: group, Version: version, Kind: n.GetKind()}, n.GetName(), n.GetNamespace()),
)
prevIds, err := PrevIds(n)
if err != nil {
return nil, err
}
result = append(result, prevIds...)
return result, nil
}
// PrevIds returns all of an RNode's previous Ids
func PrevIds(n *yaml.RNode) ([]resid.ResId, error) {
var ids []resid.ResId
// TODO: merge previous names and namespaces into one list of
// pairs on one annotation so there is no chance of error
annotations := n.GetAnnotations()
if _, ok := annotations[BuildAnnotationPreviousNames]; !ok {
return nil, nil
}
names := strings.Split(annotations[BuildAnnotationPreviousNames], ",")
ns := strings.Split(annotations[BuildAnnotationPreviousNamespaces], ",")
kinds := strings.Split(annotations[BuildAnnotationPreviousKinds], ",")
// This should never happen
if len(names) != len(ns) || len(names) != len(kinds) {
return nil, fmt.Errorf(
"number of previous names, " +
"number of previous namespaces, " +
"number of previous kinds not equal")
}
for i := range names {
meta, err := n.GetMeta()
if err != nil {
return nil, err
}
group, version := resid.ParseGroupVersion(meta.APIVersion)
gvk := resid.Gvk{
Group: group,
Version: version,
Kind: kinds[i],
}
ids = append(ids, resid.NewResIdWithNamespace(
gvk, names[i], ns[i]))
}
return ids, nil
}

View File

@@ -261,3 +261,84 @@ spec:
name: nginx
`)
}
func TestReplacementTransformerWithOriginalName(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("base/deployments.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: target
spec:
template:
spec:
containers:
- image: nginx:oldtag
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: source
spec:
template:
spec:
containers:
- image: nginx:newtag
name: nginx
`)
th.WriteK("base", `
resources:
- deployments.yaml
`)
th.WriteK("overlay", `
namePrefix: prefix1-
resources:
- ../base
`)
th.WriteK(".", `
namePrefix: prefix2-
resources:
- overlay
replacements:
- path: replacement.yaml
`)
th.WriteF("replacement.yaml", `
source:
name: source
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
name: prefix1-target
fieldPaths:
- spec.template.spec.containers.[name=nginx].image
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: prefix2-prefix1-target
spec:
template:
spec:
containers:
- image: nginx:newtag
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prefix2-prefix1-source
spec:
template:
spec:
containers:
- image: nginx:newtag
name: nginx
`)
}

View File

@@ -4,14 +4,13 @@
package resource
import (
"errors"
"fmt"
"log"
"strings"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/resid"
@@ -28,28 +27,14 @@ type Resource struct {
refVarNames []string
}
const (
buildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds"
buildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames"
buildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes"
buildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes"
buildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces"
// the following are only for patches, to specify whether they can change names
// and kinds of their targets
buildAnnotationAllowNameChange = konfig.ConfigAnnoDomain + "/allowNameChange"
buildAnnotationAllowKindChange = konfig.ConfigAnnoDomain + "/allowKindChange"
allowed = "allowed"
)
var buildAnnotations = []string{
buildAnnotationPreviousKinds,
buildAnnotationPreviousNames,
buildAnnotationPrefixes,
buildAnnotationSuffixes,
buildAnnotationPreviousNamespaces,
buildAnnotationAllowNameChange,
buildAnnotationAllowKindChange,
var BuildAnnotations = []string{
utils.BuildAnnotationPreviousKinds,
utils.BuildAnnotationPreviousNames,
utils.BuildAnnotationPrefixes,
utils.BuildAnnotationSuffixes,
utils.BuildAnnotationPreviousNamespaces,
utils.BuildAnnotationAllowNameChange,
utils.BuildAnnotationAllowKindChange,
}
func (r *Resource) ResetRNode(incoming *Resource) {
@@ -191,12 +176,12 @@ func copyStringSlice(s []string) []string {
// Implements ResCtx AddNamePrefix
func (r *Resource) AddNamePrefix(p string) {
r.appendCsvAnnotation(buildAnnotationPrefixes, p)
r.appendCsvAnnotation(utils.BuildAnnotationPrefixes, p)
}
// Implements ResCtx AddNameSuffix
func (r *Resource) AddNameSuffix(s string) {
r.appendCsvAnnotation(buildAnnotationSuffixes, s)
r.appendCsvAnnotation(utils.BuildAnnotationSuffixes, s)
}
func (r *Resource) appendCsvAnnotation(name, value string) {
@@ -232,12 +217,12 @@ func SameEndingSubarray(shortest, longest []string) bool {
// Implements ResCtx GetNamePrefixes
func (r *Resource) GetNamePrefixes() []string {
return r.getCsvAnnotation(buildAnnotationPrefixes)
return r.getCsvAnnotation(utils.BuildAnnotationPrefixes)
}
// Implements ResCtx GetNameSuffixes
func (r *Resource) GetNameSuffixes() []string {
return r.getCsvAnnotation(buildAnnotationSuffixes)
return r.getCsvAnnotation(utils.BuildAnnotationSuffixes)
}
func (r *Resource) getCsvAnnotation(name string) []string {
@@ -263,7 +248,7 @@ func (r *Resource) RemoveBuildAnnotations() {
if len(annotations) == 0 {
return
}
for _, a := range buildAnnotations {
for _, a := range BuildAnnotations {
delete(annotations, a)
}
if err := r.SetAnnotations(annotations); err != nil {
@@ -272,16 +257,16 @@ func (r *Resource) RemoveBuildAnnotations() {
}
func (r *Resource) setPreviousId(ns string, n string, k string) *Resource {
r.appendCsvAnnotation(buildAnnotationPreviousNames, n)
r.appendCsvAnnotation(buildAnnotationPreviousNamespaces, ns)
r.appendCsvAnnotation(buildAnnotationPreviousKinds, k)
r.appendCsvAnnotation(utils.BuildAnnotationPreviousNames, n)
r.appendCsvAnnotation(utils.BuildAnnotationPreviousNamespaces, ns)
r.appendCsvAnnotation(utils.BuildAnnotationPreviousKinds, k)
return r
}
// AllowNameChange allows name changes to the resource.
func (r *Resource) AllowNameChange() {
annotations := r.GetAnnotations()
annotations[buildAnnotationAllowNameChange] = allowed
annotations[utils.BuildAnnotationAllowNameChange] = utils.Allowed
if err := r.SetAnnotations(annotations); err != nil {
panic(err)
}
@@ -289,14 +274,14 @@ func (r *Resource) AllowNameChange() {
func (r *Resource) NameChangeAllowed() bool {
annotations := r.GetAnnotations()
v, ok := annotations[buildAnnotationAllowNameChange]
return ok && v == allowed
v, ok := annotations[utils.BuildAnnotationAllowNameChange]
return ok && v == utils.Allowed
}
// AllowKindChange allows kind changes to the resource.
func (r *Resource) AllowKindChange() {
annotations := r.GetAnnotations()
annotations[buildAnnotationAllowKindChange] = allowed
annotations[utils.BuildAnnotationAllowKindChange] = utils.Allowed
if err := r.SetAnnotations(annotations); err != nil {
panic(err)
}
@@ -304,8 +289,8 @@ func (r *Resource) AllowKindChange() {
func (r *Resource) KindChangeAllowed() bool {
annotations := r.GetAnnotations()
v, ok := annotations[buildAnnotationAllowKindChange]
return ok && v == allowed
v, ok := annotations[utils.BuildAnnotationAllowKindChange]
return ok && v == utils.Allowed
}
// String returns resource as JSON.
@@ -369,26 +354,12 @@ func (r *Resource) OrgId() resid.ResId {
// The returned array does not include the resource's current
// ID. If there are no previous IDs, this will return nil.
func (r *Resource) PrevIds() []resid.ResId {
var ids []resid.ResId
// TODO: merge previous names and namespaces into one list of
// pairs on one annotation so there is no chance of error
names := r.getCsvAnnotation(buildAnnotationPreviousNames)
ns := r.getCsvAnnotation(buildAnnotationPreviousNamespaces)
kinds := r.getCsvAnnotation(buildAnnotationPreviousKinds)
if len(names) != len(ns) || len(names) != len(kinds) {
panic(errors.New(
"number of previous names, " +
"number of previous namespaces, " +
"number of previous kinds not equal"))
prevIds, err := utils.PrevIds(&r.RNode)
if err != nil {
// this should never happen
panic(err)
}
for i := range names {
k := kinds[i]
gvk := r.GetGvk()
gvk.Kind = k
ids = append(ids, resid.NewResIdWithNamespace(
gvk, names[i], ns[i]))
}
return ids
return prevIds
}
// StorePreviousId stores the resource's current ID via build annotations.