Upgrade k8s package verison (#5358)

* upgrade k8s package version

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

* Script upgrade and code formatting.

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-11-15 14:56:38 +08:00
committed by GitHub
parent 5f91c1663a
commit 44167aa47a
3106 changed files with 321340 additions and 172080 deletions

View File

@@ -7,13 +7,13 @@ import (
"encoding/json"
"strings"
"github.com/go-openapi/spec"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"k8s.io/kube-openapi/pkg/validation/spec"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/yaml"
)
@@ -178,9 +178,12 @@ func loadCrdIntoConfig(
}
}
if property.Ref.GetURL() != nil {
loadCrdIntoConfig(
err = loadCrdIntoConfig(
theConfig, theGvk, theMap,
property.Ref.String(), append(path, propName))
if err != nil {
return
}
}
}
return nil

View File

@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/kyaml/resid"
)
type nameReferenceTransformer struct {
@@ -51,7 +52,10 @@ func (t *nameReferenceTransformer) Transform(m resmap.ResMap) error {
fMap := t.determineFilters(m.Resources())
debug(fMap)
for r, fList := range fMap {
c := m.SubsetThatCouldBeReferencedByResource(r)
c, err := m.SubsetThatCouldBeReferencedByResource(r)
if err != nil {
return err
}
for _, f := range fList {
f.Referrer = r
f.ReferralCandidates = c
@@ -109,11 +113,17 @@ func debug(fMap filterMap) {
// 'spec/scaleTargetRef/name' field. Return a filter that can do that.
func (t *nameReferenceTransformer) determineFilters(
resources []*resource.Resource) (fMap filterMap) {
// We cache the resource OrgId values because they don't change and otherwise are very visible in a memory pprof
resourceOrgIds := make([]resid.ResId, len(resources))
for i, resource := range resources {
resourceOrgIds[i] = resource.OrgId()
}
fMap = make(filterMap)
for _, backReference := range t.backRefs {
for _, referrerSpec := range backReference.Referrers {
for _, res := range resources {
if res.OrgId().IsSelected(&referrerSpec.Gvk) {
for i, res := range resources {
if resourceOrgIds[i].IsSelected(&referrerSpec.Gvk) {
// If this is true, the res might be a referrer, and if
// so, the name reference it holds might need an update.
if resHasField(res, referrerSpec.Path) {

View File

@@ -9,9 +9,9 @@ import (
"strings"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
)
// ResAccumulator accumulates resources and the rules
@@ -72,7 +72,7 @@ func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
for _, v := range incoming {
targetId := resid.NewResIdWithNamespace(v.ObjRef.GVK(), v.ObjRef.Name, v.ObjRef.Namespace)
idMatcher := targetId.GvknEquals
if targetId.Namespace != "" || !targetId.IsNamespaceableKind() {
if targetId.Namespace != "" || targetId.IsClusterScoped() {
// Preserve backward compatibility. An empty namespace means
// wildcard search on the namespace hence we still use GvknEquals
idMatcher = targetId.Equals
@@ -167,3 +167,23 @@ func (ra *ResAccumulator) FixBackReferences() (err error) {
return ra.Transform(
newNameReferenceTransformer(ra.tConfig.NameReference))
}
// Intersection drops the resources which "other" does not have.
func (ra *ResAccumulator) Intersection(other resmap.ResMap) error {
for _, curId := range ra.resMap.AllIds() {
toDelete := true
for _, otherId := range other.AllIds() {
if otherId == curId {
toDelete = false
break
}
}
if toDelete {
err := ra.resMap.Remove(curId)
if err != nil {
return err
}
}
}
return nil
}

View File

@@ -0,0 +1,38 @@
// Code generated by pluginator on AnnotationsTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sigs.k8s.io/kustomize/api/filters/annotations"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
// Add the given annotations to the given field specifications.
type AnnotationsTransformerPlugin struct {
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
func (p *AnnotationsTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Annotations = nil
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
}
func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
if len(p.Annotations) == 0 {
return nil
}
return m.ApplyFilter(annotations.Filter{
Annotations: p.Annotations,
FsSlice: p.FieldSpecs,
})
}
func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin {
return &AnnotationsTransformerPlugin{}
}

View File

@@ -0,0 +1,39 @@
// Code generated by pluginator on ConfigMapGenerator; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
type ConfigMapGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
types.ConfigMapArgs
}
func (p *ConfigMapGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.ConfigMapArgs = types.ConfigMapArgs{}
err = yaml.Unmarshal(config, p)
if p.ConfigMapArgs.Name == "" {
p.ConfigMapArgs.Name = p.Name
}
if p.ConfigMapArgs.Namespace == "" {
p.ConfigMapArgs.Namespace = p.Namespace
}
p.h = h
return
}
func (p *ConfigMapGeneratorPlugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromConfigMapArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.ConfigMapArgs)
}
func NewConfigMapGeneratorPlugin() resmap.GeneratorPlugin {
return &ConfigMapGeneratorPlugin{}
}

View File

@@ -0,0 +1,40 @@
// Code generated by pluginator on HashTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/resmap"
)
type HashTransformerPlugin struct {
hasher ifc.KustHasher
}
func (p *HashTransformerPlugin) Config(
h *resmap.PluginHelpers, _ []byte) (err error) {
p.hasher = h.ResmapFactory().RF().Hasher()
return nil
}
// Transform appends hash to generated resources.
func (p *HashTransformerPlugin) Transform(m resmap.ResMap) error {
for _, res := range m.Resources() {
if res.NeedHashSuffix() {
h, err := res.Hash(p.hasher)
if err != nil {
return err
}
res.StorePreviousId()
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
}
}
return nil
}
func NewHashTransformerPlugin() resmap.TransformerPlugin {
return &HashTransformerPlugin{}
}

View File

@@ -0,0 +1,339 @@
// Code generated by pluginator on HelmChartInflationGenerator; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/imdario/mergo"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
// HelmChartInflationGeneratorPlugin is a plugin to generate resources
// from a remote or local helm chart.
type HelmChartInflationGeneratorPlugin struct {
h *resmap.PluginHelpers
types.HelmGlobals
types.HelmChart
tmpDir string
}
var KustomizePlugin HelmChartInflationGeneratorPlugin
const (
valuesMergeOptionMerge = "merge"
valuesMergeOptionOverride = "override"
valuesMergeOptionReplace = "replace"
)
var legalMergeOptions = []string{
valuesMergeOptionMerge,
valuesMergeOptionOverride,
valuesMergeOptionReplace,
}
// Config uses the input plugin configurations `config` to setup the generator
// options
func (p *HelmChartInflationGeneratorPlugin) Config(
h *resmap.PluginHelpers, config []byte) (err error) {
if h.GeneralConfig() == nil {
return fmt.Errorf("unable to access general config")
}
if !h.GeneralConfig().HelmConfig.Enabled {
return fmt.Errorf("must specify --enable-helm")
}
if h.GeneralConfig().HelmConfig.Command == "" {
return fmt.Errorf("must specify --helm-command")
}
p.h = h
if err = yaml.Unmarshal(config, p); err != nil {
return
}
return p.validateArgs()
}
// This uses the real file system since tmpDir may be used
// by the helm subprocess. Cannot use a chroot jail or fake
// filesystem since we allow the user to use previously
// downloaded charts. This is safe since this plugin is
// owned by kustomize.
func (p *HelmChartInflationGeneratorPlugin) establishTmpDir() (err error) {
if p.tmpDir != "" {
// already done.
return nil
}
p.tmpDir, err = ioutil.TempDir("", "kustomize-helm-")
return err
}
func (p *HelmChartInflationGeneratorPlugin) validateArgs() (err error) {
if p.Name == "" {
return fmt.Errorf("chart name cannot be empty")
}
// ChartHome might be consulted by the plugin (to read
// values files below it), so it must be located under
// the loader root (unless root restrictions are
// disabled, in which case this can be an absolute path).
if p.ChartHome == "" {
p.ChartHome = "charts"
}
// The ValuesFile may be consulted by the plugin, so it must
// be under the loader root (unless root restrictions are
// disabled).
if p.ValuesFile == "" {
p.ValuesFile = filepath.Join(p.ChartHome, p.Name, "values.yaml")
}
if err = p.errIfIllegalValuesMerge(); err != nil {
return err
}
// ConfigHome is not loaded by the plugin, and can be located anywhere.
if p.ConfigHome == "" {
if err = p.establishTmpDir(); err != nil {
return errors.Wrap(
err, "unable to create tmp dir for HELM_CONFIG_HOME")
}
p.ConfigHome = filepath.Join(p.tmpDir, "helm")
}
return nil
}
func (p *HelmChartInflationGeneratorPlugin) errIfIllegalValuesMerge() error {
if p.ValuesMerge == "" {
// Use the default.
p.ValuesMerge = valuesMergeOptionOverride
return nil
}
for _, opt := range legalMergeOptions {
if p.ValuesMerge == opt {
return nil
}
}
return fmt.Errorf("valuesMerge must be one of %v", legalMergeOptions)
}
func (p *HelmChartInflationGeneratorPlugin) absChartHome() string {
if filepath.IsAbs(p.ChartHome) {
return p.ChartHome
}
return filepath.Join(p.h.Loader().Root(), p.ChartHome)
}
func (p *HelmChartInflationGeneratorPlugin) runHelmCommand(
args []string) ([]byte, error) {
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
cmd := exec.Command(p.h.GeneralConfig().HelmConfig.Command, args...)
cmd.Stdout = stdout
cmd.Stderr = stderr
env := []string{
fmt.Sprintf("HELM_CONFIG_HOME=%s", p.ConfigHome),
fmt.Sprintf("HELM_CACHE_HOME=%s/.cache", p.ConfigHome),
fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.ConfigHome)}
cmd.Env = append(os.Environ(), env...)
err := cmd.Run()
if err != nil {
helm := p.h.GeneralConfig().HelmConfig.Command
err = errors.Wrap(
fmt.Errorf(
"unable to run: '%s %s' with env=%s (is '%s' installed?)",
helm, strings.Join(args, " "), env, helm),
stderr.String(),
)
}
return stdout.Bytes(), err
}
// createNewMergedValuesFile replaces/merges original values file with ValuesInline.
func (p *HelmChartInflationGeneratorPlugin) createNewMergedValuesFile() (
path string, err error) {
if p.ValuesMerge == valuesMergeOptionMerge ||
p.ValuesMerge == valuesMergeOptionOverride {
if err = p.replaceValuesInline(); err != nil {
return "", err
}
}
var b []byte
b, err = yaml.Marshal(p.ValuesInline)
if err != nil {
return "", err
}
return p.writeValuesBytes(b)
}
func (p *HelmChartInflationGeneratorPlugin) replaceValuesInline() error {
pValues, err := p.h.Loader().Load(p.ValuesFile)
if err != nil {
return err
}
chValues := make(map[string]interface{})
if err = yaml.Unmarshal(pValues, &chValues); err != nil {
return err
}
switch p.ValuesMerge {
case valuesMergeOptionOverride:
err = mergo.Merge(
&chValues, p.ValuesInline, mergo.WithOverride)
case valuesMergeOptionMerge:
err = mergo.Merge(&chValues, p.ValuesInline)
}
p.ValuesInline = chValues
return err
}
// copyValuesFile to avoid branching. TODO: get rid of this.
func (p *HelmChartInflationGeneratorPlugin) copyValuesFile() (string, error) {
b, err := p.h.Loader().Load(p.ValuesFile)
if err != nil {
return "", err
}
return p.writeValuesBytes(b)
}
// Write a absolute path file in the tmp file system.
func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(
b []byte) (string, error) {
if err := p.establishTmpDir(); err != nil {
return "", fmt.Errorf("cannot create tmp dir to write helm values")
}
path := filepath.Join(p.tmpDir, p.Name+"-kustomize-values.yaml")
return path, ioutil.WriteFile(path, b, 0644)
}
func (p *HelmChartInflationGeneratorPlugin) cleanup() {
if p.tmpDir != "" {
os.RemoveAll(p.tmpDir)
}
}
// Generate implements generator
func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err error) {
defer p.cleanup()
if err = p.checkHelmVersion(); err != nil {
return nil, err
}
if path, exists := p.chartExistsLocally(); !exists {
if p.Repo == "" {
return nil, fmt.Errorf(
"no repo specified for pull, no chart found at '%s'", path)
}
if _, err := p.runHelmCommand(p.pullCommand()); err != nil {
return nil, err
}
}
if len(p.ValuesInline) > 0 {
p.ValuesFile, err = p.createNewMergedValuesFile()
} else {
p.ValuesFile, err = p.copyValuesFile()
}
if err != nil {
return nil, err
}
var stdout []byte
stdout, err = p.runHelmCommand(p.templateCommand())
if err != nil {
return nil, err
}
rm, err = p.h.ResmapFactory().NewResMapFromBytes(stdout)
if err == nil {
return rm, nil
}
// try to remove the contents before first "---" because
// helm may produce messages to stdout before it
stdoutStr := string(stdout)
if idx := strings.Index(stdoutStr, "---"); idx != -1 {
return p.h.ResmapFactory().NewResMapFromBytes([]byte(stdoutStr[idx:]))
}
return nil, err
}
func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
args := []string{"template"}
if p.ReleaseName != "" {
args = append(args, p.ReleaseName)
}
if p.Namespace != "" {
args = append(args, "--namespace", p.Namespace)
}
args = append(args, filepath.Join(p.absChartHome(), p.Name))
if p.ValuesFile != "" {
args = append(args, "--values", p.ValuesFile)
}
if p.ReleaseName == "" {
// AFAICT, this doesn't work as intended due to a bug in helm.
// See https://github.com/helm/helm/issues/6019
// I've tried placing the flag before and after the name argument.
args = append(args, "--generate-name")
}
if p.IncludeCRDs {
args = append(args, "--include-crds")
}
return args
}
func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string {
args := []string{
"pull",
"--untar",
"--untardir", p.absChartHome(),
"--repo", p.Repo,
p.Name}
if p.Version != "" {
args = append(args, "--version", p.Version)
}
return args
}
// chartExistsLocally will return true if the chart does exist in
// local chart home.
func (p *HelmChartInflationGeneratorPlugin) chartExistsLocally() (string, bool) {
path := filepath.Join(p.absChartHome(), p.Name)
s, err := os.Stat(path)
if err != nil {
return "", false
}
return path, s.IsDir()
}
// checkHelmVersion will return an error if the helm version is not V3
func (p *HelmChartInflationGeneratorPlugin) checkHelmVersion() error {
stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"})
if err != nil {
return err
}
r, err := regexp.Compile(`v?\d+(\.\d+)+`)
if err != nil {
return err
}
v := r.FindString(string(stdout))
if v == "" {
return fmt.Errorf("cannot find version string in %s", string(stdout))
}
if v[0] == 'v' {
v = v[1:]
}
majorVersion := strings.Split(v, ".")[0]
if majorVersion != "3" {
return fmt.Errorf("this plugin requires helm V3 but got v%s", v)
}
return nil
}
func NewHelmChartInflationGeneratorPlugin() resmap.GeneratorPlugin {
return &HelmChartInflationGeneratorPlugin{}
}

View File

@@ -0,0 +1,33 @@
// Code generated by pluginator on IAMPolicyGenerator; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sigs.k8s.io/kustomize/api/filters/iampolicygenerator"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
type IAMPolicyGeneratorPlugin struct {
types.IAMPolicyGeneratorArgs
}
func (p *IAMPolicyGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.IAMPolicyGeneratorArgs = types.IAMPolicyGeneratorArgs{}
err = yaml.Unmarshal(config, p)
return
}
func (p *IAMPolicyGeneratorPlugin) Generate() (resmap.ResMap, error) {
r := resmap.New()
err := r.ApplyFilter(iampolicygenerator.Filter{
IAMPolicyGenerator: p.IAMPolicyGeneratorArgs,
})
return r, err
}
func NewIAMPolicyGeneratorPlugin() resmap.GeneratorPlugin {
return &IAMPolicyGeneratorPlugin{}
}

View File

@@ -0,0 +1,41 @@
// Code generated by pluginator on ImageTagTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sigs.k8s.io/kustomize/api/filters/imagetag"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
// Find matching image declarations and replace
// the name, tag and/or digest.
type ImageTagTransformerPlugin struct {
ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
func (p *ImageTagTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.ImageTag = types.Image{}
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
}
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
if err := m.ApplyFilter(imagetag.LegacyFilter{
ImageTag: p.ImageTag,
}); err != nil {
return err
}
return m.ApplyFilter(imagetag.Filter{
ImageTag: p.ImageTag,
FsSlice: p.FieldSpecs,
})
}
func NewImageTagTransformerPlugin() resmap.TransformerPlugin {
return &ImageTagTransformerPlugin{}
}

View File

@@ -0,0 +1,38 @@
// Code generated by pluginator on LabelTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sigs.k8s.io/kustomize/api/filters/labels"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
// Add the given labels to the given field specifications.
type LabelTransformerPlugin struct {
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
func (p *LabelTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Labels = nil
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
}
func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error {
if len(p.Labels) == 0 {
return nil
}
return m.ApplyFilter(labels.Filter{
Labels: p.Labels,
FsSlice: p.FieldSpecs,
})
}
func NewLabelTransformerPlugin() resmap.TransformerPlugin {
return &LabelTransformerPlugin{}
}

View File

@@ -0,0 +1,46 @@
// Code generated by pluginator on LegacyOrderTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sort"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
)
// Sort the resources using an ordering defined in the Gvk class.
// This puts cluster-wide basic resources with no
// dependencies (like Namespace, StorageClass, etc.)
// first, and resources with a high number of dependencies
// (like ValidatingWebhookConfiguration) last.
type LegacyOrderTransformerPlugin struct{}
// Nothing needed for configuration.
func (p *LegacyOrderTransformerPlugin) Config(
_ *resmap.PluginHelpers, _ []byte) (err error) {
return nil
}
func (p *LegacyOrderTransformerPlugin) Transform(m resmap.ResMap) (err error) {
resources := make([]*resource.Resource, m.Size())
ids := m.AllIds()
sort.Sort(resmap.IdSlice(ids))
for i, id := range ids {
resources[i], err = m.GetByCurrentId(id)
if err != nil {
return errors.Wrap(err, "expected match for sorting")
}
}
m.Clear()
for _, r := range resources {
m.Append(r)
}
return nil
}
func NewLegacyOrderTransformerPlugin() resmap.TransformerPlugin {
return &LegacyOrderTransformerPlugin{}
}

View File

@@ -0,0 +1,74 @@
// Code generated by pluginator on NamespaceTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/yaml"
)
// Change or set the namespace of non-cluster level resources.
type NamespaceTransformerPlugin struct {
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
UnsetOnly bool `json:"unsetOnly" yaml:"unsetOnly"`
SetRoleBindingSubjects namespace.RoleBindingSubjectMode `json:"setRoleBindingSubjects" yaml:"setRoleBindingSubjects"`
}
func (p *NamespaceTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Namespace = ""
p.FieldSpecs = nil
if err := yaml.Unmarshal(c, p); err != nil {
return errors.WrapPrefixf(err, "unmarshalling NamespaceTransformer config")
}
switch p.SetRoleBindingSubjects {
case namespace.AllServiceAccountSubjects, namespace.DefaultSubjectsOnly, namespace.NoSubjects:
// valid
case namespace.SubjectModeUnspecified:
p.SetRoleBindingSubjects = namespace.DefaultSubjectsOnly
default:
return errors.Errorf("invalid value %q for setRoleBindingSubjects: "+
"must be one of %q, %q or %q", p.SetRoleBindingSubjects,
namespace.DefaultSubjectsOnly, namespace.NoSubjects, namespace.AllServiceAccountSubjects)
}
return nil
}
func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
if len(p.Namespace) == 0 {
return nil
}
for _, r := range m.Resources() {
if r.IsNilOrEmpty() {
// Don't mutate empty objects?
continue
}
r.StorePreviousId()
if err := r.ApplyFilter(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
SetRoleBindingSubjects: p.SetRoleBindingSubjects,
UnsetOnly: p.UnsetOnly,
}); err != nil {
return err
}
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
if len(matches) != 1 {
return fmt.Errorf(
"namespace transformation produces ID conflict: %+v", matches)
}
}
return nil
}
func NewNamespaceTransformerPlugin() resmap.TransformerPlugin {
return &NamespaceTransformerPlugin{}
}

View File

@@ -0,0 +1,105 @@
// Code generated by pluginator on PatchJson6902Transformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
"sigs.k8s.io/yaml"
)
type PatchJson6902TransformerPlugin struct {
ldr ifc.Loader
decodedPatch jsonpatch.Patch
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
}
func (p *PatchJson6902TransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.ldr = h.Loader()
err = yaml.Unmarshal(c, p)
if err != nil {
return err
}
if p.Target.Name == "" {
return fmt.Errorf("must specify the target name")
}
if p.Path == "" && p.JsonOp == "" {
return fmt.Errorf("empty file path and empty jsonOp")
}
if p.Path != "" {
if p.JsonOp != "" {
return fmt.Errorf("must specify a file path or jsonOp, not both")
}
rawOp, err := p.ldr.Load(p.Path)
if err != nil {
return err
}
p.JsonOp = string(rawOp)
if p.JsonOp == "" {
return fmt.Errorf("patch file '%s' empty seems to be empty", p.Path)
}
}
if p.JsonOp[0] != '[' {
// if it doesn't seem to be JSON, imagine
// it is YAML, and convert to JSON.
op, err := yaml.YAMLToJSON([]byte(p.JsonOp))
if err != nil {
return err
}
p.JsonOp = string(op)
}
p.decodedPatch, err = jsonpatch.DecodePatch([]byte(p.JsonOp))
if err != nil {
return errors.Wrapf(err, "decoding %s", p.JsonOp)
}
if len(p.decodedPatch) == 0 {
return fmt.Errorf(
"patch appears to be empty; file=%s, JsonOp=%s", p.Path, p.JsonOp)
}
return err
}
func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
if p.Target == nil {
return fmt.Errorf("must specify a target for patch %s", p.JsonOp)
}
resources, err := m.Select(*p.Target)
if err != nil {
return err
}
for _, res := range resources {
internalAnnotations := kioutil.GetInternalAnnotations(&res.RNode)
err = res.ApplyFilter(patchjson6902.Filter{
Patch: p.JsonOp,
})
if err != nil {
return err
}
annotations := res.GetAnnotations()
for key, value := range internalAnnotations {
annotations[key] = value
}
err = res.SetAnnotations(annotations)
if err != nil {
return err
}
}
return nil
}
func NewPatchJson6902TransformerPlugin() resmap.TransformerPlugin {
return &PatchJson6902TransformerPlugin{}
}

View File

@@ -0,0 +1,89 @@
// Code generated by pluginator on PatchStrategicMergeTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
type PatchStrategicMergeTransformerPlugin struct {
loadedPatches []*resource.Resource
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
}
func (p *PatchStrategicMergeTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
err = yaml.Unmarshal(c, p)
if err != nil {
return err
}
if len(p.Paths) == 0 && p.Patches == "" {
return fmt.Errorf("empty file path and empty patch content")
}
if len(p.Paths) != 0 {
patches, err := loadFromPaths(h, p.Paths)
if err != nil {
return err
}
p.loadedPatches = append(p.loadedPatches, patches...)
}
if p.Patches != "" {
patches, err := h.ResmapFactory().RF().SliceFromBytes([]byte(p.Patches))
if err != nil {
return err
}
p.loadedPatches = append(p.loadedPatches, patches...)
}
if len(p.loadedPatches) == 0 {
return fmt.Errorf(
"patch appears to be empty; files=%v, Patch=%s", p.Paths, p.Patches)
}
return nil
}
func loadFromPaths(
h *resmap.PluginHelpers,
paths []types.PatchStrategicMerge) (
result []*resource.Resource, err error) {
var patches []*resource.Resource
for _, path := range paths {
// For legacy reasons, attempt to treat the path string as
// actual patch content.
patches, err = h.ResmapFactory().RF().SliceFromBytes([]byte(path))
if err != nil {
// Failing that, treat it as a file path.
patches, err = h.ResmapFactory().RF().SliceFromPatches(
h.Loader(), []types.PatchStrategicMerge{path})
if err != nil {
return
}
}
result = append(result, patches...)
}
return
}
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
for _, patch := range p.loadedPatches {
target, err := m.GetById(patch.OrgId())
if err != nil {
return err
}
if err = m.ApplySmPatch(
resource.MakeIdSet([]*resource.Resource{target}), patch); err != nil {
return err
}
}
return nil
}
func NewPatchStrategicMergeTransformerPlugin() resmap.TransformerPlugin {
return &PatchStrategicMergeTransformerPlugin{}
}

View File

@@ -0,0 +1,153 @@
// Code generated by pluginator on PatchTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"strings"
jsonpatch "github.com/evanphx/json-patch"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
"sigs.k8s.io/yaml"
)
type PatchTransformerPlugin struct {
loadedPatch *resource.Resource
decodedPatch jsonpatch.Patch
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
Options map[string]bool `json:"options,omitempty" yaml:"options,omitempty"`
}
func (p *PatchTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) error {
err := yaml.Unmarshal(c, p)
if err != nil {
return err
}
p.Patch = strings.TrimSpace(p.Patch)
if p.Patch == "" && p.Path == "" {
return fmt.Errorf(
"must specify one of patch and path in\n%s", string(c))
}
if p.Patch != "" && p.Path != "" {
return fmt.Errorf(
"patch and path can't be set at the same time\n%s", string(c))
}
if p.Path != "" {
loaded, loadErr := h.Loader().Load(p.Path)
if loadErr != nil {
return loadErr
}
p.Patch = string(loaded)
}
patchSM, errSM := h.ResmapFactory().RF().FromBytes([]byte(p.Patch))
patchJson, errJson := jsonPatchFromBytes([]byte(p.Patch))
if (errSM == nil && errJson == nil) ||
(patchSM != nil && patchJson != nil) {
return fmt.Errorf(
"illegally qualifies as both an SM and JSON patch: [%v]",
p.Patch)
}
if errSM != nil && errJson != nil {
return fmt.Errorf(
"unable to parse SM or JSON patch from [%v]", p.Patch)
}
if errSM == nil {
p.loadedPatch = patchSM
if p.Options["allowNameChange"] {
p.loadedPatch.AllowNameChange()
}
if p.Options["allowKindChange"] {
p.loadedPatch.AllowKindChange()
}
} else {
p.decodedPatch = patchJson
}
return nil
}
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
if p.loadedPatch == nil {
return p.transformJson6902(m, p.decodedPatch)
}
// The patch was a strategic merge patch
return p.transformStrategicMerge(m, p.loadedPatch)
}
// transformStrategicMerge applies the provided strategic merge patch
// to all the resources in the ResMap that match either the Target or
// the identifier of the patch.
func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch *resource.Resource) error {
if p.Target == nil {
target, err := m.GetById(patch.OrgId())
if err != nil {
return err
}
return target.ApplySmPatch(patch)
}
selected, err := m.Select(*p.Target)
if err != nil {
return err
}
return m.ApplySmPatch(resource.MakeIdSet(selected), patch)
}
// transformJson6902 applies the provided json6902 patch
// to all the resources in the ResMap that match the Target.
func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpatch.Patch) error {
if p.Target == nil {
return fmt.Errorf("must specify a target for patch %s", p.Patch)
}
resources, err := m.Select(*p.Target)
if err != nil {
return err
}
for _, res := range resources {
res.StorePreviousId()
internalAnnotations := kioutil.GetInternalAnnotations(&res.RNode)
err = res.ApplyFilter(patchjson6902.Filter{
Patch: p.Patch,
})
if err != nil {
return err
}
annotations := res.GetAnnotations()
for key, value := range internalAnnotations {
annotations[key] = value
}
err = res.SetAnnotations(annotations)
}
return nil
}
// jsonPatchFromBytes loads a Json 6902 patch from
// a bytes input
func jsonPatchFromBytes(
in []byte) (jsonpatch.Patch, error) {
ops := string(in)
if ops == "" {
return nil, fmt.Errorf("empty json patch operations")
}
if ops[0] != '[' {
jsonOps, err := yaml.YAMLToJSON(in)
if err != nil {
return nil, err
}
ops = string(jsonOps)
}
return jsonpatch.DecodePatch([]byte(ops))
}
func NewPatchTransformerPlugin() resmap.TransformerPlugin {
return &PatchTransformerPlugin{}
}

