mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-12 01:14:22 +00:00
Parse metadata directly instead of struct serialization hack
This commit is contained in:
@@ -6,7 +6,6 @@ package yaml
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -70,6 +69,14 @@ func IsFieldEmpty(node *MapNode) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValue returns underlying yaml.Node Value field
|
||||||
|
func GetValue(node *RNode) string {
|
||||||
|
if IsEmpty(node) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return node.YNode().Value
|
||||||
|
}
|
||||||
|
|
||||||
func IsFieldNull(node *MapNode) bool {
|
func IsFieldNull(node *MapNode) bool {
|
||||||
return node != nil && node.Value != nil && node.Value.YNode() != nil &&
|
return node != nil && node.Value != nil && node.Value.YNode() != nil &&
|
||||||
node.Value.YNode().Tag == NullNodeTag
|
node.Value.YNode().Tag == NullNodeTag
|
||||||
@@ -280,23 +287,79 @@ func (r *ResourceIdentifier) GetKind() string {
|
|||||||
|
|
||||||
var ErrMissingMetadata = fmt.Errorf("missing Resource metadata")
|
var ErrMissingMetadata = fmt.Errorf("missing Resource metadata")
|
||||||
|
|
||||||
// GetMeta returns the ResourceMeta for a RNode
|
// Field names
|
||||||
|
const (
|
||||||
|
AnnotationsField = "annotations"
|
||||||
|
APIVersionField = "apiVersion"
|
||||||
|
KindField = "kind"
|
||||||
|
MetadataField = "metadata"
|
||||||
|
NameField = "name"
|
||||||
|
NamespaceField = "namespace"
|
||||||
|
LabelsField = "labels"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetMeta returns the ResourceMeta for an RNode
|
||||||
func (rn *RNode) GetMeta() (ResourceMeta, error) {
|
func (rn *RNode) GetMeta() (ResourceMeta, error) {
|
||||||
|
if IsEmpty(rn) {
|
||||||
|
return ResourceMeta{}, nil
|
||||||
|
}
|
||||||
|
missingMeta := true
|
||||||
|
n := rn
|
||||||
|
if n.YNode().Kind == DocumentNode {
|
||||||
|
// get the content is this is the document node
|
||||||
|
n = NewRNode(n.Content()[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't decode into the struct directly or it will fail on UTF-8 issues
|
||||||
|
// which appear in comments
|
||||||
m := ResourceMeta{}
|
m := ResourceMeta{}
|
||||||
b := &bytes.Buffer{}
|
|
||||||
e := NewEncoder(b)
|
// TODO: consider optimizing this parsing
|
||||||
if err := e.Encode(rn.YNode()); err != nil {
|
if f := n.Field(APIVersionField); !IsFieldEmpty(f) {
|
||||||
return m, errors.Wrap(err)
|
m.APIVersion = GetValue(f.Value)
|
||||||
|
missingMeta = false
|
||||||
}
|
}
|
||||||
if err := e.Close(); err != nil {
|
if f := n.Field(KindField); !IsFieldEmpty(f) {
|
||||||
return m, errors.Wrap(err)
|
m.Kind = GetValue(f.Value)
|
||||||
|
missingMeta = false
|
||||||
}
|
}
|
||||||
d := yaml.NewDecoder(b)
|
|
||||||
d.KnownFields(false) // only want to parse the metadata
|
mf := n.Field(MetadataField)
|
||||||
if err := d.Decode(&m); err != nil {
|
if IsFieldEmpty(mf) {
|
||||||
return m, errors.Wrap(err)
|
if missingMeta {
|
||||||
|
return m, ErrMissingMetadata
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
}
|
}
|
||||||
if reflect.DeepEqual(m, ResourceMeta{}) {
|
meta := mf.Value
|
||||||
|
|
||||||
|
if f := meta.Field(NameField); !IsFieldEmpty(f) {
|
||||||
|
m.Name = f.Value.YNode().Value
|
||||||
|
missingMeta = false
|
||||||
|
}
|
||||||
|
if f := meta.Field(NamespaceField); !IsFieldEmpty(f) {
|
||||||
|
m.Namespace = GetValue(f.Value)
|
||||||
|
missingMeta = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if f := meta.Field(LabelsField); !IsFieldEmpty(f) {
|
||||||
|
m.Labels = map[string]string{}
|
||||||
|
_ = f.Value.VisitFields(func(node *MapNode) error {
|
||||||
|
m.Labels[GetValue(node.Key)] = GetValue(node.Value)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
missingMeta = false
|
||||||
|
}
|
||||||
|
if f := meta.Field(AnnotationsField); !IsFieldEmpty(f) {
|
||||||
|
m.Annotations = map[string]string{}
|
||||||
|
_ = f.Value.VisitFields(func(node *MapNode) error {
|
||||||
|
m.Annotations[GetValue(node.Key)] = GetValue(node.Value)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
missingMeta = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if missingMeta {
|
||||||
return m, ErrMissingMetadata
|
return m, ErrMissingMetadata
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|||||||
49
kyaml/yaml/types_test.go
Normal file
49
kyaml/yaml/types_test.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test that non-UTF8 characters in comments don't cause failures
|
||||||
|
func TestRNode_GetMeta_UTF16(t *testing.T) {
|
||||||
|
sr, err := Parse(`apiVersion: rbac.istio.io/v1alpha1
|
||||||
|
kind: ServiceRole
|
||||||
|
metadata:
|
||||||
|
name: wildcard
|
||||||
|
namespace: default
|
||||||
|
# If set to [“*”], it refers to all services in the namespace
|
||||||
|
annotations:
|
||||||
|
foo: bar
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
# There is one service in default namespace, should not result in a validation error
|
||||||
|
# If set to [“*”], it refers to all services in the namespace
|
||||||
|
- services: ["*"]
|
||||||
|
methods: ["GET", "HEAD"]
|
||||||
|
`)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
actual, err := sr.GetMeta()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := ResourceMeta{
|
||||||
|
APIVersion: "rbac.istio.io/v1alpha1",
|
||||||
|
Kind: "ServiceRole",
|
||||||
|
ObjectMeta: ObjectMeta{
|
||||||
|
Name: "wildcard",
|
||||||
|
Namespace: "default",
|
||||||
|
Annotations: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, expected, actual) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user