mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 01:50:55 +00:00
move setters to be available as libraries
This commit is contained in:
@@ -21,9 +21,9 @@ import (
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/sub"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/set"
|
||||
)
|
||||
|
||||
// NewSubRunner returns a command runner.
|
||||
@@ -55,8 +55,8 @@ func SubCommand(parent string) *cobra.Command {
|
||||
|
||||
type SubRunner struct {
|
||||
Command *cobra.Command
|
||||
Lookup sub.LookupSubstitutions
|
||||
Perform sub.PerformSubstitutions
|
||||
Lookup set.LookupSubstitutions
|
||||
Perform set.PerformSubstitutions
|
||||
}
|
||||
|
||||
func (r *SubRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
|
||||
@@ -17,8 +17,8 @@ package commands
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/sub"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/set"
|
||||
)
|
||||
|
||||
// NewSubSetRunner returns a command runner.
|
||||
@@ -62,7 +62,7 @@ func SubSetCommand(parent string) *cobra.Command {
|
||||
|
||||
type SubSetRunner struct {
|
||||
Command *cobra.Command
|
||||
Set sub.SetSubstitutionMarker
|
||||
Set set.SetSubstitutionMarker
|
||||
}
|
||||
|
||||
func (r *SubSetRunner) runE(c *cobra.Command, args []string) error {
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sub
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
var _ kio.Filter = &SetSubstitutionMarker{}
|
||||
|
||||
// Sub performs substitutions
|
||||
type SetSubstitutionMarker struct {
|
||||
// Marker is the marker to set
|
||||
Marker Marker
|
||||
|
||||
// ResourceMeta defines the Resource to set the marker on
|
||||
ResourceMeta yaml.ResourceMeta
|
||||
}
|
||||
|
||||
func (s *SetSubstitutionMarker) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
for i := range input {
|
||||
m, err := input[i].GetMeta()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.ResourceMeta.Name != "" && m.Name != s.ResourceMeta.Name {
|
||||
continue
|
||||
}
|
||||
if s.ResourceMeta.Kind != "" && m.Kind != s.ResourceMeta.Kind {
|
||||
continue
|
||||
}
|
||||
if err := input[i].PipeE(&s.Marker); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sub
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
var _ yaml.Filter = &Marker{}
|
||||
|
||||
// substituteResource substitutes a Marker value on a field
|
||||
type Marker struct {
|
||||
// Path is the path of the field to add the substitution for
|
||||
Field string
|
||||
|
||||
// Substitution is the substitution to add
|
||||
Substitution fieldmeta.Substitution
|
||||
|
||||
// PartialMatch if true will match if the Substitution value is a substring of the current
|
||||
// value.
|
||||
PartialMatch bool
|
||||
|
||||
Description string
|
||||
OwnedBy string
|
||||
Type string
|
||||
|
||||
// currentFieldName is the name of the current field being processed
|
||||
currentFieldName string
|
||||
}
|
||||
|
||||
// Filter performs the substitutions for a single object
|
||||
func (m *Marker) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
switch object.YNode().Kind {
|
||||
case yaml.DocumentNode:
|
||||
return m.Filter(yaml.NewRNode(object.YNode().Content[0]))
|
||||
case yaml.MappingNode:
|
||||
return object, object.VisitFields(func(node *yaml.MapNode) error {
|
||||
// set the current field name
|
||||
n := m.currentFieldName
|
||||
defer func() { m.currentFieldName = n }()
|
||||
m.currentFieldName = node.Key.YNode().Value
|
||||
_, err := m.Filter(node.Value)
|
||||
return err
|
||||
})
|
||||
case yaml.SequenceNode:
|
||||
return object, object.VisitElements(func(node *yaml.RNode) error {
|
||||
_, err := m.Filter(node)
|
||||
return err
|
||||
})
|
||||
case yaml.ScalarNode:
|
||||
if m.currentFieldName != m.Field {
|
||||
return object, nil
|
||||
}
|
||||
if err := m.createSub(object); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return object, nil
|
||||
default:
|
||||
return object, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (as *Marker) createSub(field *yaml.RNode) error {
|
||||
// doesn't match the supplied value
|
||||
if field.YNode().Value != as.Substitution.Value {
|
||||
if !as.PartialMatch || !strings.Contains(field.YNode().Value, as.Substitution.Value) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(field); err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
fm.OwnedBy = as.OwnedBy
|
||||
fm.Description = as.Description
|
||||
fm.Type = fieldmeta.FieldValueType(as.Type)
|
||||
if as.Substitution.Marker == "" {
|
||||
as.Substitution.Marker = "[MARKER]"
|
||||
}
|
||||
|
||||
found := false
|
||||
for i := range fm.Substitutions {
|
||||
s := fm.Substitutions[i]
|
||||
if s.Name == as.Substitution.Name {
|
||||
// update the substitution if we find it
|
||||
found = true
|
||||
fm.Substitutions[i] = as.Substitution
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// add the substitution if it wasn't found
|
||||
fm.Substitutions = append(fm.Substitutions, as.Substitution)
|
||||
}
|
||||
if err := fm.Write(field); err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sub
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
var _ kio.Filter = &PerformSubstitutions{}
|
||||
|
||||
// Sub performs substitutions
|
||||
type PerformSubstitutions struct {
|
||||
// Name is the name of the substitution to perform
|
||||
Name string
|
||||
|
||||
// NewValue is the substitution value
|
||||
NewValue string
|
||||
|
||||
// Override if set to true will re-substitute already fields with a new value
|
||||
Override bool
|
||||
|
||||
// Revert if set to true will substitute fields back to the marker value
|
||||
Revert bool
|
||||
|
||||
// Description, if set will annotate the field with a description.
|
||||
Description string
|
||||
|
||||
// OwnedBy, if set will annotate the field with an owner.
|
||||
OwnedBy string
|
||||
|
||||
// Count is the number of substitutions performed by Filter.
|
||||
Count int
|
||||
}
|
||||
|
||||
func (s *PerformSubstitutions) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
for i := range input {
|
||||
p := &performSubstitutions{
|
||||
Name: s.Name,
|
||||
Override: s.Override,
|
||||
Revert: s.Revert,
|
||||
NewValue: s.NewValue,
|
||||
OwnedBy: s.OwnedBy,
|
||||
Description: s.Description,
|
||||
}
|
||||
if err := input[i].PipeE(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Count += p.Count
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package sub substitutes strings in fields
|
||||
package sub
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
var _ yaml.Filter = &performSubstitutions{}
|
||||
|
||||
// substituteResource substitutes a Marker value on a field
|
||||
type performSubstitutions struct {
|
||||
// Name of the substitution to perform.
|
||||
Name string
|
||||
|
||||
// Override if set to true will replace previously substituted values
|
||||
Override bool
|
||||
|
||||
// Revert if set to true will undo previously substituted values
|
||||
Revert bool
|
||||
|
||||
// NewValue is the new value to set. Mutually exclusive with Revert.
|
||||
NewValue string
|
||||
|
||||
// Description, if set will annotate the field with a description.
|
||||
Description string
|
||||
|
||||
// OwnedBy, if set will annotate the field with an owner.
|
||||
OwnedBy string
|
||||
|
||||
// Count will be incremented for each substituted value.
|
||||
Count int
|
||||
}
|
||||
|
||||
// Filter performs the substitutions for a single object
|
||||
func (fs *performSubstitutions) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
switch object.YNode().Kind {
|
||||
case yaml.DocumentNode:
|
||||
return fs.Filter(yaml.NewRNode(object.YNode().Content[0]))
|
||||
case yaml.MappingNode:
|
||||
return object, object.VisitFields(func(node *yaml.MapNode) error {
|
||||
_, err := fs.Filter(node.Value)
|
||||
return err
|
||||
})
|
||||
case yaml.SequenceNode:
|
||||
return object, object.VisitElements(func(node *yaml.RNode) error {
|
||||
_, err := fs.Filter(node)
|
||||
return err
|
||||
})
|
||||
case yaml.ScalarNode:
|
||||
s, f, err := fs.findSub(object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s == nil {
|
||||
return object, nil
|
||||
}
|
||||
return object, fs.substitute(object, s, f)
|
||||
default:
|
||||
return object, nil
|
||||
}
|
||||
}
|
||||
|
||||
// findSub finds the substitution matching the name if one exists
|
||||
func (fs *performSubstitutions) findSub(field *yaml.RNode) (
|
||||
*fieldmeta.Substitution, *fieldmeta.FieldMeta, error) {
|
||||
// check if there are any substitutions for this field
|
||||
var fm = &fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(field); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if fs.OwnedBy != "" {
|
||||
fm.OwnedBy = fs.OwnedBy
|
||||
}
|
||||
if fs.Description != "" {
|
||||
fm.Description = fs.Description
|
||||
}
|
||||
|
||||
// check if there is a matching substitution
|
||||
for i := range fm.Substitutions {
|
||||
if fm.Substitutions[i].Name == fs.Name {
|
||||
// validate the value if we are not reverting to the marker.
|
||||
// markers are allowed to be invalid.
|
||||
// only validate if there is a substitution matching the name
|
||||
if !fs.Revert {
|
||||
if err := fm.Type.Validate(fs.NewValue); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return &fm.Substitutions[i], fm, nil
|
||||
}
|
||||
}
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// substitute performs the substitution for the given field, substitution, and metadata
|
||||
func (fs *performSubstitutions) substitute(
|
||||
field *yaml.RNode, s *fieldmeta.Substitution, f *fieldmeta.FieldMeta) error {
|
||||
// undo or override previous substitutions by substituting the marker back
|
||||
// NOTE: check if s.Value != "" so we never try to substitute the empty string back
|
||||
if (fs.Revert || fs.Override) && s.Value != "" {
|
||||
// revert to the marker value
|
||||
if strings.Contains(field.YNode().Value, s.Value) {
|
||||
// revert the substitution
|
||||
field.YNode().Value = strings.ReplaceAll(field.YNode().Value, s.Value, s.Marker)
|
||||
// only use the tag matching the type if the marker parses to that type
|
||||
field.YNode().Tag = f.Type.TagForValue(s.Marker)
|
||||
// record that the config has been modified
|
||||
}
|
||||
}
|
||||
if fs.Revert {
|
||||
fs.Count++
|
||||
s.Value = "" // value has been cleared and replaced with marker
|
||||
if err := f.Write(field); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.Value == fs.NewValue || !strings.Contains(field.YNode().Value, s.Marker) {
|
||||
// no substitutions necessary -- already substituted or doesn't have the marker
|
||||
return nil
|
||||
}
|
||||
|
||||
// replace the marker with the new value
|
||||
field.YNode().Value = strings.ReplaceAll(field.YNode().Value, s.Marker, fs.NewValue)
|
||||
// be sure to set the tag so the yaml doesn't incorrectly quote ints, bools or floats
|
||||
field.YNode().Tag = f.Type.Tag()
|
||||
field.YNode().Style = 0
|
||||
// record that the config has been modified
|
||||
fs.Count++
|
||||
|
||||
// update the comment on the field
|
||||
s.Value = fs.NewValue
|
||||
if err := f.Write(field); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sub
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
var _ kio.Filter = &LookupSubstitutions{}
|
||||
|
||||
// Sub performs substitutions
|
||||
type LookupSubstitutions struct {
|
||||
// Name is the name of the substitution to match. If unspecified, all substitutions will
|
||||
// be matched.
|
||||
Name string
|
||||
|
||||
// SubstitutionCounts are the aggregate substitutions matched.
|
||||
SubstitutionCounts []FieldSubstitutionCount
|
||||
}
|
||||
|
||||
type FieldSubstitutionCount struct {
|
||||
// Count is the number of substitutions possible to perform
|
||||
Count int
|
||||
|
||||
// CountComplete is the number of substitutions that have already been performed
|
||||
// independent of this object.
|
||||
CountComplete int
|
||||
|
||||
// FieldSubstitution is the substitution found
|
||||
FieldSubstitution
|
||||
}
|
||||
|
||||
func (l *LookupSubstitutions) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
subs := map[string]*FieldSubstitutionCount{}
|
||||
for i := range input {
|
||||
// lookup substitutions for this object
|
||||
ls := &lookupSubstitutions{Name: l.Name}
|
||||
if err := input[i].PipeE(ls); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// aggregate counts for each substitution
|
||||
for j := range ls.Substitutions {
|
||||
sub := ls.Substitutions[j]
|
||||
curr, found := subs[sub.Name]
|
||||
if !found {
|
||||
curr = &FieldSubstitutionCount{FieldSubstitution: sub}
|
||||
subs[sub.Name] = curr
|
||||
}
|
||||
curr.Count++
|
||||
if sub.CurrentValue != "" {
|
||||
curr.CountComplete++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pull out and sort the results
|
||||
for _, v := range subs {
|
||||
l.SubstitutionCounts = append(l.SubstitutionCounts, *v)
|
||||
}
|
||||
sort.Slice(l.SubstitutionCounts, func(i, j int) bool {
|
||||
return l.SubstitutionCounts[i].Name < l.SubstitutionCounts[j].Name
|
||||
})
|
||||
return input, nil
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sub
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
var _ yaml.Filter = &lookupSubstitutions{}
|
||||
|
||||
// substituteResource substitutes a Marker value on a field
|
||||
type lookupSubstitutions struct {
|
||||
// Name of the substitution to lookup. If unspecified lookup all substitutions.
|
||||
Name string
|
||||
|
||||
// FieldSubstitution is the list of substitutions that were found
|
||||
Substitutions []FieldSubstitution
|
||||
}
|
||||
|
||||
func (ls *lookupSubstitutions) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
switch object.YNode().Kind {
|
||||
case yaml.DocumentNode:
|
||||
return ls.Filter(yaml.NewRNode(object.YNode().Content[0]))
|
||||
case yaml.MappingNode:
|
||||
return object, object.VisitFields(func(node *yaml.MapNode) error {
|
||||
_, err := ls.Filter(node.Value)
|
||||
return err
|
||||
})
|
||||
case yaml.SequenceNode:
|
||||
return object, object.VisitElements(func(node *yaml.RNode) error {
|
||||
_, err := ls.Filter(node)
|
||||
return err
|
||||
})
|
||||
case yaml.ScalarNode:
|
||||
return object, ls.lookup(object)
|
||||
default:
|
||||
return object, nil
|
||||
}
|
||||
}
|
||||
|
||||
// lookup finds any substitutions for this field
|
||||
func (ls *lookupSubstitutions) lookup(field *yaml.RNode) error {
|
||||
// check if there is a substitution for this field
|
||||
var fm = &fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(field); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range fm.Substitutions {
|
||||
s := fm.Substitutions[i]
|
||||
if ls.Name == "" || ls.Name == s.Name {
|
||||
ls.Substitutions = append(ls.Substitutions, FieldSubstitution{
|
||||
Name: s.Name,
|
||||
CurrentValue: s.Value,
|
||||
Description: fm.Description,
|
||||
Marker: s.Marker,
|
||||
Type: fm.Type,
|
||||
OwnedBy: fm.OwnedBy,
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sub
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
)
|
||||
|
||||
// FieldSubstitution is a possible field substitution read from a field
|
||||
type FieldSubstitution struct {
|
||||
// Name is the name of the substitution
|
||||
Name string
|
||||
|
||||
// Description is a description of the fields current value
|
||||
Description string
|
||||
|
||||
// Value is the current substituted value for the field.
|
||||
CurrentValue string
|
||||
|
||||
// Type is the type of the substitution
|
||||
Type fieldmeta.FieldValueType
|
||||
|
||||
// Marker is the marker used
|
||||
Marker string
|
||||
|
||||
// OwnedBy, if set will annotate the field with an owner.
|
||||
OwnedBy string
|
||||
}
|
||||
Reference in New Issue
Block a user