View File

@@ -0,0 +1,96 @@
// Code generated by pluginator on PrefixTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"errors"
"sigs.k8s.io/kustomize/api/filters/prefix"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Add the given prefix to the field
type PrefixTransformerPlugin struct {
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
FieldSpecs types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
// TODO: Make this gvk skip list part of the config.
var prefixFieldSpecsToSkip = types.FsSlice{
{Gvk: resid.Gvk{Kind: "CustomResourceDefinition"}},
{Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"}},
{Gvk: resid.Gvk{Kind: "Namespace"}},
}
func (p *PrefixTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Prefix = ""
p.FieldSpecs = nil
err = yaml.Unmarshal(c, p)
if err != nil {
return
}
if p.FieldSpecs == nil {
return errors.New("fieldSpecs is not expected to be nil")
}
return
}
func (p *PrefixTransformerPlugin) Transform(m resmap.ResMap) error {
// Even if the Prefix is empty we want to proceed with the
// transformation. This allows to add contextual information
// to the resources (AddNamePrefix).
for _, r := range m.Resources() {
// TODO: move this test into the filter (i.e. make a better filter)
if p.shouldSkip(r.OrgId()) {
continue
}
id := r.OrgId()
// current default configuration contains
// only one entry: "metadata/name" with no GVK
for _, fs := range p.FieldSpecs {
// TODO: this is redundant to filter (but needed for now)
if !id.IsSelected(&fs.Gvk) {
continue
}
// TODO: move this test into the filter.
if fs.Path == "metadata/name" {
// "metadata/name" is the only field.
// this will add a prefix to the resource
// even if it is empty
r.AddNamePrefix(p.Prefix)
if p.Prefix != "" {
// TODO: There are multiple transformers that can change a resource's name, and each makes a call to
// StorePreviousID(). We should make it so that we only call StorePreviousID once per kustomization layer
// to avoid storing intermediate names between transformations, to prevent intermediate name conflicts.
r.StorePreviousId()
}
}
if err := r.ApplyFilter(prefix.Filter{
Prefix: p.Prefix,
FieldSpec: fs,
}); err != nil {
return err
}
}
}
return nil
}
func (p *PrefixTransformerPlugin) shouldSkip(id resid.ResId) bool {
for _, path := range prefixFieldSpecsToSkip {
if id.IsSelected(&path.Gvk) {
return true
}
}
return false
}
func NewPrefixTransformerPlugin() resmap.TransformerPlugin {
return &PrefixTransformerPlugin{}
}

View File

@@ -0,0 +1,78 @@
// Code generated by pluginator on ReplacementTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"reflect"
"sigs.k8s.io/kustomize/api/filters/replacement"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
// Replace values in targets with values from a source
type ReplacementTransformerPlugin struct {
ReplacementList []types.ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
Replacements []types.Replacement `json:"omitempty" yaml:"omitempty"`
}
func (p *ReplacementTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.ReplacementList = []types.ReplacementField{}
if err := yaml.Unmarshal(c, p); err != nil {
return err
}
for _, r := range p.ReplacementList {
if r.Path != "" && (r.Source != nil || len(r.Targets) != 0) {
return fmt.Errorf("cannot specify both path and inline replacement")
}
if r.Path != "" {
// load the replacement from the path
content, err := h.Loader().Load(r.Path)
if err != nil {
return err
}
// find if the path contains a a list of replacements or a single replacement
var replacement interface{}
err = yaml.Unmarshal(content, &replacement)
if err != nil {
return err
}
items := reflect.ValueOf(replacement)
switch items.Kind() {
case reflect.Slice:
repl := []types.Replacement{}
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl...)
case reflect.Map:
repl := types.Replacement{}
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl)
default:
return fmt.Errorf("unsupported replacement type encountered within replacement path: %v", items.Kind())
}
} else {
// replacement information is already loaded
p.Replacements = append(p.Replacements, r.Replacement)
}
}
return nil
}
func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) {
return m.ApplyFilter(replacement.Filter{
Replacements: p.Replacements,
})
}
func NewReplacementTransformerPlugin() resmap.TransformerPlugin {
return &ReplacementTransformerPlugin{}
}

