1616package translate
1717
1818import (
19+ "errors"
1920 "fmt"
21+ "reflect"
2022
23+ "github.com/stretchr/testify/assert/yaml"
2124 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
25+ "sigs.k8s.io/controller-runtime/pkg/client"
2226)
2327
2428const (
@@ -27,21 +31,136 @@ const (
2731 SecretProperySelector = "$.data.#"
2832)
2933
30- type Mapper struct {
31- deps DependencyRepo
34+ type mapContext struct {
35+ main client.Object
36+ m map [client.ObjectKey ]client.Object
37+ added []client.Object
38+ }
39+
40+ func newMapContext (main client.Object , objs ... client.Object ) * mapContext {
41+ m := map [client.ObjectKey ]client.Object {}
42+ for _ , obj := range objs {
43+ m [client .ObjectKeyFromObject (obj )] = obj
44+ }
45+ return & mapContext {main : main , m : m }
46+ }
47+
48+ func (mc * mapContext ) find (name string ) client.Object {
49+ key := client.ObjectKey {Name : name , Namespace : mc .main .GetNamespace ()}
50+ return mc .m [key ]
51+ }
52+
53+ func (mc * mapContext ) has (name string ) bool {
54+ return mc .find (name ) != nil
55+ }
56+
57+ func (mc * mapContext ) add (obj client.Object ) {
58+ mc .m [client .ObjectKeyFromObject (obj )] = obj
59+ mc .added = append (mc .added , obj )
60+ }
61+
62+ type mapper struct {
63+ * mapContext
3264 expand bool
3365}
3466
35- func (m * Mapper ) mapProperties (path []string , props , obj map [string ]any ) error {
67+ func newExpanderMapper (main client.Object , objs ... client.Object ) * mapper {
68+ return newMapper (true , main , objs ... )
69+ }
70+
71+ func newCollarserMapper (main client.Object , objs ... client.Object ) * mapper {
72+ return newMapper (false , main , objs ... )
73+ }
74+
75+ func newMapper (expand bool , main client.Object , objs ... client.Object ) * mapper {
76+ return & mapper {
77+ mapContext : newMapContext (main , objs ... ),
78+ expand : expand ,
79+ }
80+ }
81+
82+ func ExpandMappings (t * Translator , obj map [string ]any , main client.Object , objs ... client.Object ) ([]client.Object , error ) {
83+ em := newExpanderMapper (main , objs ... )
84+ mappingsYML := t .crd .definition .Annotations [APIMAppingsAnnotation ]
85+ if mappingsYML == "" {
86+ return []client.Object {}, nil
87+ }
88+ mappings := map [string ]any {}
89+ if err := yaml .Unmarshal ([]byte (mappingsYML ), mappings ); err != nil {
90+ return nil , fmt .Errorf ("failed to unmarshal mappings YAML: %w" , err )
91+ }
92+
93+ if err := em .expandMappingsAt (obj , mappings , "spec" , t .majorVersion ); err != nil {
94+ return nil , fmt .Errorf ("failed to map properties of spec from API to Kubernetes: %w" , err )
95+ }
96+ if err := em .expandMappingsAt (obj , mappings , "spec" , t .majorVersion , "entry" ); err != nil {
97+ return nil , fmt .Errorf ("failed to map properties of spec from API to Kubernetes: %w" , err )
98+ }
99+ if err := em .expandMappingsAt (obj , mappings , "status" , t .majorVersion ); err != nil {
100+ return nil , fmt .Errorf ("failed to map properties of status from API to Kubernetes: %w" , err )
101+ }
102+ return em .added , nil
103+ }
104+
105+ func CollapseMappings (t * Translator , spec map [string ]any , main client.Object , objs ... client.Object ) error {
106+ cm := newCollarserMapper (main , objs ... )
107+ mappingsYML := t .crd .definition .Annotations [APIMAppingsAnnotation ]
108+ if mappingsYML == "" {
109+ return nil
110+ }
111+ mappings := map [string ]any {}
112+ if err := yaml .Unmarshal ([]byte (mappingsYML ), mappings ); err != nil {
113+ return fmt .Errorf ("failed to unmarshal mappings YAML: %w" , err )
114+ }
115+ props , err := accessField [map [string ]any ](mappings ,
116+ "properties" , "spec" , "properties" , t .majorVersion , "properties" )
117+ if errors .Is (err , ErrNotFound ) {
118+ return nil
119+ }
120+ if err != nil {
121+ return fmt .Errorf ("failed to access the API mapping properties for the spec: %w" , err )
122+ }
123+ return cm .mapProperties ([]string {}, props , spec )
124+ }
125+
126+ func findEntryPathInTarget (targetType reflect.Type ) []string {
127+ if targetType .String () == "admin.CreateAlertConfigurationApiParams" {
128+ return []string {"GroupAlertsConfig" }
129+ }
130+ return []string {}
131+ }
132+
133+ func (m * mapper ) expandMappingsAt (obj , mappings map [string ]any , fields ... string ) error {
134+ expandedPath := []string {"properties" }
135+ for _ , field := range fields {
136+ expandedPath = append (expandedPath , field , "properties" )
137+ }
138+ props , err := accessField [map [string ]any ](mappings , expandedPath ... )
139+ if errors .Is (err , ErrNotFound ) {
140+ return nil
141+ }
142+ if err != nil {
143+ return fmt .Errorf ("failed to access the API mapping properties for %v: %w" , expandedPath , err )
144+ }
145+ field , err := accessField [map [string ]any ](obj , fields ... )
146+ if err != nil {
147+ return fmt .Errorf ("failed to access object's %v: %w" , fields , err )
148+ }
149+ if err := m .mapProperties ([]string {}, props , field ); err != nil {
150+ return fmt .Errorf ("failed to process properties from API into %v: %w" , fields , err )
151+ }
152+ return nil
153+ }
154+
155+ func (m * mapper ) mapProperties (path []string , props , obj map [string ]any ) error {
36156 for key , prop := range props {
37157 mapping , ok := (prop ).(map [string ]any )
38158 if ! ok {
39159 continue
40160 }
41161 subPath := append (path , key )
42162 if isReference (mapping ) {
43- err := m .mapReference (subPath , key , mapping , obj )
44- if err != nil {
163+ if err := m .mapReference (subPath , key , mapping , obj ); err != nil {
45164 return fmt .Errorf ("failed to process reference: %w" , err )
46165 }
47166 continue
@@ -54,20 +173,23 @@ func (m *Mapper) mapProperties(path []string, props, obj map[string]any) error {
54173 return fmt .Errorf ("failed to access %q: %w" , key , err )
55174 }
56175 if arrayField , ok := (rawField ).([]any ); ok {
57- return m .mapArray (subPath , mapping , arrayField )
176+ if err := m .mapArray (subPath , mapping , arrayField ); err != nil {
177+ return fmt .Errorf ("failed to process array mapping %q: %w" , key , err )
178+ }
179+ continue
58180 }
59181 subSpec , ok := (rawField ).(map [string ]any )
60182 if ! ok {
61183 return fmt .Errorf ("unsupported mapping of type %T" , rawField )
62184 }
63185 if err := m .mapObject (subPath , key , mapping , subSpec ); err != nil {
64- return fmt .Errorf ("failed to process mapping %q: %w" , key , err )
186+ return fmt .Errorf ("failed to process object mapping %q: %w" , key , err )
65187 }
66188 }
67189 return nil
68190}
69191
70- func (m * Mapper ) mapArray (path []string , mapping map [string ]any , list []any ) error {
192+ func (m * mapper ) mapArray (path []string , mapping map [string ]any , list []any ) error {
71193 mapItems , err := accessField [map [string ]any ](mapping , "items" , "properties" )
72194 if err != nil {
73195 return fmt .Errorf ("failed to access %q: %w" , base (path ), err )
@@ -89,7 +211,7 @@ func (m *Mapper) mapArray(path []string, mapping map[string]any, list []any) err
89211 return nil
90212}
91213
92- func (m * Mapper ) mapObject (path []string , mapName string , mapping , obj map [string ]any ) error {
214+ func (m * mapper ) mapObject (path []string , mapName string , mapping , obj map [string ]any ) error {
93215 if mapping ["properties" ] != nil {
94216 props , err := accessField [map [string ]any ](mapping , "properties" )
95217 if err != nil {
@@ -103,16 +225,16 @@ func (m *Mapper) mapObject(path []string, mapName string, mapping, obj map[strin
103225 return fmt .Errorf ("unsupported extension at %v with fields %v" , path , fieldsOf (mapping ))
104226}
105227
106- func (m * Mapper ) mapReference (path []string , mappingName string , mapping , obj map [string ]any ) error {
228+ func (m * mapper ) mapReference (path []string , mappingName string , mapping , obj map [string ]any ) error {
107229 rm := refMapping {}
108230 if err := fromUnstructured (& rm , mapping ); err != nil {
109231 return fmt .Errorf ("failed to parse a reference mapping: %w" , err )
110232 }
111233 ref := newRef (mappingName , & rm )
112234 if m .expand {
113- return ref .Expand (m .deps , path , obj )
235+ return ref .Expand (m .mapContext , path , obj )
114236 }
115- return ref .Collapse (m .deps , path , obj )
237+ return ref .Collapse (m .mapContext , path , obj )
116238}
117239
118240func entryMatchingMapping (mapName string , mapping map [string ]any , list []any , expand bool ) (string , map [string ]any ) {
0 commit comments