1
16
17 package objectmeta
18
19 import (
20 "fmt"
21
22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
24 "k8s.io/apimachinery/pkg/runtime"
25 utiljson "k8s.io/apimachinery/pkg/util/json"
26 "k8s.io/apimachinery/pkg/util/validation/field"
27 kjson "sigs.k8s.io/json"
28 )
29
30
31 func GetObjectMeta(obj map[string]interface{}, dropMalformedFields bool) (*metav1.ObjectMeta, bool, error) {
32 meta, found, _, err := GetObjectMetaWithOptions(obj, ObjectMetaOptions{
33 DropMalformedFields: dropMalformedFields,
34 })
35 return meta, found, err
36 }
37
38
39 type ObjectMetaOptions struct {
40
41
42
43
44
45 DropMalformedFields bool
46
47
48 ReturnUnknownFieldPaths bool
49
50
51 ParentPath *field.Path
52 }
53
54
55
56
57
58
59
60 func GetObjectMetaWithOptions(obj map[string]interface{}, opts ObjectMetaOptions) (*metav1.ObjectMeta, bool, []string, error) {
61 metadata, found := obj["metadata"]
62 if !found {
63 return nil, false, nil, nil
64 }
65
66
67 objectMeta := &metav1.ObjectMeta{}
68 metadataBytes, err := utiljson.Marshal(metadata)
69 if err != nil {
70 return nil, false, nil, err
71 }
72 var unmarshalErr error
73 if opts.ReturnUnknownFieldPaths {
74 var strictErrs []error
75 strictErrs, unmarshalErr = kjson.UnmarshalStrict(metadataBytes, objectMeta)
76 if unmarshalErr == nil {
77 if len(strictErrs) > 0 {
78 unknownPaths := []string{}
79 prefix := opts.ParentPath.Child("metadata").String()
80 for _, err := range strictErrs {
81 if fieldPathErr, ok := err.(kjson.FieldError); ok {
82 unknownPaths = append(unknownPaths, prefix+"."+fieldPathErr.FieldPath())
83 }
84 }
85 return objectMeta, true, unknownPaths, nil
86 }
87 return objectMeta, true, nil, nil
88 }
89 } else {
90 if unmarshalErr = utiljson.Unmarshal(metadataBytes, objectMeta); unmarshalErr == nil {
91
92 return objectMeta, true, nil, nil
93 }
94 }
95 if !opts.DropMalformedFields {
96
97 return nil, true, nil, unmarshalErr
98 }
99
100 metadataMap, ok := metadata.(map[string]interface{})
101 if !ok {
102 return nil, false, nil, fmt.Errorf("invalid metadata: expected object, got %T", metadata)
103 }
104
105
106
107
108 accumulatedObjectMeta := &metav1.ObjectMeta{}
109 testObjectMeta := &metav1.ObjectMeta{}
110 var unknownFields []string
111 for k, v := range metadataMap {
112
113 if singleFieldBytes, err := utiljson.Marshal(map[string]interface{}{k: v}); err == nil {
114
115 if utiljson.Unmarshal(singleFieldBytes, testObjectMeta) == nil {
116
117 if opts.ReturnUnknownFieldPaths {
118 strictErrs, _ := kjson.UnmarshalStrict(singleFieldBytes, accumulatedObjectMeta)
119 if len(strictErrs) > 0 {
120 prefix := opts.ParentPath.Child("metadata").String()
121 for _, err := range strictErrs {
122 if fieldPathErr, ok := err.(kjson.FieldError); ok {
123 unknownFields = append(unknownFields, prefix+"."+fieldPathErr.FieldPath())
124 }
125 }
126 }
127 } else {
128 utiljson.Unmarshal(singleFieldBytes, accumulatedObjectMeta)
129 }
130 }
131 }
132 }
133
134 return accumulatedObjectMeta, true, unknownFields, nil
135 }
136
137
138 func SetObjectMeta(obj map[string]interface{}, objectMeta *metav1.ObjectMeta) error {
139 if objectMeta == nil {
140 unstructured.RemoveNestedField(obj, "metadata")
141 return nil
142 }
143
144 metadata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objectMeta)
145 if err != nil {
146 return err
147 }
148
149 obj["metadata"] = metadata
150 return nil
151 }
152
View as plain text