View File

@@ -0,0 +1,73 @@
// Code generated by pluginator on ReplicaCountTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/replicacount"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/yaml"
)
// Find matching replicas declarations and replace the count.
// Eases the kustomization configuration of replica changes.
type ReplicaCountTransformerPlugin struct {
Replica types.Replica `json:"replica,omitempty" yaml:"replica,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
func (p *ReplicaCountTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Replica = types.Replica{}
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
}
func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
found := false
for _, fs := range p.FieldSpecs {
matcher := p.createMatcher(fs)
resList := m.GetMatchingResourcesByAnyId(matcher)
if len(resList) > 0 {
found = true
for _, r := range resList {
// There are redundant checks in the filter
// that we'll live with until resolution of
// https://github.com/kubernetes-sigs/kustomize/issues/2506
err := r.ApplyFilter(replicacount.Filter{
Replica: p.Replica,
FieldSpec: fs,
})
if err != nil {
return err
}
}
}
}
if !found {
gvks := make([]string, len(p.FieldSpecs))
for i, replicaSpec := range p.FieldSpecs {
gvks[i] = replicaSpec.Gvk.String()
}
return fmt.Errorf("resource with name %s does not match a config with the following GVK %v",
p.Replica.Name, gvks)
}
return nil
}
// Match Replica.Name and FieldSpec
func (p *ReplicaCountTransformerPlugin) createMatcher(fs types.FieldSpec) resmap.IdMatcher {
return func(r resid.ResId) bool {
return r.Name == p.Replica.Name && r.Gvk.IsSelected(&fs.Gvk)
}
}
func NewReplicaCountTransformerPlugin() resmap.TransformerPlugin {
return &ReplicaCountTransformerPlugin{}
}

View File

@@ -0,0 +1,39 @@
// Code generated by pluginator on SecretGenerator; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
type SecretGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
types.SecretArgs
}
func (p *SecretGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.SecretArgs = types.SecretArgs{}
err = yaml.Unmarshal(config, p)
if p.SecretArgs.Name == "" {
p.SecretArgs.Name = p.Name
}
if p.SecretArgs.Namespace == "" {
p.SecretArgs.Namespace = p.Namespace
}
p.h = h
return
}
func (p *SecretGeneratorPlugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromSecretArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.SecretArgs)
}
func NewSecretGeneratorPlugin() resmap.GeneratorPlugin {
return &SecretGeneratorPlugin{}
}

View File

@@ -0,0 +1,96 @@
// Code generated by pluginator on SuffixTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"errors"
"sigs.k8s.io/kustomize/api/filters/suffix"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Add the given suffix to the field
type SuffixTransformerPlugin struct {
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
FieldSpecs types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
// TODO: Make this gvk skip list part of the config.
var suffixFieldSpecsToSkip = types.FsSlice{
{Gvk: resid.Gvk{Kind: "CustomResourceDefinition"}},
{Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"}},
{Gvk: resid.Gvk{Kind: "Namespace"}},
}
func (p *SuffixTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Suffix = ""
p.FieldSpecs = nil
err = yaml.Unmarshal(c, p)
if err != nil {
return
}
if p.FieldSpecs == nil {
return errors.New("fieldSpecs is not expected to be nil")
}
return
}
func (p *SuffixTransformerPlugin) Transform(m resmap.ResMap) error {
// Even if the Suffix is empty we want to proceed with the
// transformation. This allows to add contextual information
// to the resources (AddNameSuffix).
for _, r := range m.Resources() {
// TODO: move this test into the filter (i.e. make a better filter)
if p.shouldSkip(r.OrgId()) {
continue
}
id := r.OrgId()
// current default configuration contains
// only one entry: "metadata/name" with no GVK
for _, fs := range p.FieldSpecs {
// TODO: this is redundant to filter (but needed for now)
if !id.IsSelected(&fs.Gvk) {
continue
}
// TODO: move this test into the filter.
if fs.Path == "metadata/name" {
// "metadata/name" is the only field.
// this will add a suffix to the resource
// even if it is empty
r.AddNameSuffix(p.Suffix)
if p.Suffix != "" {
// TODO: There are multiple transformers that can change a resource's name, and each makes a call to
// StorePreviousID(). We should make it so that we only call StorePreviousID once per kustomization layer
// to avoid storing intermediate names between transformations, to prevent intermediate name conflicts.
r.StorePreviousId()
}
}
if err := r.ApplyFilter(suffix.Filter{
Suffix: p.Suffix,
FieldSpec: fs,
}); err != nil {
return err
}
}
}
return nil
}
func (p *SuffixTransformerPlugin) shouldSkip(id resid.ResId) bool {
for _, path := range suffixFieldSpecsToSkip {
if id.IsSelected(&path.Gvk) {
return true
}
}
return false
}
func NewSuffixTransformerPlugin() resmap.TransformerPlugin {
return &SuffixTransformerPlugin{}
}

View File

@@ -0,0 +1,141 @@
// Code generated by pluginator on ValueAddTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/filters/valueadd"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
// An 'Add' transformer inspired by the IETF RFC 6902 JSON spec Add operation.
type ValueAddTransformerPlugin struct {
// Value is the value to add.
// Defaults to base name of encompassing kustomization root.
Value string `json:"value,omitempty" yaml:"value,omitempty"`
// Targets is a slice of targets that should have the value added.
Targets []Target `json:"targets,omitempty" yaml:"targets,omitempty"`
// TargetFilePath is a file path. If specified, the file will be parsed into
// a slice of Target, and appended to anything that was specified in the
// Targets field. This is just a means to share common target specifications.
TargetFilePath string `json:"targetFilePath,omitempty" yaml:"targetFilePath,omitempty"`
}
// Target describes where to put the value.
type Target struct {
// Selector selects the resources to modify.
Selector *types.Selector `json:"selector,omitempty" yaml:"selector,omitempty"`
// NotSelector selects the resources to exclude
// from those included by overly broad selectors.
// TODO: implement this?
// NotSelector *types.Selector `json:"notSelector,omitempty" yaml:"notSelector,omitempty"`
// FieldPath is a JSON-style path to the field intended to hold the value.
FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"`
// FilePathPosition is passed to the filter directly. Look there for doc.
FilePathPosition int `json:"filePathPosition,omitempty" yaml:"filePathPosition,omitempty"`
}
func (p *ValueAddTransformerPlugin) Config(h *resmap.PluginHelpers, c []byte) error {
err := yaml.Unmarshal(c, p)
if err != nil {
return err
}
p.Value = strings.TrimSpace(p.Value)
if p.Value == "" {
p.Value = filepath.Base(h.Loader().Root())
}
if p.TargetFilePath != "" {
bytes, err := h.Loader().Load(p.TargetFilePath)
if err != nil {
return err
}
var targets struct {
Targets []Target `json:"targets,omitempty" yaml:"targets,omitempty"`
}
err = yaml.Unmarshal(bytes, &targets)
if err != nil {
return err
}
p.Targets = append(p.Targets, targets.Targets...)
}
if len(p.Targets) == 0 {
return fmt.Errorf("must specify at least one target")
}
for _, target := range p.Targets {
if err = validateSelector(target.Selector); err != nil {
return err
}
// TODO: call validateSelector(target.NotSelector) if field added.
if err = validateJsonFieldPath(target.FieldPath); err != nil {
return err
}
if target.FilePathPosition < 0 {
return fmt.Errorf(
"value of FilePathPosition (%d) cannot be negative",
target.FilePathPosition)
}
}
return nil
}
// TODO: implement
func validateSelector(_ *types.Selector) error {
return nil
}
// TODO: Enforce RFC 6902?
func validateJsonFieldPath(p string) error {
if len(p) == 0 {
return fmt.Errorf("fieldPath cannot be empty")
}
return nil
}
func (p *ValueAddTransformerPlugin) Transform(m resmap.ResMap) (err error) {
for _, t := range p.Targets {
var resources []*resource.Resource
if t.Selector == nil {
resources = m.Resources()
} else {
resources, err = m.Select(*t.Selector)
if err != nil {
return err
}
}
// TODO: consider t.NotSelector if implemented
for _, res := range resources {
if t.FieldPath == types.MetadataNamespacePath {
err = res.ApplyFilter(namespace.Filter{
Namespace: p.Value,
})
} else {
err = res.ApplyFilter(valueadd.Filter{
Value: p.Value,
FieldPath: t.FieldPath,
FilePathPosition: t.FilePathPosition,
})
}
if err != nil {
return err
}
}
}
return nil
}
func NewValueAddTransformerPlugin() resmap.TransformerPlugin {
return &ValueAddTransformerPlugin{}
}

