update vendor

Signed-off-by: Roland.Ma <rolandma@yunify.com>
This commit is contained in:
Roland.Ma
2021-08-11 07:10:14 +00:00
parent a18f72b565
commit ea8f47c73a
2901 changed files with 269317 additions and 43103 deletions

View File

@@ -0,0 +1,385 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package walk
import (
"strings"
"github.com/go-errors/errors"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/sets"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// appendListNode will append the nodes from src to dst and return dst.
// src and dst should be both sequence node. key is used to call ElementSetter.
// ElementSetter will use key-value pair to find and set the element in sequence
// node.
func appendListNode(dst, src *yaml.RNode, keys []string) (*yaml.RNode, error) {
var err error
for _, elem := range src.Content() {
// If key is empty, we know this is a scalar value and we can directly set the
// node
if keys[0] == "" {
_, err = dst.Pipe(yaml.ElementSetter{
Element: elem,
Keys: []string{""},
Values: []string{elem.Value},
})
if err != nil {
return nil, err
}
continue
}
// we need to get the value for key so that we can find the element to set
// in sequence.
v := []string{}
for _, key := range keys {
tmpNode := yaml.NewRNode(elem)
valueNode, err := tmpNode.Pipe(yaml.Get(key))
if err != nil {
return nil, err
}
if valueNode.IsNil() {
// no key found, directly append to dst
err = dst.PipeE(yaml.Append(elem))
if err != nil {
return nil, err
}
continue
}
v = append(v, valueNode.YNode().Value)
}
// When there are multiple keys, ElementSetter appends the node to dst
// even if the output is already in dst. We remove the node from dst to
// prevent duplicates.
if len(keys) > 1 {
_, err = dst.Pipe(yaml.ElementSetter{
Keys: keys,
Values: v,
})
if err != nil {
return nil, err
}
}
// We use the key and value from elem to find the corresponding element in dst.
// Then we will use ElementSetter to replace the element with elem. If we cannot
// find the item, the element will be appended.
_, err = dst.Pipe(yaml.ElementSetter{
Element: elem,
Keys: keys,
Values: v,
})
if err != nil {
return nil, err
}
}
return dst, nil
}
// validateKeys returns a list of valid key-value pairs
// if secondary merge key values are missing, use only the available merge keys
func validateKeys(valuesList [][]string, values []string, keys []string) ([]string, []string) {
validKeys := make([]string, 0)
validValues := make([]string, 0)
validKeySet := sets.String{}
for _, values := range valuesList {
for i, v := range values {
if v != "" {
validKeySet.Insert(keys[i])
}
}
}
if validKeySet.Len() == 0 { // if values missing, fall back to primary keys
return keys, values
}
for _, k := range keys {
if validKeySet.Has(k) {
validKeys = append(validKeys, k)
}
}
for i, v := range values {
if v != "" || validKeySet.Has(keys[i]) {
validValues = append(validValues, v)
}
}
return validKeys, validValues
}
// mergeValues merges values together - e.g. if two containerPorts
// have the same port and targetPort but one has an empty protocol
// and the other doesn't, they are treated as the same containerPort
func mergeValues(valuesList [][]string) [][]string {
for i, values1 := range valuesList {
for j, values2 := range valuesList {
if matched, values := match(values1, values2); matched {
valuesList[i] = values
valuesList[j] = values
}
}
}
return valuesList
}
// two values match if they have at least one common element and
// corresponding elements only differ if one is an empty string
func match(values1 []string, values2 []string) (bool, []string) {
if len(values1) != len(values2) {
return false, nil
}
var commonElement bool
var res []string
for i := range values1 {
if values1[i] == values2[i] {
commonElement = true
res = append(res, values1[i])
continue
}
if values1[i] != "" && values2[i] != "" {
return false, nil
}
if values1[i] != "" {
res = append(res, values1[i])
} else {
res = append(res, values2[i])
}
}
return commonElement, res
}
// setAssociativeSequenceElements recursively set the elements in the list
func (l *Walker) setAssociativeSequenceElements(valuesList [][]string, keys []string, dest *yaml.RNode) (*yaml.RNode, error) {
// itemsToBeAdded contains the items that will be added to dest
itemsToBeAdded := yaml.NewListRNode()
var schema *openapi.ResourceSchema
if l.Schema != nil {
schema = l.Schema.Elements()
}
if len(keys) > 1 {
valuesList = mergeValues(valuesList)
}
// each element in valuesList is a list of values corresponding to the keys
// for example, for the following yaml:
// - containerPort: 8080
// protocol: UDP
// - containerPort: 8080
// protocol: TCP
// `keys` would be [containerPort, protocol]
// and `valuesList` would be [ [8080, UDP], [8080, TCP] ]
var validKeys []string
var validValues []string
for _, values := range valuesList {
if len(values) == 0 {
continue
}
validKeys, validValues = validateKeys(valuesList, values, keys)
val, err := Walker{
VisitKeysAsScalars: l.VisitKeysAsScalars,
InferAssociativeLists: l.InferAssociativeLists,
Visitor: l,
Schema: schema,
Sources: l.elementValueList(validKeys, validValues),
MergeOptions: l.MergeOptions,
}.Walk()
if err != nil {
return nil, err
}
exit := false
for i, key := range validKeys {
// delete the node from **dest** if it's null or empty
if yaml.IsMissingOrNull(val) || yaml.IsEmptyMap(val) {
_, err = dest.Pipe(yaml.ElementSetter{
Keys: validKeys,
Values: validValues,
})
if err != nil {
return nil, err
}
exit = true
} else if val.Field(key) == nil && validValues[i] != "" {
// make sure the key is set on the field
_, err = val.Pipe(yaml.SetField(key, yaml.NewScalarRNode(validValues[i])))
if err != nil {
return nil, err
}
}
}
if exit {
continue
}
// Add the val to the sequence. val will replace the item in the sequence if
// there is an item that matches all key-value pairs. Otherwise val will be appended
// the the sequence.
_, err = itemsToBeAdded.Pipe(yaml.ElementSetter{
Element: val.YNode(),
Keys: validKeys,
Values: validValues,
})
if err != nil {
return nil, err
}
}
var err error
if len(valuesList) > 0 {
if l.MergeOptions.ListIncreaseDirection == yaml.MergeOptionsListPrepend {
// items from patches are needed to be prepended. so we append the
// dest to itemsToBeAdded
dest, err = appendListNode(itemsToBeAdded, dest, validKeys)
} else {
// append the items
dest, err = appendListNode(dest, itemsToBeAdded, validKeys)
}
}
if err != nil {
return nil, err
}
// sequence is empty
if yaml.IsMissingOrNull(dest) {
return nil, nil
}
return dest, nil
}
func (l *Walker) walkAssociativeSequence() (*yaml.RNode, error) {
// may require initializing the dest node
dest, err := l.Sources.setDestNode(l.VisitList(l.Sources, l.Schema, AssociativeList))
if dest == nil || err != nil {
return nil, err
}
// get the merge key(s) from schema
var strategy string
var keys []string
if l.Schema != nil {
strategy, keys = l.Schema.PatchStrategyAndKeyList()
}
if strategy == "" && len(keys) == 0 { // neither strategy nor keys present in the schema -- infer the key
// find the list of elements we need to recursively walk
key, err := l.elementKey()
if err != nil {
return nil, err
}
if key != "" {
keys = append(keys, key)
}
}
// non-primitive associative list -- merge the elements
values := l.elementValues(keys)
if len(values) != 0 || len(keys) > 0 {
return l.setAssociativeSequenceElements(values, keys, dest)
}
// primitive associative list -- merge the values
return l.setAssociativeSequenceElements(l.elementPrimitiveValues(), []string{""}, dest)
}
// elementKey returns the merge key to use for the associative list
func (l Walker) elementKey() (string, error) {
var key string
for i := range l.Sources {
if l.Sources[i] != nil && len(l.Sources[i].Content()) > 0 {
newKey := l.Sources[i].GetAssociativeKey()
if key != "" && key != newKey {
return "", errors.Errorf(
"conflicting merge keys [%s,%s] for field %s",
key, newKey, strings.Join(l.Path, "."))
}
key = newKey
}
}
if key == "" {
return "", errors.Errorf("no merge key found for field %s",
strings.Join(l.Path, "."))
}
return key, nil
}
// elementValues returns a slice containing all values for the field across all elements
// from all sources.
// Return value slice is ordered using the original ordering from the elements, where
// elements missing from earlier sources appear later.
func (l Walker) elementValues(keys []string) [][]string {
// use slice to to keep elements in the original order
var returnValues [][]string
var seen sets.StringList
// if we are doing append, dest node should be the first.
// otherwise dest node should be the last.
beginIdx := 0
if l.MergeOptions.ListIncreaseDirection == yaml.MergeOptionsListPrepend {
beginIdx = 1
}
for i := range l.Sources {
src := l.Sources[(i+beginIdx)%len(l.Sources)]
if src == nil {
continue
}
// add the value of the field for each element
// don't check error, we know this is a list node
values, _ := src.ElementValuesList(keys)
for _, s := range values {
if len(s) == 0 || seen.Has(s) {
continue
}
returnValues = append(returnValues, s)
seen = seen.Insert(s)
}
}
return returnValues
}
// elementPrimitiveValues returns the primitive values in an associative list -- eg. finalizers
func (l Walker) elementPrimitiveValues() [][]string {
// use slice to to keep elements in the original order
var returnValues [][]string
seen := sets.String{}
// if we are doing append, dest node should be the first.
// otherwise dest node should be the last.
beginIdx := 0
if l.MergeOptions.ListIncreaseDirection == yaml.MergeOptionsListPrepend {
beginIdx = 1
}
for i := range l.Sources {
src := l.Sources[(i+beginIdx)%len(l.Sources)]
if src == nil {
continue
}
// add the value of the field for each element
// don't check error, we know this is a list node
for _, item := range src.YNode().Content {
if seen.Has(item.Value) {
continue
}
returnValues = append(returnValues, []string{item.Value})
seen.Insert(item.Value)
}
}
return returnValues
}
// fieldValue returns a slice containing each source's value for fieldName
func (l Walker) elementValueList(keys []string, values []string) []*yaml.RNode {
keys, values = validateKeys([][]string{values}, values, keys)
var fields []*yaml.RNode
for i := range l.Sources {
if l.Sources[i] == nil {
fields = append(fields, nil)
continue
}
fields = append(fields, l.Sources[i].ElementList(keys, values))
}
return fields
}

173
vendor/sigs.k8s.io/kustomize/kyaml/yaml/walk/map.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package walk
import (
"sort"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/sets"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// walkMap returns the value of VisitMap
//
// - call VisitMap
// - set the return value on l.Dest
// - walk each source field
// - set each source field value on l.Dest
func (l Walker) walkMap() (*yaml.RNode, error) {
// get the new map value
dest, err := l.Sources.setDestNode(l.VisitMap(l.Sources, l.Schema))
if dest == nil || err != nil {
return nil, err
}
// recursively set the field values on the map
for _, key := range l.fieldNames() {
var res *yaml.RNode
var keys []*yaml.RNode
if l.VisitKeysAsScalars {
// visit the map keys as if they were scalars,
// this is necessary if doing things such as copying
// comments
for i := range l.Sources {
// construct the sources from the keys
if l.Sources[i] == nil {
keys = append(keys, nil)
continue
}
field := l.Sources[i].Field(key)
if field == nil || yaml.IsMissingOrNull(field.Key) {
keys = append(keys, nil)
continue
}
keys = append(keys, field.Key)
}
// visit the sources as a scalar
// keys don't have any schema --pass in nil
res, err = l.Visitor.VisitScalar(keys, nil)
if err != nil {
return nil, err
}
}
var s *openapi.ResourceSchema
if l.Schema != nil {
s = l.Schema.Field(key)
}
fv, commentSch := l.fieldValue(key)
if commentSch != nil {
s = commentSch
}
val, err := Walker{
VisitKeysAsScalars: l.VisitKeysAsScalars,
InferAssociativeLists: l.InferAssociativeLists,
Visitor: l,
Schema: s,
Sources: fv,
MergeOptions: l.MergeOptions,
Path: append(l.Path, key)}.Walk()
if err != nil {
return nil, err
}
// transfer the comments of res to dest node
var comments yaml.Comments
if !yaml.IsMissingOrNull(res) {
comments = yaml.Comments{
LineComment: res.YNode().LineComment,
HeadComment: res.YNode().HeadComment,
FootComment: res.YNode().FootComment,
}
if len(keys) > 0 && !yaml.IsMissingOrNull(keys[DestIndex]) {
keys[DestIndex].YNode().HeadComment = res.YNode().HeadComment
keys[DestIndex].YNode().LineComment = res.YNode().LineComment
keys[DestIndex].YNode().FootComment = res.YNode().FootComment
}
}
// this handles empty and non-empty values
_, err = dest.Pipe(yaml.FieldSetter{Name: key, Comments: comments, Value: val})
if err != nil {
return nil, err
}
}
return dest, nil
}
// valueIfPresent returns node.Value if node is non-nil, otherwise returns nil
func (l Walker) valueIfPresent(node *yaml.MapNode) (*yaml.RNode, *openapi.ResourceSchema) {
if node == nil {
return nil, nil
}
// parse the schema for the field if present
var s *openapi.ResourceSchema
fm := fieldmeta.FieldMeta{}
var err error
// check the value for a schema
if err = fm.Read(node.Value); err == nil {
s = &openapi.ResourceSchema{Schema: &fm.Schema}
if fm.Schema.Ref.String() != "" {
r, err := openapi.Resolve(&fm.Schema.Ref, openapi.Schema())
if err == nil && r != nil {
s.Schema = r
}
}
}
// check the key for a schema -- this will be used
// when the value is a Sequence (comments are attached)
// to the key
if fm.IsEmpty() {
if err = fm.Read(node.Key); err == nil {
s = &openapi.ResourceSchema{Schema: &fm.Schema}
}
if fm.Schema.Ref.String() != "" {
r, err := openapi.Resolve(&fm.Schema.Ref, openapi.Schema())
if err == nil && r != nil {
s.Schema = r
}
}
}
return node.Value, s
}
// fieldNames returns a sorted slice containing the names of all fields that appear in any of
// the sources
func (l Walker) fieldNames() []string {
fields := sets.String{}
for _, s := range l.Sources {
if s == nil {
continue
}
// don't check error, we know this is a mapping node
sFields, _ := s.Fields()
fields.Insert(sFields...)
}
result := fields.List()
sort.Strings(result)
return result
}
// fieldValue returns a slice containing each source's value for fieldName
func (l Walker) fieldValue(fieldName string) ([]*yaml.RNode, *openapi.ResourceSchema) {
var fields []*yaml.RNode
var sch *openapi.ResourceSchema
for i := range l.Sources {
if l.Sources[i] == nil {
fields = append(fields, nil)
continue
}
field := l.Sources[i].Field(fieldName)
f, s := l.valueIfPresent(field)
fields = append(fields, f)
if sch == nil && !s.IsMissingOrNull() {
sch = s
}
}
return fields, sch
}

View File

@@ -0,0 +1,13 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package walk
import (
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// walkNonAssociativeSequence returns the value of VisitList
func (l Walker) walkNonAssociativeSequence() (*yaml.RNode, error) {
return l.VisitList(l.Sources, l.Schema, NonAssociateList)
}

11
vendor/sigs.k8s.io/kustomize/kyaml/yaml/walk/scalar.go generated vendored Normal file
View File

@@ -0,0 +1,11 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package walk
import "sigs.k8s.io/kustomize/kyaml/yaml"
// walkScalar returns the value of VisitScalar
func (l Walker) walkScalar() (*yaml.RNode, error) {
return l.VisitScalar(l.Sources, l.Schema)
}

View File

@@ -0,0 +1,28 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package walk
import (
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type ListKind int32
const (
AssociativeList ListKind = 1 + iota
NonAssociateList
)
// Visitor is invoked by walk with source and destination node pairs
type Visitor interface {
VisitMap(Sources, *openapi.ResourceSchema) (*yaml.RNode, error)
VisitScalar(Sources, *openapi.ResourceSchema) (*yaml.RNode, error)
VisitList(Sources, *openapi.ResourceSchema, ListKind) (*yaml.RNode, error)
}
// ClearNode is returned if GrepFilter should do nothing after calling Set
var ClearNode *yaml.RNode

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

@@ -0,0 +1,186 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package walk
import (
"fmt"
"os"
"strings"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/kustomize/kyaml/yaml/schema"
)
// Walker walks the Source RNode and modifies the RNode provided to GrepFilter.
type Walker struct {
// Visitor is invoked by GrepFilter
Visitor
Schema *openapi.ResourceSchema
// Source is the RNode to walk. All Source fields and associative list elements
// will be visited.
Sources Sources
// Path is the field path to the current Source Node.
Path []string
// InferAssociativeLists if set to true will infer merge strategies for
// fields which it doesn't have the schema based on the fields in the
// list elements.
InferAssociativeLists bool
// VisitKeysAsScalars if true will call VisitScalar on map entry keys,
// providing nil as the OpenAPI schema.
VisitKeysAsScalars bool
// MergeOptions is a struct to store options for merge
MergeOptions yaml.MergeOptions
}
// Kind returns the kind of the first non-null node in Sources.
func (l Walker) Kind() yaml.Kind {
for _, s := range l.Sources {
if !yaml.IsMissingOrNull(s) {
return s.YNode().Kind
}
}
return 0
}
// Walk will recursively traverse every item in the Sources and perform corresponding
// actions on them
func (l Walker) Walk() (*yaml.RNode, error) {
l.Schema = l.GetSchema()
// invoke the handler for the corresponding node type
switch l.Kind() {
case yaml.MappingNode:
if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.MappingNode, l.Sources...); err != nil {
return nil, err
}
return l.walkMap()
case yaml.SequenceNode:
if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.SequenceNode, l.Sources...); err != nil {
return nil, err
}
// AssociativeSequence means the items in the sequence are associative. They can be merged
// according to merge key.
if schema.IsAssociative(l.Schema, l.Sources, l.InferAssociativeLists) {
return l.walkAssociativeSequence()
}
return l.walkNonAssociativeSequence()
case yaml.ScalarNode:
if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.ScalarNode, l.Sources...); err != nil {
return nil, err
}
return l.walkScalar()
case 0:
// walk empty nodes as maps
return l.walkMap()
default:
return nil, nil
}
}
func (l Walker) GetSchema() *openapi.ResourceSchema {
for i := range l.Sources {
r := l.Sources[i]
if yaml.IsMissingOrNull(r) {
continue
}
fm := fieldmeta.FieldMeta{}
if err := fm.Read(r); err == nil && !fm.IsEmpty() {
// per-field schema, this is fine
if fm.Schema.Ref.String() != "" {
// resolve the reference
s, err := openapi.Resolve(&fm.Schema.Ref, openapi.Schema())
if err == nil && s != nil {
fm.Schema = *s
}
}
return &openapi.ResourceSchema{Schema: &fm.Schema}
}
}
if l.Schema != nil {
return l.Schema
}
for i := range l.Sources {
r := l.Sources[i]
if yaml.IsMissingOrNull(r) {
continue
}
m, _ := r.GetMeta()
if m.Kind == "" || m.APIVersion == "" {
continue
}
s := openapi.SchemaForResourceType(yaml.TypeMeta{Kind: m.Kind, APIVersion: m.APIVersion})
if s != nil {
return s
}
}
return nil
}
const (
DestIndex = iota
OriginIndex
UpdatedIndex
)
// Sources are a list of RNodes. First item is the dest node, followed by
// multiple source nodes.
type Sources []*yaml.RNode
// Dest returns the destination node
func (s Sources) Dest() *yaml.RNode {
if len(s) <= DestIndex {
return nil
}
return s[DestIndex]
}
// Origin returns the origin node
func (s Sources) Origin() *yaml.RNode {
if len(s) <= OriginIndex {
return nil
}
return s[OriginIndex]
}
// Updated returns the updated node
func (s Sources) Updated() *yaml.RNode {
if len(s) <= UpdatedIndex {
return nil
}
return s[UpdatedIndex]
}
func (s Sources) String() string {
var values []string
for i := range s {
str, err := s[i].String()
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
}
values = append(values, str)
}
return strings.Join(values, "\n")
}
// setDestNode sets the destination source node
func (s Sources) setDestNode(node *yaml.RNode, err error) (*yaml.RNode, error) {
if err != nil {
return nil, err
}
s[0] = node
return node, nil
}