mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
131 lines
3.6 KiB
Go
131 lines
3.6 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Package sub substitutes strings in fields
|
|
package setters
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
)
|
|
|
|
var _ yaml.Filter = &fieldSetter{}
|
|
|
|
// fieldSetter sets part or all of a field value.
|
|
type fieldSetter struct {
|
|
// Name is the name of the setter to perform.
|
|
Name string
|
|
|
|
// Value is the value to set.
|
|
Value string
|
|
|
|
// Description, if specified will set 'description' for the field. Optional.
|
|
Description string
|
|
|
|
// SetBy, if specified will set 'setBy' for the field. Optional.
|
|
SetBy string
|
|
|
|
// Count is incremented by Filter for each field that is set.
|
|
Count int
|
|
}
|
|
|
|
// Filter implements yaml.Filter
|
|
func (fs *fieldSetter) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
|
switch object.YNode().Kind {
|
|
case yaml.DocumentNode:
|
|
// Document is the root of the object and always contains 1 node
|
|
return fs.Filter(yaml.NewRNode(object.YNode().Content[0]))
|
|
case yaml.MappingNode:
|
|
return object, object.VisitFields(func(node *yaml.MapNode) error {
|
|
// Traverse each field value
|
|
return node.Value.PipeE(fs)
|
|
})
|
|
case yaml.SequenceNode:
|
|
return object, object.VisitElements(func(node *yaml.RNode) error {
|
|
// Traverse each list element
|
|
return node.PipeE(fs)
|
|
})
|
|
case yaml.ScalarNode:
|
|
// Check if there is a setter matching the name
|
|
s, f, partial, err := fs.findSetter(object)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if s == nil {
|
|
// no matching setter
|
|
return object, nil
|
|
}
|
|
// set the field value
|
|
return object, fs.set(object, s, f, partial)
|
|
default:
|
|
return object, nil
|
|
}
|
|
}
|
|
|
|
// findPartialSetter finds the setter matching the name if one exists
|
|
func (fs *fieldSetter) findSetter(field *yaml.RNode) (
|
|
*fieldmeta.PartialFieldSetter, *fieldmeta.FieldMeta, bool, error) {
|
|
// check if there are any substitutions for this field
|
|
var fm = &fieldmeta.FieldMeta{}
|
|
if err := fm.Read(field); err != nil {
|
|
return nil, nil, false, err
|
|
}
|
|
if fs.SetBy != "" {
|
|
fm.Extensions.SetBy = fs.SetBy
|
|
}
|
|
if fs.Description != "" {
|
|
fm.Schema.Description = fs.Description
|
|
}
|
|
|
|
if fm.Extensions.FieldSetter != nil && fm.Extensions.FieldSetter.Name == fs.Name {
|
|
return fm.Extensions.FieldSetter, fm, false, nil
|
|
}
|
|
|
|
// check if there is a matching substitution
|
|
for i := range fm.Extensions.PartialFieldSetters {
|
|
if fm.Extensions.PartialFieldSetters[i].Name == fs.Name {
|
|
return &fm.Extensions.PartialFieldSetters[i], fm, true, nil
|
|
}
|
|
}
|
|
return nil, nil, false, nil
|
|
}
|
|
|
|
// set performs the substitution for the given field, substitution, and metadata
|
|
func (fs *fieldSetter) set(
|
|
field *yaml.RNode, s *fieldmeta.PartialFieldSetter,
|
|
f *fieldmeta.FieldMeta, partial bool) error {
|
|
if s.Value == fs.Value || !strings.Contains(field.YNode().Value, s.Value) {
|
|
// no substitutions necessary -- already substituted or doesn't have the set value
|
|
// which acts as a marker
|
|
return nil
|
|
}
|
|
|
|
// record that the config has been modified
|
|
fs.Count++
|
|
|
|
if !partial {
|
|
// full setter
|
|
field.YNode().Value = fs.Value
|
|
} else {
|
|
// replace the current value with the new value
|
|
field.YNode().Value = strings.ReplaceAll(field.YNode().Value, s.Value, fs.Value)
|
|
}
|
|
|
|
// be sure to set the tag to the matching type so the yaml doesn't incorrectly quote
|
|
// integers or booleans as strings
|
|
fType := fieldmeta.FieldValueType(f.Schema.Type[0])
|
|
if err := fType.Validate(field.YNode().Value); err != nil {
|
|
return err
|
|
}
|
|
field.YNode().Tag = fType.Tag()
|
|
|
|
// update the comment on the field
|
|
s.Value = fs.Value
|
|
if err := f.Write(field); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|