View File

@@ -0,0 +1,8 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package builtins holds code generated from the builtin plugins.
// The "builtin" plugins are written as normal plugins and can
// be used as such, but they are also used to generate the code
// in this package so they can be statically linked to client code.
package builtins

View File

@@ -40,6 +40,13 @@ func MakeConfigMap(
if err = rn.LoadMapIntoConfigMapData(m); err != nil {
return nil, err
}
copyLabelsAndAnnotations(rn, args.Options)
err = copyLabelsAndAnnotations(rn, args.Options)
if err != nil {
return nil, err
}
err = setImmutable(rn, args.Options)
if err != nil {
return nil, err
}
return rn, nil
}

View File

@@ -54,5 +54,6 @@ func MakeSecret(
return nil, err
}
copyLabelsAndAnnotations(rn, args.Options)
setImmutable(rn, args.Options)
return rn, nil
}

View File

@@ -76,3 +76,22 @@ func copyLabelsAndAnnotations(
}
return nil
}
func setImmutable(
rn *yaml.RNode, opts *types.GeneratorOptions) error {
if opts == nil {
return nil
}
if opts.Immutable {
n := &yaml.Node{
Kind: yaml.ScalarNode,
Value: "true",
Tag: yaml.NodeTagBool,
}
if _, err := rn.Pipe(yaml.FieldSetter{Name: "immutable", Value: yaml.NewRNode(n)}); err != nil {
return err
}
}
return nil
}

