feat: kubesphere 4.0 (#6115)

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
KubeSphere CI Bot
2024-09-06 11:05:52 +08:00
committed by GitHub
parent b5015ec7b9
commit 447a51f08b
8557 changed files with 546695 additions and 1146174 deletions

View File

@@ -6,8 +6,8 @@ package yaml
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"strconv"
"strings"
@@ -53,7 +53,7 @@ func Parse(value string) (*RNode, error) {
// ReadFile parses a single Resource from a yaml file.
// To parse multiple resources, consider a kio.ByteReader
func ReadFile(path string) (*RNode, error) {
b, err := ioutil.ReadFile(path)
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
@@ -66,7 +66,7 @@ func WriteFile(node *RNode, path string) error {
if err != nil {
return err
}
return ioutil.WriteFile(path, []byte(out), 0600)
return errors.WrapPrefixf(os.WriteFile(path, []byte(out), 0600), "writing RNode to file")
}
// UpdateFile reads the file at path, applies the filter to it, and write the result back.
@@ -242,11 +242,7 @@ func (rn *RNode) IsTaggedNull() bool {
// IsNilOrEmpty is true if the node is nil,
// has no YNode, or has YNode that appears empty.
func (rn *RNode) IsNilOrEmpty() bool {
return rn.IsNil() ||
IsYNodeTaggedNull(rn.YNode()) ||
IsYNodeEmptyMap(rn.YNode()) ||
IsYNodeEmptySeq(rn.YNode()) ||
IsYNodeZero(rn.YNode())
return rn.IsNil() || IsYNodeNilOrEmpty(rn.YNode())
}
// IsStringValue is true if the RNode is not nil and is scalar string node
@@ -420,12 +416,11 @@ func (rn *RNode) SetApiVersion(av string) {
// 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
var result *yaml.Node
visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
result = value
}, field)
return result
}
// GetName returns the name, or empty string if
@@ -440,31 +435,33 @@ func (rn *RNode) getMetaStringField(fName string) string {
if md == nil {
return ""
}
f := md.Field(fName)
if f.IsNilOrEmpty() {
return ""
}
return GetValue(f.Value)
var result string
visitMappingNodeFields(md.Content, func(key, value *yaml.Node) {
if !IsYNodeNilOrEmpty(value) {
result = value.Value
}
}, fName)
return result
}
// getMetaData returns the RNode holding the value of the metadata field.
// getMetaData returns the *yaml.Node of the metadata field.
// Return nil if field not found (no error).
func (rn *RNode) getMetaData() *RNode {
func (rn *RNode) getMetaData() *yaml.Node {
if IsMissingOrNull(rn) {
return nil
}
var n *RNode
content := rn.Content()
if rn.YNode().Kind == DocumentNode {
// get the content if this is the document node
n = NewRNode(rn.Content()[0])
} else {
n = rn
content = content[0].Content
}
mf := n.Field(MetadataField)
if mf.IsNilOrEmpty() {
return nil
}
return mf.Value
var mf *yaml.Node
visitMappingNodeFields(content, func(key, value *yaml.Node) {
if !IsYNodeNilOrEmpty(value) {
mf = value
}
}, MetadataField)
return mf
}
// SetName sets the metadata name field.
@@ -496,14 +493,14 @@ func (rn *RNode) SetNamespace(ns string) error {
}
// GetAnnotations gets the metadata annotations field.
// If the field is missing, returns an empty map.
// If the annotations 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 rn.getMapFromMeta(meta, AnnotationsField)
// If specific annotations are provided, then the map is
// restricted to only those entries with keys that match
// one of the specific annotations. If no annotations are
// provided, then the map will contain all entries.
func (rn *RNode) GetAnnotations(annotations ...string) map[string]string {
return rn.getMapFromMeta(AnnotationsField, annotations...)
}
// SetAnnotations tries to set the metadata annotations field.
@@ -512,24 +509,45 @@ func (rn *RNode) SetAnnotations(m map[string]string) error {
}
// GetLabels gets the metadata labels field.
// If the field is missing, returns an empty map.
// If the labels field is missing, returns an empty map.
// Use another method to check for missing metadata.
func (rn *RNode) GetLabels() map[string]string {
// If specific labels are provided, then the map is
// restricted to only those entries with keys that match
// one of the specific labels. If no labels are
// provided, then the map will contain all entries.
func (rn *RNode) GetLabels(labels ...string) map[string]string {
return rn.getMapFromMeta(LabelsField, labels...)
}
// getMapFromMeta returns a map, sometimes empty, from the fName
// field in the node's metadata field.
// If specific fields are provided, then the map is
// restricted to only those entries with keys that match
// one of the specific fields. If no fields are
// provided, then the map will contain all entries.
func (rn *RNode) getMapFromMeta(fName string, fields ...string) map[string]string {
meta := rn.getMetaData()
if meta == nil {
return make(map[string]string)
}
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
})
var result map[string]string
visitMappingNodeFields(meta.Content, func(_, fNameValue *yaml.Node) {
// fName is found in metadata; create the map from its content
expectedSize := len(fields)
if expectedSize == 0 {
expectedSize = len(fNameValue.Content) / 2 //nolint: gomnd
}
result = make(map[string]string, expectedSize)
visitMappingNodeFields(fNameValue.Content, func(key, value *yaml.Node) {
result[key.Value] = value.Value
}, fields...)
}, fName)
if result == nil {
return make(map[string]string)
}
return result
}
@@ -696,9 +714,9 @@ func (rn *RNode) Fields() ([]string, error) {
return nil, errors.Wrap(err)
}
var fields []string
for i := 0; i < len(rn.Content()); i += 2 {
fields = append(fields, rn.Content()[i].Value)
}
visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
fields = append(fields, key.Value)
})
return fields, nil
}
@@ -709,13 +727,12 @@ func (rn *RNode) FieldRNodes() ([]*RNode, error) {
return nil, errors.Wrap(err)
}
var fields []*RNode
for i := 0; i < len(rn.Content()); i += 2 {
yNode := rn.Content()[i]
visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
// for each key node in the input mapping node contents create equivalent rNode
rNode := &RNode{}
rNode.SetYNode(yNode)
rNode.SetYNode(key)
fields = append(fields, rNode)
}
})
return fields, nil
}
@@ -725,13 +742,11 @@ func (rn *RNode) Field(field string) *MapNode {
if rn.YNode().Kind != yaml.MappingNode {
return nil
}
for i := 0; i < len(rn.Content()); i = IncrementFieldIndex(i) {
isMatchingField := rn.Content()[i].Value == field
if isMatchingField {
return &MapNode{Key: NewRNode(rn.Content()[i]), Value: NewRNode(rn.Content()[i+1])}
}
}
return nil
var result *MapNode
visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
result = &MapNode{Key: NewRNode(key), Value: NewRNode(value)}
}, field)
return result
}
// VisitFields calls fn for each field in the RNode.
@@ -752,6 +767,59 @@ func (rn *RNode) VisitFields(fn func(node *MapNode) error) error {
return nil
}
// visitMappingNodeFields calls fn for fields in the content, in content order.
// The caller is responsible to ensure the node is a mapping node. If fieldNames
// are specified, then fn is called only for the fields that match the given
// fieldNames.
func visitMappingNodeFields(content []*yaml.Node, fn func(key, value *yaml.Node), fieldNames ...string) {
switch len(fieldNames) {
case 0: // visit all fields
visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
fn(key, value)
return true
})
case 1: // visit single field
visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
if key == nil {
return true
}
if fieldNames[0] == key.Value {
fn(key, value)
return false
}
return true
})
default: // visit specified fields
fieldsStillToVisit := make(map[string]bool, len(fieldNames))
for _, fieldName := range fieldNames {
fieldsStillToVisit[fieldName] = true
}
visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
if key == nil {
return true
}
if fieldsStillToVisit[key.Value] {
fn(key, value)
delete(fieldsStillToVisit, key.Value)
}
return len(fieldsStillToVisit) > 0
})
}
}
// visitFieldsWhileTrue calls fn for the fields in content, in content order,
// until either fn returns false or all fields have been visited. The caller
// should ensure that content is from a mapping node, or fits the same expected
// pattern (consecutive key/value entries in the slice).
func visitFieldsWhileTrue(content []*yaml.Node, fn func(key, value *yaml.Node, keyIndex int) bool) {
for i := 0; i < len(content); i += 2 {
continueVisiting := fn(content[i], content[i+1], i)
if !continueVisiting {
return
}
}
}
// Elements returns the list of elements in the RNode.
// Returns an error for non-SequenceNodes.
func (rn *RNode) Elements() ([]*RNode, error) {
@@ -937,7 +1005,11 @@ func deAnchor(yn *yaml.Node) (res *yaml.Node, err error) {
case yaml.ScalarNode:
return yn, nil
case yaml.AliasNode:
return deAnchor(yn.Alias)
result, err := deAnchor(yn.Alias)
if err != nil {
return nil, err
}
return CopyYNode(result), nil
case yaml.MappingNode:
toMerge, err := removeMergeTags(yn)
if err != nil {
@@ -1003,17 +1075,19 @@ func findMergeValues(yn *yaml.Node) ([]*yaml.Node, error) {
// 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]
var err error
visitFieldsWhileTrue(yn.Content, func(key, value *yaml.Node, _ int) bool {
if isMerge(key) {
if result != nil {
return nil, fmt.Errorf("duplicate merge key")
err = fmt.Errorf("duplicate merge key")
result = nil
return false
}
result = value
}
}
return result, nil
return true
})
return result, err
}
// removeMergeTags removes all merge tags and returns a ordered list of yaml