1 package entrypoint_test
2
3 import (
4 "encoding/json"
5 "testing"
6
7 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/require"
9
10 "github.com/datawire/ambassador/v2/cmd/entrypoint"
11 v3bootstrap "github.com/datawire/ambassador/v2/pkg/api/envoy/config/bootstrap/v3"
12 v3 "github.com/datawire/ambassador/v2/pkg/api/envoy/type/v3"
13 "github.com/datawire/ambassador/v2/pkg/kates"
14 "github.com/datawire/ambassador/v2/pkg/snapshot/v1"
15 )
16
17 func AnySnapshot(_ *snapshot.Snapshot) bool {
18 return true
19 }
20
21 func AnyConfig(_ *v3bootstrap.Bootstrap) bool {
22 return true
23 }
24
25 func TestFake(t *testing.T) {
26 f := entrypoint.RunFake(t, entrypoint.FakeConfig{EnvoyConfig: true}, nil)
27 assert.NoError(t, f.UpsertFile("testdata/snapshot.yaml"))
28 f.AutoFlush(true)
29
30 snapshot, err := f.GetSnapshot(AnySnapshot)
31 require.NoError(t, err)
32 LogJSON(t, snapshot)
33
34 envoyConfig, err := f.GetEnvoyConfig(AnyConfig)
35 require.NoError(t, err)
36 LogJSON(t, envoyConfig)
37
38 assert.NoError(t, f.Delete("Mapping", "default", "foo"))
39
40 snapshot, err = f.GetSnapshot(AnySnapshot)
41 require.NoError(t, err)
42 LogJSON(t, snapshot)
43
44 envoyConfig, err = f.GetEnvoyConfig(AnyConfig)
45 require.NoError(t, err)
46 LogJSON(t, envoyConfig)
47
48
57
58
59
60
61 }
62
63 func assertRoutePresent(t *testing.T, envoyConfig *v3bootstrap.Bootstrap, cluster string, weight int) {
64 t.Helper()
65
66 listener := mustFindListenerByName(t, envoyConfig, "ambassador-listener-8080")
67 routes := mustFindRoutesToCluster(t, listener, cluster)
68
69 for _, r := range routes {
70 assert.Equal(t, uint32(weight), r.Match.RuntimeFraction.DefaultValue.Numerator)
71 assert.Equal(t, v3.FractionalPercent_HUNDRED, r.Match.RuntimeFraction.DefaultValue.Denominator)
72 }
73 }
74
75 func assertRouteNotPresent(t *testing.T, envoyConfig *v3bootstrap.Bootstrap, cluster string) {
76 t.Helper()
77
78 listener := mustFindListenerByName(t, envoyConfig, "ambassador-listener-8080")
79 routes := findRoutesToCluster(listener, cluster)
80
81 assert.Empty(t, routes)
82 }
83
84 func TestWeightWithCache(t *testing.T) {
85 get_envoy_config := func(f *entrypoint.Fake, want_foo bool, want_bar bool) (*v3bootstrap.Bootstrap, error) {
86 return f.GetEnvoyConfig(func(config *v3bootstrap.Bootstrap) bool {
87 c_foo := FindCluster(config, ClusterNameContains("cluster_foo_"))
88 c_bar := FindCluster(config, ClusterNameContains("cluster_bar_"))
89
90 has_foo := c_foo != nil
91 has_bar := c_bar != nil
92
93 return (has_foo == want_foo) && (has_bar == want_bar)
94 })
95 }
96
97 f := entrypoint.RunFake(t, entrypoint.FakeConfig{EnvoyConfig: true, DiagdDebug: false}, nil)
98 assert.NoError(t, f.UpsertYAML(`
99 ---
100 apiVersion: getambassador.io/v3alpha1
101 kind: Listener
102 metadata:
103 name: ambassador-listener-8080
104 namespace: default
105 spec:
106 port: 8080
107 protocol: HTTP
108 securityModel: XFP
109 hostBinding:
110 namespace:
111 from: ALL
112 ---
113 apiVersion: getambassador.io/v3alpha1
114 kind: Host
115 metadata:
116 name: test-host
117 namespace: default
118 spec:
119 mappingSelector:
120 matchLabels:
121 host: minimal
122 hostname: foo.example.com
123 requestPolicy:
124 insecure:
125 action: Route
126 ---
127 apiVersion: getambassador.io/v3alpha1
128 kind: Mapping
129 metadata:
130 name: mapping-foo
131 namespace: default
132 labels:
133 host: minimal
134 spec:
135 prefix: /foo/
136 service: foo.default
137 `))
138
139 f.Flush()
140
141
142 envoyConfig, err := get_envoy_config(f, true, false)
143 require.NoError(t, err)
144 assert.NotNil(t, envoyConfig)
145
146
147 assertRoutePresent(t, envoyConfig, "cluster_foo_default_default", 100)
148 assertRouteNotPresent(t, envoyConfig, "cluster_bar_default_default")
149
150
151 assert.NoError(t, f.UpsertYAML(`
152 ---
153 apiVersion: getambassador.io/v3alpha1
154 kind: Mapping
155 metadata:
156 name: mapping-bar
157 namespace: default
158 labels:
159 host: minimal
160 spec:
161 prefix: /foo/
162 service: bar.default
163 weight: 10
164 `))
165
166 f.Flush()
167
168
169 envoyConfig, err = get_envoy_config(f, true, true)
170 require.NoError(t, err)
171 assert.NotNil(t, envoyConfig)
172
173
174
175 assertRoutePresent(t, envoyConfig, "cluster_bar_default_default", 10)
176 assertRoutePresent(t, envoyConfig, "cluster_foo_default_default", 100)
177
178
179 assert.NoError(t, f.UpsertYAML(`
180 ---
181 apiVersion: getambassador.io/v3alpha1
182 kind: Mapping
183 metadata:
184 name: mapping-bar
185 namespace: default
186 labels:
187 host: minimal
188 spec:
189 prefix: /foo/
190 service: bar.default
191 weight: 50
192 `))
193
194 f.Flush()
195
196
197 envoyConfig, err = get_envoy_config(f, true, true)
198 require.NoError(t, err)
199 assert.NotNil(t, envoyConfig)
200
201
202 assertRoutePresent(t, envoyConfig, "cluster_bar_default_default", 50)
203 assertRoutePresent(t, envoyConfig, "cluster_foo_default_default", 100)
204
205 assert.NoError(t, f.Delete("Mapping", "default", "mapping-foo"))
206 f.Flush()
207
208
209 envoyConfig, err = get_envoy_config(f, false, true)
210 require.NoError(t, err)
211 assert.NotNil(t, envoyConfig)
212
213
214 assertRoutePresent(t, envoyConfig, "cluster_bar_default_default", 100)
215 assertRouteNotPresent(t, envoyConfig, "cluster_foo_default_default")
216
217
218 assert.NoError(t, f.UpsertYAML(`
219 ---
220 apiVersion: getambassador.io/v3alpha1
221 kind: Mapping
222 metadata:
223 name: mapping-bar
224 namespace: default
225 labels:
226 host: minimal
227 spec:
228 prefix: /foo/
229 service: bar.default
230 weight: 20
231 `))
232
233 f.Flush()
234
235
236
237 envoyConfig, err = get_envoy_config(f, false, true)
238 require.NoError(t, err)
239 assert.NotNil(t, envoyConfig)
240
241 assertRoutePresent(t, envoyConfig, "cluster_bar_default_default", 100)
242 assertRouteNotPresent(t, envoyConfig, "cluster_foo_default_default")
243
244
245 assert.NoError(t, f.UpsertYAML(`
246 ---
247 apiVersion: getambassador.io/v3alpha1
248 kind: Mapping
249 metadata:
250 name: mapping-foo
251 namespace: default
252 labels:
253 host: minimal
254 spec:
255 prefix: /foo/
256 service: foo.default
257 `))
258
259 f.Flush()
260
261
262 envoyConfig, err = get_envoy_config(f, true, true)
263 require.NoError(t, err)
264 assert.NotNil(t, envoyConfig)
265
266
267
268 assertRoutePresent(t, envoyConfig, "cluster_bar_default_default", 20)
269 assertRoutePresent(t, envoyConfig, "cluster_foo_default_default", 100)
270 }
271
272 func LogJSON(t testing.TB, obj interface{}) {
273 t.Helper()
274 bytes, err := json.MarshalIndent(obj, "", " ")
275 require.NoError(t, err)
276 t.Log(string(bytes))
277 }
278
279 func TestFakeIstioCert(t *testing.T) {
280
281 f := entrypoint.RunFake(t, entrypoint.FakeConfig{EnvoyConfig: false}, nil)
282 f.AutoFlush(true)
283
284 assert.NoError(t, f.UpsertFile("testdata/tls-snap.yaml"))
285
286
287
288 snapshot, err := f.GetSnapshot(AnySnapshot)
289 require.NoError(t, err)
290 k := snapshot.Kubernetes
291
292 if len(k.Secrets) != 1 {
293 t.Errorf("needed 1 secret, got %d", len(k.Secrets))
294 }
295
296 istioSecret := kates.Secret{
297 TypeMeta: kates.TypeMeta{
298 APIVersion: "v1",
299 Kind: "Secret",
300 },
301 ObjectMeta: kates.ObjectMeta{
302 Name: "test-istio-secret",
303 Namespace: "default",
304 },
305 Type: kates.SecretTypeTLS,
306 Data: map[string][]byte{
307 "tls.crt": k.Secrets[0].Data["tls.crt"],
308 "tls.key": k.Secrets[0].Data["tls.key"],
309 },
310 }
311
312 f.SendIstioCertUpdate(entrypoint.IstioCertUpdate{
313 Op: "update",
314 Name: "test-istio-secret",
315 Namespace: "default",
316 Secret: &istioSecret,
317 })
318
319 snapshot, err = f.GetSnapshot(AnySnapshot)
320 require.NoError(t, err)
321 k = snapshot.Kubernetes
322 LogJSON(t, k)
323
324 if len(k.Secrets) != 2 {
325 t.Errorf("needed 2 secrets, got %d", len(k.Secrets))
326 }
327 }
328
View as plain text