...

Source file src/sigs.k8s.io/kustomize/api/filters/filtersutil/setters.go

Documentation: sigs.k8s.io/kustomize/api/filters/filtersutil

     1  // Copyright 2022 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package filtersutil
     5  
     6  import (
     7  	"sigs.k8s.io/kustomize/kyaml/yaml"
     8  )
     9  
    10  // SetFn is a function that accepts an RNode to possibly modify.
    11  type SetFn func(*yaml.RNode) error
    12  
    13  // SetScalar returns a SetFn to set a scalar value
    14  func SetScalar(value string) SetFn {
    15  	return SetEntry("", value, yaml.NodeTagEmpty)
    16  }
    17  
    18  // SetEntry returns a SetFn to set a field or a map entry to a value.
    19  // It can be used with an empty name to set both a value and a tag on a scalar node.
    20  // When setting only a value on a scalar node, use SetScalar instead.
    21  func SetEntry(name, value, tag string) SetFn {
    22  	n := &yaml.Node{
    23  		Kind:  yaml.ScalarNode,
    24  		Value: value,
    25  		Tag:   tag,
    26  	}
    27  	return func(node *yaml.RNode) error {
    28  		return node.PipeE(yaml.FieldSetter{
    29  			Name:  name,
    30  			Value: yaml.NewRNode(n),
    31  		})
    32  	}
    33  }
    34  
    35  type TrackableSetter struct {
    36  	// SetValueCallback will be invoked each time a field is set
    37  	setValueCallback func(name, value, tag string, node *yaml.RNode)
    38  }
    39  
    40  // WithMutationTracker registers a callback which will be invoked each time a field is mutated
    41  func (s *TrackableSetter) WithMutationTracker(callback func(key, value, tag string, node *yaml.RNode)) *TrackableSetter {
    42  	s.setValueCallback = callback
    43  	return s
    44  }
    45  
    46  // SetScalar returns a SetFn to set a scalar value.
    47  // if a mutation tracker has been registered, the tracker will be invoked each
    48  // time a scalar is set
    49  func (s TrackableSetter) SetScalar(value string) SetFn {
    50  	return s.SetEntry("", value, yaml.NodeTagEmpty)
    51  }
    52  
    53  // SetScalarIfEmpty returns a SetFn to set a scalar value only if it isn't already set.
    54  // If a mutation tracker has been registered, the tracker will be invoked each
    55  // time a scalar is actually set.
    56  func (s TrackableSetter) SetScalarIfEmpty(value string) SetFn {
    57  	return s.SetEntryIfEmpty("", value, yaml.NodeTagEmpty)
    58  }
    59  
    60  // SetEntry returns a SetFn to set a field or a map entry to a value.
    61  // It can be used with an empty name to set both a value and a tag on a scalar node.
    62  // When setting only a value on a scalar node, use SetScalar instead.
    63  // If a mutation tracker has been registered, the tracker will be invoked each
    64  // time an entry is set.
    65  func (s TrackableSetter) SetEntry(name, value, tag string) SetFn {
    66  	origSetEntry := SetEntry(name, value, tag)
    67  	return func(node *yaml.RNode) error {
    68  		if s.setValueCallback != nil {
    69  			s.setValueCallback(name, value, tag, node)
    70  		}
    71  		return origSetEntry(node)
    72  	}
    73  }
    74  
    75  // SetEntryIfEmpty returns a SetFn to set a field or a map entry to a value only if it isn't already set.
    76  // It can be used with an empty name to set both a value and a tag on a scalar node.
    77  // When setting only a value on a scalar node, use SetScalar instead.
    78  // If a mutation tracker has been registered, the tracker will be invoked each
    79  // time an entry is actually set.
    80  func (s TrackableSetter) SetEntryIfEmpty(key, value, tag string) SetFn {
    81  	origSetEntry := SetEntry(key, value, tag)
    82  	return func(node *yaml.RNode) error {
    83  		if hasExistingValue(node, key) {
    84  			return nil
    85  		}
    86  		if s.setValueCallback != nil {
    87  			s.setValueCallback(key, value, tag, node)
    88  		}
    89  		return origSetEntry(node)
    90  	}
    91  }
    92  
    93  func hasExistingValue(node *yaml.RNode, key string) bool {
    94  	if node.IsNilOrEmpty() {
    95  		return false
    96  	}
    97  	if err := yaml.ErrorIfInvalid(node, yaml.ScalarNode); err == nil {
    98  		return yaml.GetValue(node) != ""
    99  	}
   100  	entry := node.Field(key)
   101  	if entry.IsNilOrEmpty() {
   102  		return false
   103  	}
   104  	return yaml.GetValue(entry.Value) != ""
   105  }
   106  

View as plain text