Skip to content

Commit 0d4ad8d

Browse files
committed
Separate unstructued to its own package
1 parent 1b4c49d commit 0d4ad8d

File tree

6 files changed

+314
-182
lines changed

6 files changed

+314
-182
lines changed

internal/v3/translate/mapping.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ import (
2121
"reflect"
2222

2323
"github.com/stretchr/testify/assert/yaml"
24-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2524
"sigs.k8s.io/controller-runtime/pkg/client"
25+
26+
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/v3/translate/unstructured"
2627
)
2728

2829
const (
@@ -112,9 +113,9 @@ func CollapseMappings(t *Translator, spec map[string]any, main client.Object, ob
112113
if err := yaml.Unmarshal([]byte(mappingsYML), mappings); err != nil {
113114
return fmt.Errorf("failed to unmarshal mappings YAML: %w", err)
114115
}
115-
props, err := accessField[map[string]any](mappings,
116+
props, err := unstructured.AccessField[map[string]any](mappings,
116117
"properties", "spec", "properties", t.majorVersion, "properties")
117-
if errors.Is(err, ErrNotFound) {
118+
if errors.Is(err, unstructured.ErrNotFound) {
118119
return nil
119120
}
120121
if err != nil {
@@ -135,14 +136,14 @@ func (m *mapper) expandMappingsAt(obj, mappings map[string]any, fields ...string
135136
for _, field := range fields {
136137
expandedPath = append(expandedPath, field, "properties")
137138
}
138-
props, err := accessField[map[string]any](mappings, expandedPath...)
139-
if errors.Is(err, ErrNotFound) {
139+
props, err := unstructured.AccessField[map[string]any](mappings, expandedPath...)
140+
if errors.Is(err, unstructured.ErrNotFound) {
140141
return nil
141142
}
142143
if err != nil {
143144
return fmt.Errorf("failed to access the API mapping properties for %v: %w", expandedPath, err)
144145
}
145-
field, err := accessField[map[string]any](obj, fields...)
146+
field, err := unstructured.AccessField[map[string]any](obj, fields...)
146147
if err != nil {
147148
return fmt.Errorf("failed to access object's %v: %w", fields, err)
148149
}
@@ -165,8 +166,8 @@ func (m *mapper) mapProperties(path []string, props, obj map[string]any) error {
165166
}
166167
continue
167168
}
168-
rawField, ok, err := unstructured.NestedFieldNoCopy(obj, key)
169-
if !ok {
169+
rawField, err := unstructured.AccessField[any](obj, key) // unstructured.NestedFieldNoCopy(obj, key)
170+
if errors.Is(err, unstructured.ErrNotFound) {
170171
continue
171172
}
172173
if err != nil {
@@ -190,9 +191,9 @@ func (m *mapper) mapProperties(path []string, props, obj map[string]any) error {
190191
}
191192

192193
func (m *mapper) mapArray(path []string, mapping map[string]any, list []any) error {
193-
mapItems, err := accessField[map[string]any](mapping, "items", "properties")
194+
mapItems, err := unstructured.AccessField[map[string]any](mapping, "items", "properties")
194195
if err != nil {
195-
return fmt.Errorf("failed to access %q: %w", base(path), err)
196+
return fmt.Errorf("failed to access %q: %w", unstructured.Base(path), err)
196197
}
197198
for mapName, mapItem := range mapItems {
198199
mapping, ok := (mapItem).(map[string]any)
@@ -213,7 +214,7 @@ func (m *mapper) mapArray(path []string, mapping map[string]any, list []any) err
213214

214215
func (m *mapper) mapObject(path []string, mapName string, mapping, obj map[string]any) error {
215216
if mapping["properties"] != nil {
216-
props, err := accessField[map[string]any](mapping, "properties")
217+
props, err := unstructured.AccessField[map[string]any](mapping, "properties")
217218
if err != nil {
218219
return fmt.Errorf("failed to access properties at %q: %w", path, err)
219220
}
@@ -222,12 +223,12 @@ func (m *mapper) mapObject(path []string, mapName string, mapping, obj map[strin
222223
if isReference(mapping) {
223224
return m.mapReference(path, mapName, mapping, obj)
224225
}
225-
return fmt.Errorf("unsupported extension at %v with fields %v", path, fieldsOf(mapping))
226+
return fmt.Errorf("unsupported extension at %v with fields %v", path, unstructured.FieldsOf(mapping))
226227
}
227228

228229
func (m *mapper) mapReference(path []string, mappingName string, mapping, obj map[string]any) error {
229230
rm := refMapping{}
230-
if err := fromUnstructured(&rm, mapping); err != nil {
231+
if err := unstructured.FromUnstructured(&rm, mapping); err != nil {
231232
return fmt.Errorf("failed to parse a reference mapping: %w", err)
232233
}
233234
ref := newRef(mappingName, &rm)
@@ -241,11 +242,11 @@ func entryMatchingMapping(mapName string, mapping map[string]any, list []any, ex
241242
key := mapName
242243
if expand {
243244
refMap := refMapping{}
244-
if err := fromUnstructured(&refMap, mapping); err != nil {
245+
if err := unstructured.FromUnstructured(&refMap, mapping); err != nil {
245246
return "", nil // not a ref, cannot reverse mapping dfrom API property name
246247
}
247248
path := resolveXPath(refMap.XOpenAPIMapping.Property)
248-
key = base(path)
249+
key = unstructured.Base(path)
249250
}
250251
return key, findByExistingKey(list, key)
251252
}

internal/v3/translate/ref.go

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"sigs.k8s.io/controller-runtime/pkg/client"
2828

2929
v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/v3/translate/samples/v1"
30+
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/v3/translate/unstructured"
3031
)
3132

3233
type EncodeDecodeFunc func(any) (any, error)
@@ -65,9 +66,9 @@ func newKubeObjectFactory[T any, P PtrClientObj[T]]() func(map[string]any) (clie
6566
}
6667
}
6768

68-
func initObject[T any](obj *T, unstructured map[string]any) (*T, error) {
69-
if unstructured != nil {
70-
if err := fromUnstructured(obj, unstructured); err != nil {
69+
func initObject[T any](obj *T, unstructuredObj map[string]any) (*T, error) {
70+
if unstructuredObj != nil {
71+
if err := unstructured.FromUnstructured(obj, unstructuredObj); err != nil {
7172
return nil, err
7273
}
7374
}
@@ -94,8 +95,8 @@ func newRef(name string, rm *refMapping) *namedRef {
9495

9596
func (ref *namedRef) Expand(mc *mapContext, pathHint []string, obj map[string]any) error {
9697
path := ref.pathToExpand(pathHint)
97-
rawValue, err := accessField[any](obj, base(path))
98-
if errors.Is(err, ErrNotFound) {
98+
rawValue, err := unstructured.AccessField[any](obj, unstructured.Base(path))
99+
if errors.Is(err, unstructured.ErrNotFound) {
99100
return nil
100101
}
101102
if err != nil {
@@ -127,7 +128,7 @@ func (ref *namedRef) Expand(mc *mapContext, pathHint []string, obj map[string]an
127128
refData := map[string]any{"name": dep.GetName()}
128129
if ref.XOpenAPIMapping.Property != "" {
129130
path := resolveXPath(ref.XOpenAPIMapping.Property)
130-
refData["key"] = base(path)
131+
refData["key"] = unstructured.Base(path)
131132
}
132133
obj[ref.name] = refData
133134
mc.add(dep)
@@ -137,7 +138,7 @@ func (ref *namedRef) Expand(mc *mapContext, pathHint []string, obj map[string]an
137138
func (ref *namedRef) pathToExpand(pathHint []string) []string {
138139
path := make([]string, len(pathHint))
139140
copy(path, pathHint)
140-
path[len(path)-1] = base(resolveXPath(ref.XOpenAPIMapping.Property))
141+
path[len(path)-1] = unstructured.Base(resolveXPath(ref.XOpenAPIMapping.Property))
141142
return path
142143
}
143144

@@ -153,8 +154,8 @@ func (ref *namedRef) Name(prefix string, path []string) string {
153154
}
154155

155156
func (ref *namedRef) Collapse(mc *mapContext, path []string, obj map[string]any) error {
156-
reference, err := accessField[map[string]any](obj, base(path))
157-
if errors.Is(err, ErrNotFound) {
157+
reference, err := unstructured.AccessField[map[string]any](obj, unstructured.Base(path))
158+
if errors.Is(err, unstructured.ErrNotFound) {
158159
return nil
159160
}
160161
if err != nil {
@@ -167,13 +168,13 @@ func (ref *namedRef) Collapse(mc *mapContext, path []string, obj map[string]any)
167168
targetPath := ref.XOpenAPIMapping.TargetPath()
168169
key, ok := reference["key"].(string)
169170
if !ok || key == "" {
170-
key = base(targetPath)
171+
key = unstructured.Base(targetPath)
171172
}
172173
value, err := ref.XKubernetesMapping.FetchReferencedValue(mc, key, reference)
173174
if err != nil {
174175
return fmt.Errorf("failed to fetch referenced value %s: %w", key, err)
175176
}
176-
return createField(obj, value, targetPath...)
177+
return unstructured.CreateField(obj, value, targetPath...)
177178
}
178179

179180
type kubeMapping struct {
@@ -213,7 +214,7 @@ func (km kubeMapping) FetchReferencedValue(mc *mapContext, target string, refere
213214
if refPath == "" {
214215
return nil, errors.New("cannot solve reference without a x-kubernetes-mapping.nameSelector")
215216
}
216-
refName, err := accessField[string](reference, asPath(refPath)...)
217+
refName, err := unstructured.AccessField[string](reference, unstructured.AsPath(refPath)...)
217218
if err != nil {
218219
return nil, fmt.Errorf("failed to access field %q at %v: %w", refPath, reference, err)
219220
}
@@ -225,18 +226,18 @@ func (km kubeMapping) FetchReferencedValue(mc *mapContext, target string, refere
225226
if km.Type.Kind != "" && !km.Equal(gvk) {
226227
return nil, fmt.Errorf("resource %q had to be a %q but got %q", refName, km.GVK(), gvk)
227228
}
228-
resourceMap, err := toUnstructured(resource)
229+
resourceMap, err := unstructured.ToUnstructured(resource)
229230
if err != nil {
230231
return nil, fmt.Errorf("failed to turn resource %q into an unestuctued map: %w", refName, err)
231232
}
232233
value, err := km.fetchFromProperties(resourceMap)
233-
if err != nil && !errors.Is(err, ErrNotFound) {
234+
if err != nil && !errors.Is(err, unstructured.ErrNotFound) {
234235
return nil, fmt.Errorf("failed to resolve reference properties: %w", err)
235236
}
236-
if errors.Is(err, ErrNotFound) {
237+
if errors.Is(err, unstructured.ErrNotFound) {
237238
var err error
238239
value, err = km.fetchFromPropertySelectors(resourceMap, target)
239-
if errors.Is(err, ErrNotFound) {
240+
if errors.Is(err, unstructured.ErrNotFound) {
240241
return nil, fmt.Errorf("failed to resolve reference properties or property selectors: %w", err)
241242
}
242243
if err != nil {
@@ -265,16 +266,16 @@ func (km kubeMapping) Encode(value any) (any, error) {
265266
func (km kubeMapping) fetchFromProperties(resource map[string]any) (any, error) {
266267
for _, prop := range km.Properties {
267268
path := resolveXPath(prop)
268-
value, err := accessField[any](resource, path...)
269-
if errors.Is(err, ErrNotFound) {
269+
value, err := unstructured.AccessField[any](resource, path...)
270+
if errors.Is(err, unstructured.ErrNotFound) {
270271
continue
271272
}
272273
if err != nil {
273274
return nil, fmt.Errorf("failed to access property as %v: %w", path, err)
274275
}
275276
return value, nil
276277
}
277-
return nil, ErrNotFound
278+
return nil, unstructured.ErrNotFound
278279
}
279280

280281
func (km kubeMapping) fetchFromPropertySelectors(resource map[string]any, target string) (any, error) {
@@ -284,46 +285,46 @@ func (km kubeMapping) fetchFromPropertySelectors(resource map[string]any, target
284285
prop = fmt.Sprintf("%s.%s", prop[:len(prop)-2], target)
285286
}
286287
path := resolveXPath(prop)
287-
value, err := accessField[any](resource, path...)
288-
if errors.Is(err, ErrNotFound) {
288+
value, err := unstructured.AccessField[any](resource, path...)
289+
if errors.Is(err, unstructured.ErrNotFound) {
289290
continue
290291
}
291292
if err != nil {
292293
return nil, fmt.Errorf("failed to access selected property as %v: %w", path, err)
293294
}
294295
return value, nil
295296
}
296-
return nil, ErrNotFound
297+
return nil, unstructured.ErrNotFound
297298
}
298299

299-
func (km kubeMapping) setAtPropertySelectors(gvr string, unstructured map[string]any, target string, value any) (client.Object, error) {
300+
func (km kubeMapping) setAtPropertySelectors(gvr string, obj map[string]any, target string, value any) (client.Object, error) {
300301
for _, selector := range km.PropertySelectors {
301302
prop := selector
302303
if strings.HasSuffix(prop, ".#") {
303304
targetPath := resolveXPath(target)
304-
prop = fmt.Sprintf("%s.%s", prop[:len(prop)-2], base(targetPath))
305+
prop = fmt.Sprintf("%s.%s", prop[:len(prop)-2], unstructured.Base(targetPath))
305306
}
306307
path := resolveXPath(prop)
307-
if err := createField(unstructured, value, path...); err != nil {
308+
if err := unstructured.CreateField(obj, value, path...); err != nil {
308309
return nil, fmt.Errorf("failed to set value at %q: %w", path, err)
309310
}
310-
obj, err := initializedKubeObjectFor(gvr, unstructured)
311+
obj, err := initializedKubeObjectFor(gvr, obj)
311312
if err != nil {
312313
return nil, fmt.Errorf("failed to initialize Kubernetes object: %w", err)
313314
}
314-
unstructuredCopy, err := toUnstructured(obj)
315+
unstructuredCopy, err := unstructured.ToUnstructured(obj)
315316
if err != nil {
316317
return nil, fmt.Errorf("failed to read Kubernetes object contents: %w", err)
317318
}
318-
valueCopy, err := accessField[any](unstructuredCopy, path...)
319+
valueCopy, err := unstructured.AccessField[any](unstructuredCopy, path...)
319320
if reflect.DeepEqual(value, valueCopy) {
320321
return obj, nil
321322
}
322-
if err != nil && !errors.Is(err, ErrNotFound) {
323+
if err != nil && !errors.Is(err, unstructured.ErrNotFound) {
323324
return nil, fmt.Errorf("failed to check Kubernetes object contents: %w", err)
324325
}
325326
}
326-
return nil, ErrNotFound
327+
return nil, unstructured.ErrNotFound
327328
}
328329

329330
type openAPIMapping struct {
@@ -337,17 +338,17 @@ func (oam openAPIMapping) TargetPath() []string {
337338

338339
func resolveXPath(xpath string) []string {
339340
if strings.HasPrefix(xpath, "$.") {
340-
return asPath(xpath[1:])
341+
return unstructured.AsPath(xpath[1:])
341342
}
342-
return asPath(xpath)
343+
return unstructured.AsPath(xpath)
343344
}
344345

345346
func unstructuredKubeObjectFor(gvr string) (map[string]any, error) {
346347
objCopy, err := kubeObjectFor(gvr)
347348
if err != nil {
348349
return nil, fmt.Errorf("failed to get unstructured kube object for GVR %q: %w", gvr, err)
349350
}
350-
return toUnstructured(objCopy)
351+
return unstructured.ToUnstructured(objCopy)
351352
}
352353

353354
func kubeObjectFor(gvr string) (client.Object, error) {

0 commit comments

Comments
 (0)