1 package getambassadorio_test
2
3 import (
4 "encoding/json"
5 "os"
6 "path"
7 "path/filepath"
8 "reflect"
9 "testing"
10
11 "github.com/pmezard/go-difflib/difflib"
12 "github.com/stretchr/testify/require"
13 "k8s.io/apimachinery/pkg/runtime"
14 "sigs.k8s.io/yaml"
15
16 getambassadorio "github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io"
17 "github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v1"
18 "github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v2"
19 "github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v3alpha1"
20 "github.com/emissary-ingress/emissary/v3/pkg/kates"
21 )
22
23 func marshalNormalized(t *testing.T, typed interface{}) string {
24 t.Helper()
25
26
27
28
29 bs, err := json.Marshal(typed)
30 require.NoError(t, err)
31
32 var untyped interface{}
33 err = json.Unmarshal(bs, &untyped)
34 require.NoError(t, err)
35
36
37
38 out, err := json.MarshalIndent(untyped, "", "\t")
39 require.NoError(t, err)
40
41 return string(out)
42 }
43
44 func requireEqualNormalized(t *testing.T, exp, act interface{}) {
45 t.Helper()
46 expStr := marshalNormalized(t, exp)
47 actStr := marshalNormalized(t, act)
48
49
50 if expStr != actStr {
51 diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
52 A: difflib.SplitLines(expStr),
53 B: difflib.SplitLines(actStr),
54 FromFile: "Expected",
55 FromDate: "",
56 ToFile: "Actual",
57 ToDate: "",
58 Context: 3,
59 })
60 t.Errorf("Not equal\n%s", diff)
61 }
62 }
63
64 func TestConvert(t *testing.T) {
65 testcases := map[string]map[string]interface{}{
66 "authsvc": {
67 "getambassador.io/v1": v1.AuthService{},
68 "getambassador.io/v2": v2.AuthService{},
69 "getambassador.io/v3alpha1": v3alpha1.AuthService{},
70 },
71 "devportals": {
72 "getambassador.io/v1": v1.DevPortal{},
73 "getambassador.io/v2": v2.DevPortal{},
74 "getambassador.io/v3alpha1": v3alpha1.DevPortal{},
75 },
76 "hosts": {
77 "getambassador.io/v2": v2.Host{},
78 "getambassador.io/v3alpha1": v3alpha1.Host{},
79 },
80 "logsvc": {
81 "getambassador.io/v1": v1.LogService{},
82 "getambassador.io/v2": v2.LogService{},
83 "getambassador.io/v3alpha1": v3alpha1.LogService{},
84 },
85 "mappings": {
86 "getambassador.io/v1": v1.Mapping{},
87 "getambassador.io/v2": v2.Mapping{},
88 "getambassador.io/v3alpha1": v3alpha1.Mapping{},
89 },
90 "modules": {
91 "getambassador.io/v1": v1.Module{},
92 "getambassador.io/v2": v2.Module{},
93 "getambassador.io/v3alpha1": v3alpha1.Module{},
94 },
95 "ratelimitsvc": {
96 "getambassador.io/v1": v1.RateLimitService{},
97 "getambassador.io/v2": v2.RateLimitService{},
98 "getambassador.io/v3alpha1": v3alpha1.RateLimitService{},
99 },
100 "tcpmappings": {
101 "getambassador.io/v1": v1.TCPMapping{},
102 "getambassador.io/v2": v2.TCPMapping{},
103 "getambassador.io/v3alpha1": v3alpha1.TCPMapping{},
104 },
105 "tlscontexts": {
106 "getambassador.io/v1": v1.TLSContext{},
107 "getambassador.io/v2": v2.TLSContext{},
108 "getambassador.io/v3alpha1": v3alpha1.TLSContext{},
109 },
110 "tracingsvc": {
111 "getambassador.io/v1": v1.TracingService{},
112 "getambassador.io/v2": v2.TracingService{},
113 "getambassador.io/v3alpha1": v3alpha1.TracingService{},
114 },
115 }
116
117 scheme := getambassadorio.BuildScheme()
118
119 v2.MangleAmbassadorID = false
120 t.Cleanup(func() {
121 v2.MangleAmbassadorID = true
122 })
123
124 t.Run("RoundTrip", func(t *testing.T) {
125 t.Parallel()
126 for typename := range testcases {
127 typename := typename
128 t.Run(typename, func(t *testing.T) {
129 t.Parallel()
130 for mainAPIVersion := range testcases[typename] {
131 for throughAPIVersion := range testcases[typename] {
132 if mainAPIVersion == throughAPIVersion {
133 continue
134 }
135 mainAPIVersion := mainAPIVersion
136 throughAPIVersion := throughAPIVersion
137 testname := path.Base(mainAPIVersion) + "_through_" + path.Base(throughAPIVersion)
138 t.Run(testname, func(t *testing.T) {
139 t.Parallel()
140 inBytes, err := os.ReadFile(filepath.Join(path.Base(mainAPIVersion), "testdata", typename+".yaml"))
141 require.NoError(t, err)
142 inListPtr := reflect.New(reflect.SliceOf(reflect.TypeOf(testcases[typename][mainAPIVersion])))
143 require.NoError(t, yaml.Unmarshal(inBytes, inListPtr.Interface()))
144 inList := inListPtr.Elem()
145 listLen := inList.Len()
146
147 midList := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(testcases[typename][throughAPIVersion])), listLen, listLen)
148 for i := 0; i < listLen; i++ {
149 midList.Index(i).FieldByName("TypeMeta").FieldByName("APIVersion").Set(reflect.ValueOf(throughAPIVersion))
150 midList.Index(i).FieldByName("TypeMeta").FieldByName("Kind").Set(inList.Index(i).FieldByName("TypeMeta").FieldByName("Kind"))
151 require.NoError(t, kates.ConvertObject(scheme, inList.Index(i).Addr().Interface().(runtime.Object), midList.Index(i).Addr().Interface().(runtime.Object)))
152 }
153
154 outList := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(testcases[typename][mainAPIVersion])), listLen, listLen)
155 for i := 0; i < listLen; i++ {
156 outList.Index(i).FieldByName("TypeMeta").Set(inList.Index(i).FieldByName("TypeMeta"))
157 require.NoError(t, kates.ConvertObject(scheme, midList.Index(i).Addr().Interface().(runtime.Object), outList.Index(i).Addr().Interface().(runtime.Object)))
158 }
159
160 requireEqualNormalized(t, inList.Interface(), outList.Interface())
161 })
162 }
163 }
164 })
165 }
166 })
167 }
168
169 func TestConvertTracingService(t *testing.T) {
170
171 scheme := getambassadorio.BuildScheme()
172
173
174
175
176 o := &v2.TracingServiceSpec{}
177 err := scheme.Convert(&v3alpha1.TracingServiceSpec{
178 AmbassadorID: v3alpha1.AmbassadorID{},
179 CustomTags: []v3alpha1.TracingCustomTag{
180 {
181 Tag: "hola",
182 Header: &v3alpha1.TracingCustomTagTypeRequestHeader{
183 Name: "hola",
184 },
185 },
186 },
187 }, o, nil)
188 if err != nil {
189 t.Errorf("conversion failed. %v", err)
190 }
191 if len(o.V3CustomTags) != 1 {
192 t.Errorf("got %d; want 1", len(o.V3CustomTags))
193 }
194 if len(o.TagHeaders) != 0 {
195 t.Errorf("got %d; want 0", len(o.TagHeaders))
196 }
197
198
199 o2 := &v2.TracingServiceSpec{}
200 err = scheme.Convert(&v3alpha1.TracingServiceSpec{
201 AmbassadorID: v3alpha1.AmbassadorID{},
202 DeprecatedTagHeaders: []string{"hello"},
203 CustomTags: []v3alpha1.TracingCustomTag{
204 {
205 Tag: "hola",
206 Header: &v3alpha1.TracingCustomTagTypeRequestHeader{
207 Name: "hola",
208 },
209 },
210 {
211 Tag: "env",
212 Environment: &v3alpha1.TracingCustomTagTypeEnvironment{
213 Name: "env",
214 },
215 },
216 },
217 }, o2, nil)
218 if err != nil {
219 t.Errorf("conversion failed. %v", err)
220 }
221 if len(o2.V3CustomTags) != 2 {
222 t.Errorf("got %d; want 2", len(o2.V3CustomTags))
223 }
224 if len(o2.TagHeaders) != 0 {
225 t.Errorf("got %d; want 0", len(o2.TagHeaders))
226 }
227
228
229 o3 := &v2.TracingServiceSpec{}
230 err = scheme.Convert(&v3alpha1.TracingServiceSpec{
231 AmbassadorID: v3alpha1.AmbassadorID{},
232 DeprecatedTagHeaders: []string{"hello"},
233 }, o3, nil)
234 if err != nil {
235 t.Errorf("conversion failed. %v", err)
236 }
237 if len(o3.V3CustomTags) != 1 {
238 t.Errorf("got %d; want 1", len(o3.V3CustomTags))
239 }
240 if len(o3.TagHeaders) != 0 {
241 t.Errorf("got %d; want 0", len(o3.TagHeaders))
242 }
243
244
245
246
247 out := &v3alpha1.TracingServiceSpec{}
248 err = scheme.Convert(&v2.TracingServiceSpec{
249 AmbassadorID: v2.AmbassadorID{},
250 TagHeaders: []string{"hola"},
251 }, out, nil)
252 if err != nil {
253 t.Errorf("conversion failed. %v", err)
254 }
255 if len(out.CustomTags) != 1 {
256 t.Errorf("got %d; want 1", len(out.CustomTags))
257 }
258 if len(out.DeprecatedTagHeaders) != 0 {
259 t.Errorf("got %d; want 0", len(out.DeprecatedTagHeaders))
260 }
261
262
263 out2 := &v3alpha1.TracingServiceSpec{}
264 err = scheme.Convert(&v2.TracingServiceSpec{
265 AmbassadorID: v2.AmbassadorID{},
266 V3CustomTags: []v3alpha1.TracingCustomTag{
267 {
268 Tag: "hello",
269 Header: &v3alpha1.TracingCustomTagTypeRequestHeader{
270 Name: "hello",
271 },
272 },
273 },
274 }, out2, nil)
275 if err != nil {
276 t.Errorf("conversion failed. %v", err)
277 }
278 if len(out2.CustomTags) != 1 {
279 t.Errorf("got %d; want 1", len(out2.CustomTags))
280 }
281 if len(out2.DeprecatedTagHeaders) != 0 {
282 t.Errorf("got %d; want 0", len(out2.DeprecatedTagHeaders))
283 }
284
285
286 out3 := &v3alpha1.TracingServiceSpec{}
287 err = scheme.Convert(&v2.TracingServiceSpec{
288 AmbassadorID: v2.AmbassadorID{},
289 TagHeaders: []string{"hola"},
290 V3CustomTags: []v3alpha1.TracingCustomTag{
291 {
292 Tag: "hello",
293 Header: &v3alpha1.TracingCustomTagTypeRequestHeader{
294 Name: "hello",
295 },
296 },
297 {
298 Tag: "hello2",
299 Environment: &v3alpha1.TracingCustomTagTypeEnvironment{
300 Name: "hello2",
301 },
302 },
303 },
304 }, out3, nil)
305 if err != nil {
306 t.Errorf("conversion failed. %v", err)
307 }
308 if len(out3.CustomTags) != 2 {
309 t.Errorf("got %d; want 2", len(out3.CustomTags))
310 }
311 if len(out3.DeprecatedTagHeaders) != 0 {
312 t.Errorf("got %d; want 0", len(out3.DeprecatedTagHeaders))
313 }
314
315 }
316
View as plain text