View File

@@ -4,7 +4,7 @@
package git
import (
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
// Cloner is a function that can clone a git repo.
@@ -14,7 +14,7 @@ type Cloner func(repoSpec *RepoSpec) error
// to say, some remote API, to obtain a local clone of
// a remote repo.
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
r, err := newCmdRunner()
r, err := newCmdRunner(repoSpec.Timeout)
if err != nil {
return err
}
@@ -36,7 +36,10 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
if err = r.run("checkout", "FETCH_HEAD"); err != nil {
return err
}
return r.run("submodule", "update", "--init", "--recursive")
if repoSpec.Submodules {
return r.run("submodule", "update", "--init", "--recursive")
}
return nil
}
// DoNothingCloner returns a cloner that only sets

View File

@@ -8,13 +8,10 @@ import (
"time"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
// Arbitrary, but non-infinite, timeout for running commands.
const defaultDuration = 27 * time.Second
// gitRunner runs the external git binary.
type gitRunner struct {
gitProgram string
@@ -24,7 +21,7 @@ type gitRunner struct {
// newCmdRunner returns a gitRunner if it can find the binary.
// It also creats a temp directory for cloning repos.
func newCmdRunner() (*gitRunner, error) {
func newCmdRunner(timeout time.Duration) (*gitRunner, error) {
gitProgram, err := exec.LookPath("git")
if err != nil {
return nil, errors.Wrap(err, "no 'git' program on path")
@@ -35,7 +32,7 @@ func newCmdRunner() (*gitRunner, error) {
}
return &gitRunner{
gitProgram: gitProgram,
duration: defaultDuration,
duration: timeout,
dir: dir,
}, nil
}

View File

@@ -5,11 +5,13 @@ package git
import (
"fmt"
"net/url"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
// Used as a temporary non-empty occupant of the cloneDir
@@ -44,6 +46,12 @@ type RepoSpec struct {
// e.g. .git or empty in case of _git is present
GitSuffix string
// Submodules indicates whether or not to clone git submodules.
Submodules bool
// Timeout is the maximum duration allowed for execing git commands.
Timeout time.Duration
}
// CloneSpec returns a string suitable for "git clone {spec}".
@@ -70,14 +78,15 @@ func (x *RepoSpec) Cleaner(fSys filesys.FileSystem) func() error {
return func() error { return fSys.RemoveAll(x.Dir.String()) }
}
// NewRepoSpecFromURL parses git-like urls.
// From strings like git@github.com:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
func NewRepoSpecFromURL(n string) (*RepoSpec, error) {
if filepath.IsAbs(n) {
return nil, fmt.Errorf("uri looks like abs path: %s", n)
}
host, orgRepo, path, gitRef, gitSuffix := parseGitUrl(n)
host, orgRepo, path, gitRef, gitSubmodules, suffix, gitTimeout := parseGitURL(n)
if orgRepo == "" {
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
}
@@ -86,28 +95,27 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
}
return &RepoSpec{
raw: n, Host: host, OrgRepo: orgRepo,
Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: gitSuffix}, nil
Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: suffix,
Submodules: gitSubmodules, Timeout: gitTimeout}, nil
}
const (
refQuery = "?ref="
refQueryRegex = "\\?(version|ref)="
gitSuffix = ".git"
gitDelimiter = "_git/"
refQuery = "?ref="
gitSuffix = ".git"
gitDelimiter = "_git/"
)
// From strings like git@github.com:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func parseGitUrl(n string) (
host string, orgRepo string, path string, gitRef string, gitSuff string) {
func parseGitURL(n string) (
host string, orgRepo string, path string, gitRef string, gitSubmodules bool, gitSuff string, gitTimeout time.Duration) {
if strings.Contains(n, gitDelimiter) {
index := strings.Index(n, gitDelimiter)
// Adding _git/ to host
host = normalizeGitHostSpec(n[:index+len(gitDelimiter)])
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
path, gitRef = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
return
}
host, n = parseHostSpec(n)
@@ -116,35 +124,75 @@ func parseGitUrl(n string) (
index := strings.Index(n, gitSuffix)
orgRepo = n[0:index]
n = n[index+len(gitSuffix):]
path, gitRef = peelQuery(n)
if len(n) > 0 && n[0] == '/' {
n = n[1:]
}
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
return
}
i := strings.Index(n, "/")
if i < 1 {
return "", "", "", "", ""
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
return
}
j := strings.Index(n[i+1:], "/")
if j >= 0 {
j += i + 1
orgRepo = n[:j]
path, gitRef = peelQuery(n[j+1:])
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[j+1:])
return
}
path = ""
orgRepo, gitRef = peelQuery(n)
return host, orgRepo, path, gitRef, gitSuff
orgRepo, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
return host, orgRepo, path, gitRef, gitSubmodules, gitSuff, gitTimeout
}
func peelQuery(arg string) (string, string) {
// Clone git submodules by default.
const defaultSubmodules = true
r, _ := regexp.Compile(refQueryRegex)
j := r.FindStringIndex(arg)
// Arbitrary, but non-infinite, timeout for running commands.
const defaultTimeout = 27 * time.Second
if len(j) > 0 {
return arg[:j[0]], arg[j[0]+len(r.FindString(arg)):]
func peelQuery(arg string) (string, string, time.Duration, bool) {
// Parse the given arg into a URL. In the event of a parse failure, return
// our defaults.
parsed, err := url.Parse(arg)
if err != nil {
return arg, "", defaultTimeout, defaultSubmodules
}
return arg, ""
values := parsed.Query()
// ref is the desired git ref to target. Can be specified by in a git URL
// with ?ref=<string> or ?version=<string>, although ref takes precedence.
ref := values.Get("version")
if queryValue := values.Get("ref"); queryValue != "" {
ref = queryValue
}
// depth is the desired git exec timeout. Can be specified by in a git URL
// with ?timeout=<duration>.
duration := defaultTimeout
if queryValue := values.Get("timeout"); queryValue != "" {
// Attempt to first parse as a number of integer seconds (like "61"),
// and then attempt to parse as a suffixed duration (like "61s").
if intValue, err := strconv.Atoi(queryValue); err == nil && intValue > 0 {
duration = time.Duration(intValue) * time.Second
} else if durationValue, err := time.ParseDuration(queryValue); err == nil && durationValue > 0 {
duration = durationValue
}
}
// submodules indicates if git submodule cloning is desired. Can be
// specified by in a git URL with ?submodules=<bool>.
submodules := defaultSubmodules
if queryValue := values.Get("submodules"); queryValue != "" {
if boolValue, err := strconv.ParseBool(queryValue); err == nil {
submodules = boolValue
}
}
return parsed.Path, ref, duration, submodules
}
func parseHostSpec(n string) (string, string) {
@@ -180,7 +228,7 @@ func parseHostSpec(n string) (string, string) {
if strings.HasSuffix(host, p) {
i := strings.Index(n, "/")
if i > -1 {
host = host + n[0:i+1]
host += n[0 : i+1]
n = n[i+1:]
}
break

View File

@@ -19,6 +19,16 @@ func (e YamlFormatError) Error() string {
return fmt.Sprintf("YAML file [%s] encounters a format error.\n%s\n", e.Path, e.ErrorMsg)
}
// MalformedYamlError represents an error that occurred while trying to decode a given YAML.
type MalformedYamlError struct {
Path string
ErrorMsg string
}
func (e MalformedYamlError) Error() string {
return fmt.Sprintf("%s in File: %s", e.ErrorMsg, e.Path)
}
// Handler handles YamlFormatError
func Handler(e error, path string) error {
if isYAMLSyntaxError(e) {
@@ -27,9 +37,19 @@ func Handler(e error, path string) error {
ErrorMsg: e.Error(),
}
}
if IsMalformedYAMLError(e) {
return MalformedYamlError{
Path: path,
ErrorMsg: e.Error(),
}
}
return e
}
func isYAMLSyntaxError(e error) bool {
return strings.Contains(e.Error(), "error converting YAML to JSON") || strings.Contains(e.Error(), "error unmarshaling JSON")
}
func IsMalformedYAMLError(e error) bool {
return strings.Contains(e.Error(), "MalformedYAMLError")
}

View File

@@ -6,8 +6,8 @@ package builtinconfig
import (
"strings"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
)
// NameBackReferences is an association between a gvk.GVK (a ReferralTarget)

View File

@@ -11,24 +11,28 @@ func _() {
_ = x[Unknown-0]
_ = x[AnnotationsTransformer-1]
_ = x[ConfigMapGenerator-2]
_ = x[HashTransformer-3]
_ = x[ImageTagTransformer-4]
_ = x[LabelTransformer-5]
_ = x[LegacyOrderTransformer-6]
_ = x[NamespaceTransformer-7]
_ = x[PatchJson6902Transformer-8]
_ = x[PatchStrategicMergeTransformer-9]
_ = x[PatchTransformer-10]
_ = x[PrefixSuffixTransformer-11]
_ = x[ReplicaCountTransformer-12]
_ = x[SecretGenerator-13]
_ = x[ValueAddTransformer-14]
_ = x[HelmChartInflationGenerator-15]
_ = x[IAMPolicyGenerator-3]
_ = x[HashTransformer-4]
_ = x[ImageTagTransformer-5]
_ = x[LabelTransformer-6]
_ = x[LegacyOrderTransformer-7]
_ = x[NamespaceTransformer-8]
_ = x[PatchJson6902Transformer-9]
_ = x[PatchStrategicMergeTransformer-10]
_ = x[PatchTransformer-11]
_ = x[PrefixSuffixTransformer-12]
_ = x[PrefixTransformer-13]
_ = x[SuffixTransformer-14]
_ = x[ReplicaCountTransformer-15]
_ = x[SecretGenerator-16]
_ = x[ValueAddTransformer-17]
_ = x[HelmChartInflationGenerator-18]
_ = x[ReplacementTransformer-19]
}
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGenerator"
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorIAMPolicyGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerPrefixTransformerSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGeneratorReplacementTransformer"
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316}
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 65, 80, 99, 115, 137, 157, 181, 211, 227, 250, 267, 284, 307, 322, 341, 368, 390}
func (i BuiltinPluginType) String() string {
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {

View File

@@ -4,7 +4,7 @@
package builtinhelpers
import (
"sigs.k8s.io/kustomize/api/builtins"
"sigs.k8s.io/kustomize/api/internal/builtins"
"sigs.k8s.io/kustomize/api/resmap"
)
@@ -15,6 +15,7 @@ const (
Unknown BuiltinPluginType = iota
AnnotationsTransformer
ConfigMapGenerator
IAMPolicyGenerator
HashTransformer
ImageTagTransformer
LabelTransformer
@@ -24,15 +25,18 @@ const (
PatchStrategicMergeTransformer
PatchTransformer
PrefixSuffixTransformer
PrefixTransformer
SuffixTransformer
ReplicaCountTransformer
SecretGenerator
ValueAddTransformer
HelmChartInflationGenerator
ReplacementTransformer
)
var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
func init() {
func init() { //nolint:gochecknoinits
stringToBuiltinPluginTypeMap = makeStringToBuiltinPluginTypeMap()
}
@@ -57,10 +61,40 @@ func GetBuiltinPluginType(n string) BuiltinPluginType {
var GeneratorFactories = map[BuiltinPluginType]func() resmap.GeneratorPlugin{
ConfigMapGenerator: builtins.NewConfigMapGeneratorPlugin,
IAMPolicyGenerator: builtins.NewIAMPolicyGeneratorPlugin,
SecretGenerator: builtins.NewSecretGeneratorPlugin,
HelmChartInflationGenerator: builtins.NewHelmChartInflationGeneratorPlugin,
}
type MultiTransformer struct {
transformers []resmap.TransformerPlugin
}
func (t *MultiTransformer) Transform(m resmap.ResMap) error {
for _, transformer := range t.transformers {
if err := transformer.Transform(m); err != nil {
return err
}
}
return nil
}
func (t *MultiTransformer) Config(h *resmap.PluginHelpers, b []byte) error {
for _, transformer := range t.transformers {
if err := transformer.Config(h, b); err != nil {
return err
}
}
return nil
}
func NewMultiTransformer() resmap.TransformerPlugin {
return &MultiTransformer{[]resmap.TransformerPlugin{
builtins.NewPrefixTransformerPlugin(),
builtins.NewSuffixTransformerPlugin(),
}}
}
var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin{
AnnotationsTransformer: builtins.NewAnnotationsTransformerPlugin,
HashTransformer: builtins.NewHashTransformerPlugin,
@@ -71,7 +105,10 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
PatchJson6902Transformer: builtins.NewPatchJson6902TransformerPlugin,
PatchStrategicMergeTransformer: builtins.NewPatchStrategicMergeTransformerPlugin,
PatchTransformer: builtins.NewPatchTransformerPlugin,
PrefixSuffixTransformer: builtins.NewPrefixSuffixTransformerPlugin,
PrefixSuffixTransformer: NewMultiTransformer,
PrefixTransformer: builtins.NewPrefixTransformerPlugin,
SuffixTransformer: builtins.NewSuffixTransformerPlugin,
ReplacementTransformer: builtins.NewReplacementTransformerPlugin,
ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin,
ValueAddTransformer: builtins.NewValueAddTransformerPlugin,
}

View File

@@ -89,7 +89,10 @@ type argsConfig struct {
func (p *ExecPlugin) processOptionalArgsFields() error {
var c argsConfig
yaml.Unmarshal(p.cfg, &c)
err := yaml.Unmarshal(p.cfg, &c)
if err != nil {
return err
}
if c.ArgsOneLiner != "" {
p.args, _ = shlex.Split(c.ArgsOneLiner)
}

View File

@@ -78,6 +78,8 @@ func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin {
EnableExec: o.EnableExec,
StorageMounts: toStorageMounts(o.Mounts),
Env: o.Env,
AsCurrentUser: o.AsCurrentUser,
WorkingDir: o.WorkingDir,
},
}
}

View File

@@ -13,17 +13,17 @@ import (
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
"sigs.k8s.io/kustomize/api/internal/plugins/fnplugin"
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/kustomize/kyaml/resid"
)
// Loader loads plugins using a file loader (a different loader).
@@ -47,15 +47,24 @@ func (l *Loader) Config() *types.PluginConfig {
return l.pc
}
// SetWorkDir sets the working directory for this loader's plugins
func (l *Loader) SetWorkDir(wd string) {
l.pc.FnpLoadingOptions.WorkingDir = wd
}
func (l *Loader) LoadGenerators(
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Generator, error) {
var result []resmap.Generator
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) (
result []*resmap.GeneratorWithProperties, err error) {
for _, res := range rm.Resources() {
g, err := l.LoadGenerator(ldr, v, res)
if err != nil {
return nil, err
}
result = append(result, g)
generatorOrigin, err := resource.OriginFromCustomPlugin(res)
if err != nil {
return nil, err
}
result = append(result, &resmap.GeneratorWithProperties{Generator: g, Origin: generatorOrigin})
}
return result, nil
}
@@ -74,20 +83,24 @@ func (l *Loader) LoadGenerator(
}
func (l *Loader) LoadTransformers(
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Transformer, error) {
var result []resmap.Transformer
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]*resmap.TransformerWithProperties, error) {
var result []*resmap.TransformerWithProperties
for _, res := range rm.Resources() {
t, err := l.LoadTransformer(ldr, v, res)
if err != nil {
return nil, err
}
result = append(result, t)
transformerOrigin, err := resource.OriginFromCustomPlugin(res)
if err != nil {
return nil, err
}
result = append(result, &resmap.TransformerWithProperties{Transformer: t, Origin: transformerOrigin})
}
return result, nil
}
func (l *Loader) LoadTransformer(
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (resmap.Transformer, error) {
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (*resmap.TransformerWithProperties, error) {
c, err := l.loadAndConfigurePlugin(ldr, v, res)
if err != nil {
return nil, err
@@ -96,7 +109,7 @@ func (l *Loader) LoadTransformer(
if !ok {
return nil, fmt.Errorf("plugin %s not a transformer", res.OrgId())
}
return t, nil
return &resmap.TransformerWithProperties{Transformer: t}, nil
}
func relativePluginPath(id resid.ResId) string {
@@ -215,6 +228,17 @@ func (l *Loader) makeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
func (l *Loader) loadPlugin(res *resource.Resource) (resmap.Configurable, error) {
spec := fnplugin.GetFunctionSpec(res)
if spec != nil {
// validation check that function mounts are under the current kustomization directory
for _, mount := range spec.Container.StorageMounts {
if filepath.IsAbs(mount.Src) {
return nil, errors.New(fmt.Sprintf("plugin %s with mount path '%s' is not permitted; "+
"mount paths must be relative to the current kustomization directory", res.OrgId(), mount.Src))
}
if strings.HasPrefix(filepath.Clean(mount.Src), "../") {
return nil, errors.New(fmt.Sprintf("plugin %s with mount path '%s' is not permitted; "+
"mount paths must be under the current kustomization directory", res.OrgId(), mount.Src))
}
}
return fnplugin.NewFnPlugin(&l.pc.FnpLoadingOptions), nil
}
return l.loadExecOrGoPlugin(res.OrgId())

View File

@@ -12,11 +12,11 @@ import (
"strconv"
"time"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/yaml"
)
@@ -137,7 +137,9 @@ func GetResMapWithIDAnnotation(rm resmap.ResMap) (resmap.ResMap, error) {
}
annotations := r.GetAnnotations()
annotations[idAnnotation] = string(idString)
r.SetAnnotations(annotations)
if err = r.SetAnnotations(annotations); err != nil {
return nil, err
}
}
return inputRM, nil
}
@@ -158,7 +160,10 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt
}
for _, r := range resources {
removeIDAnnotation(r) // stale--not manipulated by plugin transformers
// stale--not manipulated by plugin transformers
if err = removeIDAnnotation(r); err != nil {
return err
}
// Add to the new map, checking for duplicates
if err := newMap.Append(r); err != nil {
@@ -175,7 +180,7 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt
return err
}
if oldIdx != -1 {
rm.GetByIndex(oldIdx).ResetPrimaryData(r)
rm.GetByIndex(oldIdx).ResetRNode(r)
} else {
if err := rm.Append(r); err != nil {
return err
@@ -187,21 +192,20 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt
for _, id := range rm.AllIds() {
newIdx, _ := newMap.GetIndexOfCurrentId(id)
if newIdx == -1 {
rm.Remove(id)
if err = rm.Remove(id); err != nil {
return err
}
}
}
return nil
}
func removeIDAnnotation(r *resource.Resource) {
func removeIDAnnotation(r *resource.Resource) error {
// remove the annotation set by Kustomize to track the resource
annotations := r.GetAnnotations()
delete(annotations, idAnnotation)
if len(annotations) == 0 {
annotations = nil
}
r.SetAnnotations(annotations)
return r.SetAnnotations(annotations)
}
// UpdateResourceOptions updates the generator options for each resource in the
@@ -224,14 +228,13 @@ func UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {
}
delete(annotations, HashAnnotation)
delete(annotations, BehaviorAnnotation)
if len(annotations) == 0 {
annotations = nil
if err := r.SetAnnotations(annotations); err != nil {
return nil, err
}
r.SetAnnotations(annotations)
r.SetOptions(types.NewGenArgs(
&types.GeneratorArgs{
Behavior: behavior,
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
if needsHash {
r.EnableHashSuffix()
}
r.SetBehavior(types.NewGenerationBehavior(behavior))
}
return rm, nil
}

View File

@@ -6,18 +6,22 @@ package target
import (
"encoding/json"
"fmt"
"path/filepath"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/builtins"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/accumulator"
"sigs.k8s.io/kustomize/api/internal/builtins"
"sigs.k8s.io/kustomize/api/internal/kusterr"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/konfig"
load "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/yaml"
@@ -26,10 +30,12 @@ import (
// KustTarget encapsulates the entirety of a kustomization build.
type KustTarget struct {
kustomization *types.Kustomization
kustFileName string
ldr ifc.Loader
validator ifc.Validator
rFactory *resmap.Factory
pLdr *loader.Loader
origin *resource.Origin
}
// NewKustTarget returns a new instance of KustTarget.
@@ -38,17 +44,19 @@ func NewKustTarget(
validator ifc.Validator,
rFactory *resmap.Factory,
pLdr *loader.Loader) *KustTarget {
pLdrCopy := *pLdr
pLdrCopy.SetWorkDir(ldr.Root())
return &KustTarget{
ldr: ldr,
validator: validator,
rFactory: rFactory,
pLdr: pLdr,
pLdr: &pLdrCopy,
}
}
// Load attempts to load the target's kustomization file.
func (kt *KustTarget) Load() error {
content, err := loadKustFile(kt.ldr)
content, kustFileName, err := loadKustFile(kt.ldr)
if err != nil {
return err
}
@@ -69,6 +77,7 @@ func (kt *KustTarget) Load() error {
strings.Join(errs, "\n"), kt.ldr.Root())
}
kt.kustomization = &k
kt.kustFileName = kustFileName
return nil
}
@@ -80,23 +89,25 @@ func (kt *KustTarget) Kustomization() types.Kustomization {
return result
}
func loadKustFile(ldr ifc.Loader) ([]byte, error) {
func loadKustFile(ldr ifc.Loader) ([]byte, string, error) {
var content []byte
match := 0
var kustFileName string
for _, kf := range konfig.RecognizedKustomizationFileNames() {
c, err := ldr.Load(kf)
if err == nil {
match += 1
content = c
kustFileName = kf
}
}
switch match {
case 0:
return nil, NewErrMissingKustomization(ldr.Root())
return nil, "", NewErrMissingKustomization(ldr.Root())
case 1:
return content, nil
return content, kustFileName, nil
default:
return nil, fmt.Errorf(
return nil, "", fmt.Errorf(
"Found multiple kustomization files under: %s\n", ldr.Root())
}
}
@@ -108,6 +119,11 @@ func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
}
func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) {
var origin *resource.Origin
if len(kt.kustomization.BuildMetadata) != 0 {
origin = &resource.Origin{}
}
kt.origin = origin
ra, err := kt.AccumulateTarget()
if err != nil {
return nil, err
@@ -151,6 +167,15 @@ func (kt *KustTarget) addHashesToNames(
// holding customized resources and the data/rules used
// to do so. The name back references and vars are
// not yet fixed.
// The origin parameter is used through the recursive calls
// to annotate each resource with information about where
// the resource came from, e.g. the file and/or the repository
// it originated from.
// As an entrypoint, one can pass an empty resource.Origin object to
// AccumulateTarget. As AccumulateTarget moves recursively
// through kustomization directories, it updates `origin.path`
// accordingly. When a remote base is found, it updates `origin.repo`
// and `origin.ref` accordingly.
func (kt *KustTarget) AccumulateTarget() (
ra *accumulator.ResAccumulator, err error) {
return kt.accumulateTarget(accumulator.MakeEmptyAccumulator())
@@ -205,27 +230,51 @@ func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) (
return nil, errors.Wrapf(
err, "merging vars %v", kt.kustomization.Vars)
}
err = kt.IgnoreLocal(ra)
if err != nil {
return nil, err
}
return ra, nil
}
// IgnoreLocal drops the local resource by checking the annotation "config.kubernetes.io/local-config".
func (kt *KustTarget) IgnoreLocal(ra *accumulator.ResAccumulator) error {
rf := kt.rFactory.RF()
if rf.IncludeLocalConfigs {
return nil
}
remainRes, err := rf.DropLocalNodes(ra.ResMap().ToRNodeSlice())
if err != nil {
return err
}
return ra.Intersection(kt.rFactory.FromResourceSlice(remainRes))
}
func (kt *KustTarget) runGenerators(
ra *accumulator.ResAccumulator) error {
var generators []resmap.Generator
var generators []*resmap.GeneratorWithProperties
gs, err := kt.configureBuiltinGenerators()
if err != nil {
return err
}
generators = append(generators, gs...)
gs, err = kt.configureExternalGenerators()
if err != nil {
return errors.Wrap(err, "loading generator plugins")
}
generators = append(generators, gs...)
for _, g := range generators {
for i, g := range generators {
resMap, err := g.Generate()
if err != nil {
return err
}
if resMap != nil {
err = resMap.AddOriginAnnotation(generators[i].Origin)
if err != nil {
return errors.Wrapf(err, "adding origin annotations for generator %v", g)
}
}
err = ra.AbsorbAll(resMap)
if err != nil {
return errors.Wrapf(err, "merging from generator %v", g)
@@ -234,7 +283,8 @@ func (kt *KustTarget) runGenerators(
return nil
}
func (kt *KustTarget) configureExternalGenerators() ([]resmap.Generator, error) {
func (kt *KustTarget) configureExternalGenerators() (
[]*resmap.GeneratorWithProperties, error) {
ra := accumulator.MakeEmptyAccumulator()
var generatorPaths []string
for _, p := range kt.kustomization.Generators {
@@ -245,7 +295,17 @@ func (kt *KustTarget) configureExternalGenerators() ([]resmap.Generator, error)
generatorPaths = append(generatorPaths, p)
continue
}
ra.AppendAll(rm)
// inline config, track the origin
if kt.origin != nil {
resources := rm.Resources()
for _, r := range resources {
r.SetOrigin(kt.origin.Append(kt.kustFileName))
rm.Replace(r)
}
}
if err = ra.AppendAll(rm); err != nil {
return nil, errors.Wrapf(err, "configuring external generator")
}
}
ra, err := kt.accumulateResources(ra, generatorPaths)
if err != nil {
@@ -255,7 +315,7 @@ func (kt *KustTarget) configureExternalGenerators() ([]resmap.Generator, error)
}
func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
var r []resmap.Transformer
var r []*resmap.TransformerWithProperties
tConfig := ra.GetTransformerConfig()
lts, err := kt.configureBuiltinTransformers(tConfig)
if err != nil {
@@ -270,7 +330,7 @@ func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
return ra.Transform(newMultiTransformer(r))
}
func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]resmap.Transformer, error) {
func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]*resmap.TransformerWithProperties, error) {
ra := accumulator.MakeEmptyAccumulator()
var transformerPaths []string
for _, p := range transformers {
@@ -281,10 +341,20 @@ func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]re
transformerPaths = append(transformerPaths, p)
continue
}
ra.AppendAll(rm)
// inline config, track the origin
if kt.origin != nil {
resources := rm.Resources()
for _, r := range resources {
r.SetOrigin(kt.origin.Append(kt.kustFileName))
rm.Replace(r)
}
}
if err = ra.AppendAll(rm); err != nil {
return nil, errors.Wrapf(err, "configuring external transformer")
}
}
ra, err := kt.accumulateResources(ra, transformerPaths)
if err != nil {
return nil, err
}
@@ -303,16 +373,18 @@ func (kt *KustTarget) runValidators(ra *accumulator.ResAccumulator) error {
if err != nil {
return err
}
new := ra.ResMap().DeepCopy()
kt.removeValidatedByLabel(new)
if err = orignal.ErrorIfNotEqualSets(new); err != nil {
newMap := ra.ResMap().DeepCopy()
if err = kt.removeValidatedByLabel(newMap); err != nil {
return err
}
if err = orignal.ErrorIfNotEqualSets(newMap); err != nil {
return fmt.Errorf("validator shouldn't modify the resource map: %v", err)
}
}
return nil
}
func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) {
func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) error {
resources := rm.Resources()
for _, r := range resources {
labels := r.GetLabels()
@@ -320,12 +392,11 @@ func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) {
continue
}
delete(labels, konfig.ValidatedByLabelKey)
if len(labels) == 0 {
r.SetLabels(nil)
} else {
r.SetLabels(labels)
if err := r.SetLabels(labels); err != nil {
return err
}
}
return nil
}
// accumulateResources fills the given resourceAccumulator
@@ -335,13 +406,32 @@ func (kt *KustTarget) accumulateResources(
for _, path := range paths {
// try loading resource as file then as base (directory or git repository)
if errF := kt.accumulateFile(ra, path); errF != nil {
// not much we can do if the error is an HTTP error so we bail out
if errors.Is(errF, load.ErrHTTP) {
return nil, errF
}
ldr, err := kt.ldr.New(path)
if err != nil {
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
return nil, errF
}
return nil, errors.Wrapf(
err, "accumulation err='%s'", errF.Error())
}
ra, err = kt.accumulateDirectory(ra, ldr, false)
// store the origin, we'll need it later
origin := kt.origin.Copy()
if kt.origin != nil {
kt.origin = kt.origin.Append(path)
ra, err = kt.accumulateDirectory(ra, ldr, false)
// after we are done recursing through the directory, reset the origin
kt.origin = &origin
} else {
ra, err = kt.accumulateDirectory(ra, ldr, false)
}
if err != nil {
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
return nil, errF
}
return nil, errors.Wrapf(
err, "accumulation err='%s'", errF.Error())
}
@@ -361,7 +451,16 @@ func (kt *KustTarget) accumulateComponents(
return nil, fmt.Errorf("loader.New %q", errL)
}
var errD error
ra, errD = kt.accumulateDirectory(ra, ldr, true)
// store the origin, we'll need it later
origin := kt.origin.Copy()
if kt.origin != nil {
kt.origin = kt.origin.Append(path)
ra, errD = kt.accumulateDirectory(ra, ldr, true)
// after we are done recursing through the directory, reset the origin
kt.origin = &origin
} else {
ra, errD = kt.accumulateDirectory(ra, ldr, true)
}
if errD != nil {
return nil, fmt.Errorf("accumulateDirectory: %q", errD)
}
@@ -378,10 +477,11 @@ func (kt *KustTarget) accumulateDirectory(
return nil, errors.Wrapf(
err, "couldn't make target for path '%s'", ldr.Root())
}
subKt.kustomization.BuildMetadata = kt.kustomization.BuildMetadata
subKt.origin = kt.origin
var bytes []byte
path := ldr.Root()
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
bytes, err = ldr.Load(filepath.Join(path, openApiPath))
bytes, err = ldr.Load(openApiPath)
if err != nil {
return nil, err
}
@@ -426,6 +526,16 @@ func (kt *KustTarget) accumulateFile(
if err != nil {
return errors.Wrapf(err, "accumulating resources from '%s'", path)
}
if kt.origin != nil {
originAnno, err := kt.origin.Append(path).String()
if err != nil {
return errors.Wrapf(err, "cannot add path annotation for '%s'", path)
}
err = resources.AnnotateAll(utils.OriginAnnotationKey, originAnno)
if err != nil || originAnno == "" {
return errors.Wrapf(err, "cannot add path annotation for '%s'", path)
}
}
err = ra.AppendAll(resources)
if err != nil {
return errors.Wrapf(err, "merging resources from '%s'", path)

View File

@@ -5,11 +5,15 @@ package target
import (
"fmt"
"path/filepath"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Functions dedicated to configuring the builtin
@@ -28,7 +32,7 @@ import (
// N plugin instances with differing configurations.
func (kt *KustTarget) configureBuiltinGenerators() (
result []resmap.Generator, err error) {
result []*resmap.GeneratorWithProperties, err error) {
for _, bpt := range []builtinhelpers.BuiltinPluginType{
builtinhelpers.ConfigMapGenerator,
builtinhelpers.SecretGenerator,
@@ -39,31 +43,67 @@ func (kt *KustTarget) configureBuiltinGenerators() (
if err != nil {
return nil, err
}
result = append(result, r...)
var generatorOrigin *resource.Origin
if kt.origin != nil {
generatorOrigin = &resource.Origin{
Repo: kt.origin.Repo,
Ref: kt.origin.Ref,
ConfiguredIn: filepath.Join(kt.origin.Path, kt.kustFileName),
ConfiguredBy: yaml.ResourceIdentifier{
TypeMeta: yaml.TypeMeta{
APIVersion: "builtin",
Kind: bpt.String(),
},
},
}
}
for i := range r {
result = append(result, &resmap.GeneratorWithProperties{Generator: r[i], Origin: generatorOrigin})
}
}
return result, nil
}
func (kt *KustTarget) configureBuiltinTransformers(
tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
result []*resmap.TransformerWithProperties, err error) {
for _, bpt := range []builtinhelpers.BuiltinPluginType{
builtinhelpers.PatchStrategicMergeTransformer,
builtinhelpers.PatchTransformer,
builtinhelpers.NamespaceTransformer,
builtinhelpers.PrefixSuffixTransformer,
builtinhelpers.PrefixTransformer,
builtinhelpers.SuffixTransformer,
builtinhelpers.LabelTransformer,
builtinhelpers.AnnotationsTransformer,
builtinhelpers.PatchJson6902Transformer,
builtinhelpers.ReplicaCountTransformer,
builtinhelpers.ImageTagTransformer,
builtinhelpers.ReplacementTransformer,
} {
r, err := transformerConfigurators[bpt](
kt, bpt, builtinhelpers.TransformerFactories[bpt], tc)
if err != nil {
return nil, err
}
result = append(result, r...)
var transformerOrigin *resource.Origin
if kt.origin != nil {
transformerOrigin = &resource.Origin{
Repo: kt.origin.Repo,
Ref: kt.origin.Ref,
ConfiguredIn: filepath.Join(kt.origin.Path, kt.kustFileName),
ConfiguredBy: yaml.ResourceIdentifier{
TypeMeta: yaml.TypeMeta{
APIVersion: "builtin",
Kind: bpt.String(),
},
},
}
}
for i := range r {
result = append(result, &resmap.TransformerWithProperties{Transformer: r[i], Origin: transformerOrigin})
}
}
return result, nil
}
@@ -146,6 +186,9 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.NamespaceTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
if kt.kustomization.Namespace == "" {
return
}
var c struct {
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
FieldSpecs []types.FieldSpec
@@ -229,6 +272,9 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.LabelTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
if len(kt.kustomization.Labels) == 0 && len(kt.kustomization.CommonLabels) == 0 {
return
}
for _, label := range kt.kustomization.Labels {
var c struct {
Labels map[string]string
@@ -240,6 +286,13 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
if label.IncludeSelectors {
fss, err = fss.MergeAll(tc.CommonLabels)
} else {
// merge spec/template/metadata fieldSpec if includeTemplate flag is true
if label.IncludeTemplates {
fss, err = fss.MergeOne(types.FieldSpec{Path: "spec/template/metadata/labels", CreateIfNotPresent: false})
if err != nil {
return nil, errors.Wrap(err, "failed to merge template fieldSpec")
}
}
// only add to metadata by default
fss, err = fss.MergeOne(types.FieldSpec{Path: "metadata/labels", CreateIfNotPresent: true})
}
@@ -271,6 +324,9 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.AnnotationsTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
if len(kt.kustomization.CommonAnnotations) == 0 {
return
}
var c struct {
Annotations map[string]string
FieldSpecs []types.FieldSpec
@@ -285,16 +341,17 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
result = append(result, p)
return
},
builtinhelpers.PrefixSuffixTransformer: func(
builtinhelpers.PrefixTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
if kt.kustomization.NamePrefix == "" {
return
}
var c struct {
Prefix string
Suffix string
FieldSpecs []types.FieldSpec
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
c.Prefix = kt.kustomization.NamePrefix
c.Suffix = kt.kustomization.NameSuffix
c.FieldSpecs = tc.NamePrefix
p := f()
err = kt.configureBuiltinPlugin(p, c, bpt)
@@ -304,6 +361,26 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
result = append(result, p)
return
},
builtinhelpers.SuffixTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
if kt.kustomization.NameSuffix == "" {
return
}
var c struct {
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
c.Suffix = kt.kustomization.NameSuffix
c.FieldSpecs = tc.NameSuffix
p := f()
err = kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
return nil, err
}
result = append(result, p)
return
},
builtinhelpers.ImageTagTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
@@ -323,6 +400,24 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
}
return
},
builtinhelpers.ReplacementTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
if len(kt.kustomization.Replacements) == 0 {
return
}
var c struct {
Replacements []types.ReplacementField
}
c.Replacements = kt.kustomization.Replacements
p := f()
err = kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
return nil, err
}
result = append(result, p)
return result, nil
},
builtinhelpers.ReplicaCountTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {

View File

@@ -9,15 +9,15 @@ import (
// multiTransformer contains a list of transformers.
type multiTransformer struct {
transformers []resmap.Transformer
transformers []*resmap.TransformerWithProperties
}
var _ resmap.Transformer = &multiTransformer{}
// newMultiTransformer constructs a multiTransformer.
func newMultiTransformer(t []resmap.Transformer) resmap.Transformer {
func newMultiTransformer(t []*resmap.TransformerWithProperties) resmap.Transformer {
r := &multiTransformer{
transformers: make([]resmap.Transformer, len(t)),
transformers: make([]*resmap.TransformerWithProperties, len(t)),
}
copy(r.transformers, t)
return r
@@ -30,6 +30,11 @@ func (o *multiTransformer) Transform(m resmap.ResMap) error {
if err := t.Transform(m); err != nil {
return err
}
if t.Origin != nil {
if err := m.AddTransformerAnnotation(t.Origin); err != nil {
return err
}
}
m.DropEmpties()
}
return nil

View File

@@ -0,0 +1,29 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import "sigs.k8s.io/kustomize/api/konfig"
const (
// build annotations
BuildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds"
BuildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames"
BuildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes"
BuildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes"
BuildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces"
BuildAnnotationsRefBy = konfig.ConfigAnnoDomain + "/refBy"
BuildAnnotationsGenBehavior = konfig.ConfigAnnoDomain + "/generatorBehavior"
BuildAnnotationsGenAddHashSuffix = konfig.ConfigAnnoDomain + "/needsHashSuffix"
// 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"
// for keeping track of origin and transformer data
OriginAnnotationKey = "config.kubernetes.io/origin"
TransformerAnnotationKey = "alpha.config.kubernetes.io/transformations"
Enabled = "enabled"
)

View File

@@ -0,0 +1,67 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import (
"fmt"
"strings"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// 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

@@ -1,22 +0,0 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import "strings"
// PathSplitter splits a slash delimited string, permitting escaped slashes.
func PathSplitter(path string) []string {
ps := strings.Split(path, "/")
var res []string
res = append(res, ps[0])
for i := 1; i < len(ps); i++ {
last := len(res) - 1
if strings.HasSuffix(res[last], `\`) {
res[last] = strings.TrimSuffix(res[last], `\`) + "/" + ps[i]
} else {
res = append(res, ps[i])
}
}
return res
}

View File

@@ -0,0 +1,44 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
// StringSliceIndex returns the index of the str, else -1.
func StringSliceIndex(slice []string, str string) int {
for i := range slice {
if slice[i] == str {
return i
}
}
return -1
}
// StringSliceContains returns true if the slice has the string.
func StringSliceContains(slice []string, str string) bool {
for _, s := range slice {
if s == str {
return true
}
}
return false
}
// SameEndingSubSlice returns true if the slices end the same way, e.g.
// {"a", "b", "c"}, {"b", "c"} => true
// {"a", "b", "c"}, {"a", "b"} => false
// If one slice is empty and the other is not, return false.
func SameEndingSubSlice(shortest, longest []string) bool {
if len(shortest) > len(longest) {
longest, shortest = shortest, longest
}
diff := len(longest) - len(shortest)
if len(shortest) == 0 {
return diff == 0
}
for i := len(shortest) - 1; i >= 0; i-- {
if longest[i+diff] != shortest[i] {
return false
}
}
return true
}