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

@@ -4,11 +4,32 @@
package yaml
import (
"bytes"
"io"
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
)
const (
WideSequenceStyle SequenceIndentStyle = "wide"
CompactSequenceStyle SequenceIndentStyle = "compact"
DefaultIndent = 2
// BareSeqNodeWrappingKey kyaml uses reader annotations to track resources, it is not possible to
// add them to bare sequence nodes, this key is used to wrap such bare
// sequence nodes into map node, byteio_writer unwraps it while writing back
BareSeqNodeWrappingKey = "bareSeqNodeWrappingKey"
)
// SeqIndentType holds the indentation style for sequence nodes
type SequenceIndentStyle string
// EncoderOptions are options that can be used to configure the encoder,
// do not expose new options without considerable justification
type EncoderOptions struct {
// SeqIndent is the indentation style for YAML Sequence nodes
SeqIndent SequenceIndentStyle
}
// Expose the yaml.v3 functions so this package can be used as a replacement
type Decoder = yaml.Decoder
@@ -21,15 +42,45 @@ type Style = yaml.Style
type TypeError = yaml.TypeError
type Unmarshaler = yaml.Unmarshaler
var Marshal = yaml.Marshal
var Marshal = func(in interface{}) ([]byte, error) {
var buf bytes.Buffer
err := NewEncoder(&buf).Encode(in)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var Unmarshal = yaml.Unmarshal
var NewDecoder = yaml.NewDecoder
var NewEncoder = func(w io.Writer) *yaml.Encoder {
e := yaml.NewEncoder(w)
e.SetIndent(2)
e.SetIndent(DefaultIndent)
e.CompactSeqIndent()
return e
}
// MarshalWithOptions marshals the input interface with provided options
func MarshalWithOptions(in interface{}, opts *EncoderOptions) ([]byte, error) {
var buf bytes.Buffer
err := NewEncoderWithOptions(&buf, opts).Encode(in)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// NewEncoderWithOptions returns the encoder with provided options
func NewEncoderWithOptions(w io.Writer, opts *EncoderOptions) *yaml.Encoder {
encoder := NewEncoder(w)
encoder.SetIndent(DefaultIndent)
if opts.SeqIndent == WideSequenceStyle {
encoder.DefaultSeqIndent()
} else {
encoder.CompactSeqIndent()
}
return encoder
}
var AliasNode yaml.Kind = yaml.AliasNode
var DocumentNode yaml.Kind = yaml.DocumentNode
var MappingNode yaml.Kind = yaml.MappingNode
@@ -42,3 +93,7 @@ var FoldedStyle yaml.Style = yaml.FoldedStyle
var LiteralStyle yaml.Style = yaml.LiteralStyle
var SingleQuotedStyle yaml.Style = yaml.SingleQuotedStyle
var TaggedStyle yaml.Style = yaml.TaggedStyle
const (
MergeTag = "!!merge"
)

View File

@@ -7,9 +7,9 @@ import (
"reflect"
"strings"
"github.com/go-openapi/spec"
y1_1 "gopkg.in/yaml.v2"
y1_2 "gopkg.in/yaml.v3"
"k8s.io/kube-openapi/pkg/validation/spec"
y1_2 "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
)
// typeToTag maps OpenAPI schema types to yaml 1.2 tags
@@ -45,6 +45,14 @@ func FormatNonStringStyle(node *Node, schema spec.Schema) {
default:
return
}
// if the node tag is null, make sure we don't add any non-null tags
// https://github.com/GoogleContainerTools/kpt/issues/2321
if node.Tag == NodeTagNull {
// must NOT quote null values
node.Style = 0
return
}
if tag, found := typeToTag[t]; found {
// make sure the right tag is set
node.Tag = tag

View File

@@ -10,8 +10,8 @@ import (
"strings"
"github.com/davecgh/go-spew/spew"
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
)
// Append creates an ElementAppender
@@ -424,12 +424,46 @@ func Lookup(path ...string) PathGetter {
return PathGetter{Path: path}
}
// Lookup returns a PathGetter to lookup a field by its path and create it if it doesn't already
// LookupCreate returns a PathGetter to lookup a field by its path and create it if it doesn't already
// exist.
func LookupCreate(kind yaml.Kind, path ...string) PathGetter {
return PathGetter{Path: path, Create: kind}
}
// ConventionalContainerPaths is a list of paths at which containers typically appear in workload APIs.
// It is intended for use with LookupFirstMatch.
var ConventionalContainerPaths = [][]string{
// e.g. Deployment, ReplicaSet, DaemonSet, Job, StatefulSet
{"spec", "template", "spec", "containers"},
// e.g. CronJob
{"spec", "jobTemplate", "spec", "template", "spec", "containers"},
// e.g. Pod
{"spec", "containers"},
// e.g. PodTemplate
{"template", "spec", "containers"},
}
// LookupFirstMatch returns a Filter for locating a value that may exist at one of several possible paths.
// For example, it can be used with ConventionalContainerPaths to find the containers field in a standard workload resource.
// If more than one of the paths exists in the resource, the first will be returned. If none exist,
// nil will be returned. If an error is encountered during lookup, it will be returned.
func LookupFirstMatch(paths [][]string) Filter {
return FilterFunc(func(object *RNode) (*RNode, error) {
var result *RNode
var err error
for _, path := range paths {
result, err = object.Pipe(PathGetter{Path: path})
if err != nil {
return nil, errors.Wrap(err)
}
if result != nil {
return result, nil
}
}
return nil, nil
})
}
// PathGetter returns the RNode under Path.
type PathGetter struct {
Kind string `yaml:"kind,omitempty"`
@@ -507,6 +541,9 @@ func (l PathGetter) getFilter(part, nextPart string, fieldPath *[]string) (Filte
case part == "-":
// part is a hyphen
return GetElementByIndex(-1), nil
case part == "*":
// PathGetter is not support for wildcard matching
return nil, errors.Errorf("wildcard is not supported in PathGetter")
case IsListIndex(part):
// part is surrounded by brackets
return l.elemFilter(part)
@@ -518,7 +555,6 @@ func (l PathGetter) getFilter(part, nextPart string, fieldPath *[]string) (Filte
}
func (l PathGetter) elemFilter(part string) (Filter, error) {
var match *RNode
name, value, err := SplitIndexNameValue(part)
if err != nil {
return nil, errors.Wrap(err)
@@ -533,10 +569,9 @@ func (l PathGetter) elemFilter(part string) (Filter, error) {
// append a ScalarNode
elem = NewScalarRNode(value)
elem.YNode().Style = l.Style
match = elem
} else {
// append a MappingNode
match = NewRNode(&yaml.Node{Kind: yaml.ScalarNode, Value: value, Style: l.Style})
match := NewRNode(&yaml.Node{Kind: yaml.ScalarNode, Value: value, Style: l.Style})
elem = NewRNode(&yaml.Node{
Kind: yaml.MappingNode,
Content: []*yaml.Node{{Kind: yaml.ScalarNode, Value: name}, match.YNode()},
@@ -578,6 +613,50 @@ func Set(value *RNode) FieldSetter {
return FieldSetter{Value: value}
}
// MapEntrySetter sets a map entry to a value. If it finds a key with the same
// value, it will override both Key and Value RNodes, including style and any
// other metadata. If it doesn't find the key, it will insert a new map entry.
// It will set the field, even if it's empty or nil, unlike the FieldSetter.
// This is useful for rebuilding some pre-existing RNode structure.
type MapEntrySetter struct {
// Name is the name of the field or key to lookup in a MappingNode.
// If Name is unspecified, it will use the Key's Value
Name string `yaml:"name,omitempty"`
// Value is the value to set.
Value *RNode `yaml:"value,omitempty"`
// Key is the map key to set.
Key *RNode `yaml:"key,omitempty"`
}
func (s MapEntrySetter) Filter(rn *RNode) (*RNode, error) {
if rn == nil {
return nil, errors.Errorf("Can't set map entry on a nil RNode")
}
if err := ErrorIfInvalid(rn, yaml.MappingNode); err != nil {
return nil, err
}
if s.Name == "" {
s.Name = GetValue(s.Key)
}
for i := 0; i < len(rn.Content()); i = IncrementFieldIndex(i) {
isMatchingField := rn.Content()[i].Value == s.Name
if isMatchingField {
rn.Content()[i] = s.Key.YNode()
rn.Content()[i+1] = s.Value.YNode()
return rn, nil
}
}
// create the field
rn.YNode().Content = append(
rn.YNode().Content,
s.Key.YNode(),
s.Value.YNode())
return rn, nil
}
// FieldSetter sets a field or map entry to a value.
type FieldSetter struct {
Kind string `yaml:"kind,omitempty"`
@@ -607,6 +686,12 @@ func (s FieldSetter) Filter(rn *RNode) (*RNode, error) {
s.Value = NewScalarRNode(s.StringValue)
}
// need to set style for strings not recognized by yaml 1.1 to quoted if not previously set
// TODO: fix in upstream yaml library so this can be handled with yaml SetString
if s.Value.IsStringValue() && !s.OverrideStyle && s.Value.YNode().Style == 0 && IsYaml1_1NonString(s.Value.YNode()) {
s.Value.YNode().Style = yaml.DoubleQuotedStyle
}
if s.Name == "" {
if err := ErrorIfInvalid(rn, yaml.ScalarNode); err != nil {
return rn, err
@@ -748,6 +833,19 @@ func IsListIndex(p string) bool {
return strings.HasPrefix(p, "[") && strings.HasSuffix(p, "]")
}
// IsIdxNumber returns true if p is an index number.
// e.g. 1
func IsIdxNumber(p string) bool {
idx, err := strconv.Atoi(p)
return err == nil && idx >= 0
}
// IsWildcard returns true if p is matching every elements.
// e.g. "*"
func IsWildcard(p string) bool {
return p == "*"
}
// SplitIndexNameValue splits a lookup part Val index into the field name
// and field value to match.
// e.g. splits [name=nginx] into (name, nginx)

View File

@@ -1,6 +1,7 @@
// Code generated by k8scopy from k8s.io/apimachinery@v0.19.8; DO NOT EDIT.
// File content copied from k8s.io/apimachinery@v0.19.8/pkg/labels/zz_generated.deepcopy.go
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*

View File

@@ -4,8 +4,8 @@
package yaml
import (
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
)
// AnnotationClearer removes an annotation at metadata.annotations.

View File

@@ -5,6 +5,7 @@ package yaml
import (
"regexp"
"strconv"
"strings"
)
@@ -42,9 +43,10 @@ type PathMatcher struct {
// This is useful for if the nodes are to be printed in FlowStyle.
StripComments bool
val *RNode
field string
matchRegex string
val *RNode
field string
matchRegex string
indexNumber int
}
func (p *PathMatcher) stripComments(n *Node) {
@@ -79,14 +81,47 @@ func (p *PathMatcher) filter(rn *RNode) (*RNode, error) {
return p.val, nil
}
if IsIdxNumber(p.Path[0]) {
return p.doIndexSeq(rn)
}
if IsListIndex(p.Path[0]) {
// match seq elements
return p.doSeq(rn)
}
if IsWildcard(p.Path[0]) {
// match every elements (*)
return p.doMatchEvery(rn)
}
// match a field
return p.doField(rn)
}
func (p *PathMatcher) doMatchEvery(rn *RNode) (*RNode, error) {
if err := rn.VisitElements(p.visitEveryElem); err != nil {
return nil, err
}
return p.val, nil
}
func (p *PathMatcher) visitEveryElem(elem *RNode) error {
fieldName := p.Path[0]
// recurse on the matching element
pm := &PathMatcher{Path: p.Path[1:]}
add, err := pm.filter(elem)
for k, v := range pm.Matches {
p.Matches[k] = v
}
if err != nil || add == nil {
return err
}
p.append(fieldName, add.Content()...)
return nil
}
func (p *PathMatcher) doField(rn *RNode) (*RNode, error) {
// lookup the field
field, err := rn.Pipe(Get(p.Path[0]))
@@ -102,6 +137,36 @@ func (p *PathMatcher) doField(rn *RNode) (*RNode, error) {
return p.val, err
}
// doIndexSeq iterates over a sequence and appends elements matching the index p.Val
func (p *PathMatcher) doIndexSeq(rn *RNode) (*RNode, error) {
// parse to index number
idx, err := strconv.Atoi(p.Path[0])
if err != nil {
return nil, err
}
p.indexNumber = idx
elements, err := rn.Elements()
if err != nil {
return nil, err
}
// get target element
element := elements[idx]
// recurse on the matching element
pm := &PathMatcher{Path: p.Path[1:]}
add, err := pm.filter(element)
for k, v := range pm.Matches {
p.Matches[k] = v
}
if err != nil || add == nil {
return nil, err
}
p.append("", add.Content()...)
return p.val, nil
}
// doSeq iterates over a sequence and appends elements matching the path regex to p.Val
func (p *PathMatcher) doSeq(rn *RNode) (*RNode, error) {
// parse the field + match pair

View File

@@ -12,8 +12,10 @@ import (
"strconv"
"strings"
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
"sigs.k8s.io/kustomize/kyaml/sliceutil"
"sigs.k8s.io/kustomize/kyaml/utils"
"sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels"
)
@@ -146,6 +148,50 @@ func NewMapRNode(values *map[string]string) *RNode {
return m
}
// SyncMapNodesOrder sorts the map node keys in 'to' node to match the order of
// map node keys in 'from' node, additional keys are moved to the end
func SyncMapNodesOrder(from, to *RNode) {
to.Copy()
res := &RNode{value: &yaml.Node{
Kind: to.YNode().Kind,
Style: to.YNode().Style,
Tag: to.YNode().Tag,
Anchor: to.YNode().Anchor,
Alias: to.YNode().Alias,
HeadComment: to.YNode().HeadComment,
LineComment: to.YNode().LineComment,
FootComment: to.YNode().FootComment,
Line: to.YNode().Line,
Column: to.YNode().Column,
}}
fromFieldNames, err := from.Fields()
if err != nil {
return
}
toFieldNames, err := to.Fields()
if err != nil {
return
}
for _, fieldName := range fromFieldNames {
if !sliceutil.Contains(toFieldNames, fieldName) {
continue
}
// append the common nodes in the order defined in 'from' node
res.value.Content = append(res.value.Content, to.Field(fieldName).Key.YNode(), to.Field(fieldName).Value.YNode())
toFieldNames = sliceutil.Remove(toFieldNames, fieldName)
}
for _, fieldName := range toFieldNames {
// append the residual nodes which are not present in 'from' node
res.value.Content = append(res.value.Content, to.Field(fieldName).Key.YNode(), to.Field(fieldName).Value.YNode())
}
to.SetYNode(res.YNode())
}
// NewRNode returns a new RNode pointer containing the provided Node.
func NewRNode(value *yaml.Node) *RNode {
return &RNode{value: value}
@@ -203,6 +249,11 @@ func (rn *RNode) IsNilOrEmpty() bool {
IsYNodeZero(rn.YNode())
}
// IsStringValue is true if the RNode is not nil and is scalar string node
func (rn *RNode) IsStringValue() bool {
return !rn.IsNil() && IsYNodeString(rn.YNode())
}
// GetMeta returns the ResourceMeta for an RNode
func (rn *RNode) GetMeta() (ResourceMeta, error) {
if IsMissingOrNull(rn) {
@@ -337,26 +388,83 @@ func (rn *RNode) SetYNode(node *yaml.Node) {
*rn.value = *node
}
// GetKind returns the kind.
// GetKind returns the kind, if it exists, else empty string.
func (rn *RNode) GetKind() string {
node, err := rn.Pipe(FieldMatcher{Name: KindField})
if err != nil {
return ""
if node := rn.getMapFieldValue(KindField); node != nil {
return node.Value
}
return GetValue(node)
return ""
}
// GetName returns the name.
// SetKind sets the kind.
func (rn *RNode) SetKind(k string) {
rn.SetMapField(NewScalarRNode(k), KindField)
}
// GetApiVersion returns the apiversion, if it exists, else empty string.
func (rn *RNode) GetApiVersion() string {
if node := rn.getMapFieldValue(APIVersionField); node != nil {
return node.Value
}
return ""
}
// SetApiVersion sets the apiVersion.
func (rn *RNode) SetApiVersion(av string) {
rn.SetMapField(NewScalarRNode(av), APIVersionField)
}
// getMapFieldValue returns the value (*yaml.Node) of a mapping field.
// The value might be nil. Also, the function returns nil, not an error,
// if this node is not a mapping node, or if this node does not have the
// given field, so this function cannot be used to make distinctions
// between these cases.
func (rn *RNode) getMapFieldValue(field string) *yaml.Node {
for i := 0; i < len(rn.Content()); i = IncrementFieldIndex(i) {
if rn.Content()[i].Value == field {
return rn.Content()[i+1]
}
}
return nil
}
// GetName returns the name, or empty string if
// field not found. The setter is more restrictive.
func (rn *RNode) GetName() string {
f := rn.Field(MetadataField)
return rn.getMetaStringField(NameField)
}
// getMetaStringField returns the value of a string field in metadata.
func (rn *RNode) getMetaStringField(fName string) string {
md := rn.getMetaData()
if md == nil {
return ""
}
f := md.Field(fName)
if f.IsNilOrEmpty() {
return ""
}
f = f.Value.Field(NameField)
if f.IsNilOrEmpty() {
return ""
return GetValue(f.Value)
}
// getMetaData returns the RNode holding the value of the metadata field.
// Return nil if field not found (no error).
func (rn *RNode) getMetaData() *RNode {
if IsMissingOrNull(rn) {
return nil
}
return f.Value.YNode().Value
var n *RNode
if rn.YNode().Kind == DocumentNode {
// get the content if this is the document node
n = NewRNode(rn.Content()[0])
} else {
n = rn
}
mf := n.Field(MetadataField)
if mf.IsNilOrEmpty() {
return nil
}
return mf.Value
}
// SetName sets the metadata name field.
@@ -364,16 +472,14 @@ func (rn *RNode) SetName(name string) error {
return rn.SetMapField(NewScalarRNode(name), MetadataField, NameField)
}
// GetNamespace gets the metadata namespace field.
func (rn *RNode) GetNamespace() (string, error) {
meta, err := rn.GetMeta()
if err != nil {
return "", err
}
return meta.Namespace, nil
// GetNamespace gets the metadata namespace field, or empty string if
// field not found. The setter is more restrictive.
func (rn *RNode) GetNamespace() string {
return rn.getMetaStringField(NamespaceField)
}
// SetNamespace tries to set the metadata namespace field.
// SetNamespace tries to set the metadata namespace field. If the argument
// is empty, the field is dropped.
func (rn *RNode) SetNamespace(ns string) error {
meta, err := rn.Pipe(Lookup(MetadataField))
if err != nil {
@@ -390,12 +496,14 @@ func (rn *RNode) SetNamespace(ns string) error {
}
// GetAnnotations gets the metadata annotations field.
func (rn *RNode) GetAnnotations() (map[string]string, error) {
meta, err := rn.GetMeta()
if err != nil {
return nil, err
// If the field is missing, returns an empty map.
// Use another method to check for missing metadata.
func (rn *RNode) GetAnnotations() map[string]string {
meta := rn.getMetaData()
if meta == nil {
return make(map[string]string)
}
return meta.Annotations, nil
return rn.getMapFromMeta(meta, AnnotationsField)
}
// SetAnnotations tries to set the metadata annotations field.
@@ -404,12 +512,26 @@ func (rn *RNode) SetAnnotations(m map[string]string) error {
}
// GetLabels gets the metadata labels field.
func (rn *RNode) GetLabels() (map[string]string, error) {
meta, err := rn.GetMeta()
if err != nil {
return nil, err
// If the field is missing, returns an empty map.
// Use another method to check for missing metadata.
func (rn *RNode) GetLabels() map[string]string {
meta := rn.getMetaData()
if meta == nil {
return make(map[string]string)
}
return meta.Labels, nil
return rn.getMapFromMeta(meta, LabelsField)
}
// getMapFromMeta returns map, sometimes empty, from metadata.
func (rn *RNode) getMapFromMeta(meta *RNode, fName string) map[string]string {
result := make(map[string]string)
if f := meta.Field(fName); !f.IsNilOrEmpty() {
_ = f.Value.VisitFields(func(node *MapNode) error {
result[GetValue(node.Key)] = GetValue(node.Value)
return nil
})
}
return result
}
// SetLabels sets the metadata labels field.
@@ -419,7 +541,7 @@ func (rn *RNode) SetLabels(m map[string]string) error {
// This established proper quoting on string values, and sorts by key.
func (rn *RNode) setMapInMetadata(m map[string]string, field string) error {
meta, err := rn.Pipe(Lookup(MetadataField))
meta, err := rn.Pipe(LookupCreate(MappingNode, MetadataField))
if err != nil {
return err
}
@@ -475,6 +597,32 @@ func (rn *RNode) GetBinaryDataMap() map[string]string {
return result
}
// GetValidatedDataMap retrieves the data map and returns an error if the data
// map contains entries which are not included in the expectedKeys set.
func (rn *RNode) GetValidatedDataMap(expectedKeys []string) (map[string]string, error) {
dataMap := rn.GetDataMap()
err := rn.validateDataMap(dataMap, expectedKeys)
return dataMap, err
}
func (rn *RNode) validateDataMap(dataMap map[string]string, expectedKeys []string) error {
if dataMap == nil {
return fmt.Errorf("The datamap is unassigned")
}
for key := range dataMap {
found := false
for _, expected := range expectedKeys {
if expected == key {
found = true
}
}
if !found {
return fmt.Errorf("an unexpected key (%v) was found", key)
}
}
return nil
}
func (rn *RNode) SetDataMap(m map[string]string) {
if rn == nil {
log.Fatal("cannot set data map on nil Rnode")
@@ -761,6 +909,155 @@ func (rn *RNode) UnmarshalJSON(b []byte) error {
return nil
}
// DeAnchor inflates all YAML aliases with their anchor values.
// All YAML anchor data is permanently removed (feel free to call Copy first).
func (rn *RNode) DeAnchor() (err error) {
rn.value, err = deAnchor(rn.value)
return
}
// deAnchor removes all AliasNodes from the yaml.Node's tree, replacing
// them with what they point to. All Anchor fields (these are used to mark
// anchor definitions) are cleared.
func deAnchor(yn *yaml.Node) (res *yaml.Node, err error) {
if yn == nil {
return nil, nil
}
if yn.Anchor != "" {
// This node defines an anchor. Clear the field so that it
// doesn't show up when marshalling.
if yn.Kind == yaml.AliasNode {
// Maybe this is OK, but for now treating it as a bug.
return nil, fmt.Errorf(
"anchor %q defined using alias %v", yn.Anchor, yn.Alias)
}
yn.Anchor = ""
}
switch yn.Kind {
case yaml.ScalarNode:
return yn, nil
case yaml.AliasNode:
return deAnchor(yn.Alias)
case yaml.MappingNode:
toMerge, err := removeMergeTags(yn)
if err != nil {
return nil, err
}
err = mergeAll(yn, toMerge)
if err != nil {
return nil, err
}
fallthrough
case yaml.DocumentNode, yaml.SequenceNode:
for i := range yn.Content {
yn.Content[i], err = deAnchor(yn.Content[i])
if err != nil {
return nil, err
}
}
return yn, nil
default:
return nil, fmt.Errorf("cannot deAnchor kind %q", yn.Kind)
}
}
// isMerge returns if the node is tagged with !!merge
func isMerge(yn *yaml.Node) bool {
return yn.Tag == MergeTag
}
// findMergeValues receives either a MappingNode, a AliasNode or a potentially
// mixed list of MappingNodes and AliasNodes. It returns a list of MappingNodes.
func findMergeValues(yn *yaml.Node) ([]*yaml.Node, error) {
if yn == nil {
return []*yaml.Node{}, nil
}
switch yn.Kind {
case MappingNode:
return []*yaml.Node{yn}, nil
case AliasNode:
if yn.Alias != nil && yn.Alias.Kind != MappingNode {
return nil, errors.Errorf("invalid map merge: received alias for a non-map value")
}
return []*yaml.Node{yn.Alias}, nil
case SequenceNode:
mergeValues := []*yaml.Node{}
for i := 0; i < len(yn.Content); i++ {
if yn.Content[i].Kind == SequenceNode {
return nil, errors.Errorf("invalid map merge: received a nested sequence")
}
newMergeValues, err := findMergeValues(yn.Content[i])
if err != nil {
return nil, err
}
mergeValues = append(newMergeValues, mergeValues...)
}
return mergeValues, nil
default:
return nil, errors.Errorf("map merge requires map or sequence of maps as the value")
}
}
// getMergeTagValue receives a MappingNode yaml node, and it searches for
// merge tagged keys and return its value yaml node. If the key is duplicated,
// it fails.
func getMergeTagValue(yn *yaml.Node) (*yaml.Node, error) {
var result *yaml.Node
for i := 0; i < len(yn.Content); i += 2 {
key := yn.Content[i]
value := yn.Content[i+1]
if isMerge(key) {
if result != nil {
return nil, fmt.Errorf("duplicate merge key")
}
result = value
}
}
return result, nil
}
// removeMergeTags removes all merge tags and returns a ordered list of yaml
// nodes to merge and a error
func removeMergeTags(yn *yaml.Node) ([]*yaml.Node, error) {
if yn == nil || yn.Content == nil {
return nil, nil
}
if yn.Kind != yaml.MappingNode {
return nil, nil
}
value, err := getMergeTagValue(yn)
if err != nil {
return nil, err
}
toMerge, err := findMergeValues(value)
if err != nil {
return nil, err
}
err = NewRNode(yn).PipeE(Clear("<<"))
if err != nil {
return nil, err
}
return toMerge, nil
}
func mergeAll(yn *yaml.Node, toMerge []*yaml.Node) error {
// We only need to start with a copy of the existing node because we need to
// maintain duplicated keys and style
rn := NewRNode(yn).Copy()
toMerge = append(toMerge, yn)
for i := range toMerge {
rnToMerge := NewRNode(toMerge[i]).Copy()
err := rnToMerge.VisitFields(func(node *MapNode) error {
return rn.PipeE(MapEntrySetter{Key: node.Key, Value: node.Value})
})
if err != nil {
return err
}
}
*yn = *rn.value
return nil
}
// GetValidatedMetadata returns metadata after subjecting it to some tests.
func (rn *RNode) GetValidatedMetadata() (ResourceMeta, error) {
m, err := rn.GetMeta()
@@ -786,11 +1083,7 @@ func (rn *RNode) MatchesAnnotationSelector(selector string) (bool, error) {
if err != nil {
return false, err
}
slice, err := rn.GetAnnotations()
if err != nil {
return false, err
}
return s.Matches(labels.Set(slice)), nil
return s.Matches(labels.Set(rn.GetAnnotations())), nil
}
// MatchesLabelSelector returns true on a selector match to labels.
@@ -799,11 +1092,7 @@ func (rn *RNode) MatchesLabelSelector(selector string) (bool, error) {
if err != nil {
return false, err
}
slice, err := rn.GetLabels()
if err != nil {
return false, err
}
return s.Matches(labels.Set(slice)), nil
return s.Matches(labels.Set(rn.GetLabels())), nil
}
// HasNilEntryInList returns true if the RNode contains a list which has
@@ -887,7 +1176,6 @@ func checkKey(key string, elems []*Node) bool {
return count == len(elems)
}
// Deprecated: use pipes instead.
// GetSlice returns the contents of the slice field at the given path.
func (rn *RNode) GetSlice(path string) ([]interface{}, error) {
value, err := rn.GetFieldValue(path)
@@ -900,7 +1188,6 @@ func (rn *RNode) GetSlice(path string) ([]interface{}, error) {
return nil, fmt.Errorf("node %s is not a slice", path)
}
// Deprecated: use pipes instead.
// GetString returns the contents of the string field at the given path.
func (rn *RNode) GetString(path string) (string, error) {
value, err := rn.GetFieldValue(path)
@@ -913,7 +1200,6 @@ func (rn *RNode) GetString(path string) (string, error) {
return "", fmt.Errorf("node %s is not a string: %v", path, value)
}
// Deprecated: use slash paths instead.
// GetFieldValue finds period delimited fields.
// TODO: When doing kustomize var replacement, which is likely a
// a primary use of this function and the reason it returns interface{}
@@ -922,7 +1208,7 @@ func (rn *RNode) GetString(path string) (string, error) {
// assuming we keep the var feature in kustomize.
// The other end of this is: refvar.go:updateNodeValue.
func (rn *RNode) GetFieldValue(path string) (interface{}, error) {
fields := convertSliceIndex(strings.Split(path, "."))
fields := convertSliceIndex(utils.SmarterPathSplitter(path, "."))
rn, err := rn.Pipe(Lookup(fields...))
if err != nil {
return nil, err

View File

@@ -1,76 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package yaml
import "gopkg.in/yaml.v3"
func DoSerializationHacksOnNodes(nodes []*RNode) {
for _, node := range nodes {
DoSerializationHacks(node.YNode())
}
}
// DoSerializationHacks addresses a bug in yaml V3 upstream, it parses the yaml node,
// and rearranges the head comments of the children of sequence node.
// Refer to https://github.com/go-yaml/yaml/issues/587 for more details
func DoSerializationHacks(node *yaml.Node) {
switch node.Kind {
case DocumentNode:
for _, node := range node.Content {
DoSerializationHacks(node)
}
case MappingNode:
for _, node := range node.Content {
DoSerializationHacks(node)
}
case SequenceNode:
for _, node := range node.Content {
// for each child mapping node, transfer the head comment of it's
// first child scalar node to the head comment of itself
// This is necessary to address serialization issue
// https://github.com/go-yaml/yaml/issues/587 in go-yaml.v3
// Remove this hack when the issue has been resolved
if len(node.Content) > 0 && node.Content[0].Kind == ScalarNode {
node.HeadComment = node.Content[0].HeadComment
node.Content[0].HeadComment = ""
}
}
}
}
func UndoSerializationHacksOnNodes(nodes []*RNode) {
for _, node := range nodes {
UndoSerializationHacks(node.YNode())
}
}
// UndoSerializationHacks reverts the changes made by DoSerializationHacks
// Refer to https://github.com/go-yaml/yaml/issues/587 for more details
func UndoSerializationHacks(node *yaml.Node) {
switch node.Kind {
case DocumentNode:
for _, node := range node.Content {
DoSerializationHacks(node)
}
case MappingNode:
for _, node := range node.Content {
DoSerializationHacks(node)
}
case SequenceNode:
for _, node := range node.Content {
// revert the changes made in DoSerializationHacks
// This is necessary to address serialization issue
// https://github.com/go-yaml/yaml/issues/587 in go-yaml.v3
// Remove this hack when the issue has been resolved
if len(node.Content) > 0 && node.Content[0].Kind == ScalarNode {
node.Content[0].HeadComment = node.HeadComment
node.HeadComment = ""
}
}
}
}

View File

@@ -7,8 +7,8 @@ import (
"bytes"
"strings"
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
"sigs.k8s.io/kustomize/kyaml/sets"
)
@@ -139,16 +139,16 @@ type NameMeta struct {
type ResourceMeta struct {
TypeMeta `json:",inline" yaml:",inline"`
// ObjectMeta is the metadata field of a Resource
ObjectMeta `yaml:"metadata,omitempty"`
ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}
// ObjectMeta contains metadata about a Resource
type ObjectMeta struct {
NameMeta `json:",inline" yaml:",inline"`
// Labels is the metadata.labels field of a Resource
Labels map[string]string `yaml:"labels,omitempty"`
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
// Annotations is the metadata.annotations field of a Resource.
Annotations map[string]string `yaml:"annotations,omitempty"`
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
}
// GetIdentifier returns a ResourceIdentifier that includes
@@ -213,7 +213,10 @@ func String(node *yaml.Node, opts ...string) (string, error) {
b := &bytes.Buffer{}
e := NewEncoder(b)
err := e.Encode(node)
e.Close()
errClose := e.Close()
if err == nil {
err = errClose
}
val := b.String()
if optsSet.Has(Trim) {
val = strings.TrimSpace(val)

70
vendor/sigs.k8s.io/kustomize/kyaml/yaml/util.go generated vendored Normal file
View File

@@ -0,0 +1,70 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package yaml
import (
"strings"
)
// DeriveSeqIndentStyle derives the sequence indentation annotation value for the resource,
// originalYAML is the input yaml string,
// the style is decided by deriving the existing sequence indentation of first sequence node
func DeriveSeqIndentStyle(originalYAML string) string {
lines := strings.Split(originalYAML, "\n")
for i, line := range lines {
elems := strings.SplitN(line, "- ", 2)
if len(elems) != 2 {
continue
}
// prefix of "- " must be sequence of spaces
if strings.Trim(elems[0], " ") != "" {
continue
}
numSpacesBeforeSeqElem := len(elems[0])
// keyLine is the line before the first sequence element
keyLine := keyLineBeforeSeqElem(lines, i)
if keyLine == "" {
// there is no keyLine for this sequence node
// all of those lines are comments
continue
}
numSpacesBeforeKeyElem := len(keyLine) - len(strings.TrimLeft(keyLine, " "))
trimmedKeyLine := strings.Trim(keyLine, " ")
if strings.Count(trimmedKeyLine, ":") != 1 || !strings.HasSuffix(trimmedKeyLine, ":") {
// if the key line doesn't contain only one : that too at the end,
// this is not a sequence node, it is a wrapped sequence node string
// ignore it
continue
}
if numSpacesBeforeSeqElem == numSpacesBeforeKeyElem {
return string(CompactSequenceStyle)
}
if numSpacesBeforeSeqElem-numSpacesBeforeKeyElem == 2 {
return string(WideSequenceStyle)
}
}
return string(CompactSequenceStyle)
}
// keyLineBeforeSeqElem iterates through the lines before the first seqElement
// and tries to find the non-comment key line for the sequence node
func keyLineBeforeSeqElem(lines []string, seqElemIndex int) string {
// start with the previous line of sequence element
i := seqElemIndex - 1
for ; i >= 0; i-- {
line := lines[i]
trimmedLine := strings.Trim(line, " ")
if strings.HasPrefix(trimmedLine, "#") { // commented line
continue
}
// we have a non-commented line which can have a trailing comment
parts := strings.SplitN(line, "#", 2)
return parts[0] // throw away the trailing comment part
}
return ""
}