-
Notifications
You must be signed in to change notification settings - Fork 7.6k
/
config.go
411 lines (336 loc) · 14.8 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package istio
import (
"fmt"
"os"
"path"
"path/filepath"
"strings"
corev1 "k8s.io/api/core/v1"
"istio.io/istio/pkg/test"
"istio.io/istio/pkg/test/env"
"istio.io/istio/pkg/test/framework/components/namespace"
"istio.io/istio/pkg/test/framework/resource"
"istio.io/istio/pkg/test/scopes"
)
const (
// DefaultSystemNamespace default value for SystemNamespace
DefaultSystemNamespace = "istio-system"
// IntegrationTestDefaultsIOP is the path of the default IstioOperator spec to use
// for integration tests
IntegrationTestDefaultsIOP = "tests/integration/iop-integration-test-defaults.yaml"
// IntegrationTestDefaultsIOPWithQUIC is the path of the default IstioOperator spec to
// use for integration tests involving QUIC
IntegrationTestDefaultsIOPWithQUIC = "tests/integration/iop-integration-test-defaults-with-quic.yaml"
// IntegrationTestRemoteDefaultsIOP is the path of the default IstioOperator spec to use
// on remote clusters for integration tests
IntegrationTestRemoteDefaultsIOP = "tests/integration/iop-remote-integration-test-defaults.yaml"
// BaseIOP is the path of the base IstioOperator spec
BaseIOP = "tests/integration/base.yaml"
// IntegrationTestRemoteGatewaysIOP is the path of the default IstioOperator spec to use
// to install gateways on remote clusters for integration tests
IntegrationTestRemoteGatewaysIOP = "tests/integration/iop-remote-integration-test-gateways.yaml"
// IntegrationTestExternalIstiodPrimaryDefaultsIOP is the path of the default IstioOperator spec to use
// on external istiod primary clusters for integration tests
IntegrationTestExternalIstiodPrimaryDefaultsIOP = "tests/integration/iop-externalistiod-primary-integration-test-defaults.yaml"
// IntegrationTestExternalIstiodConfigDefaultsIOP is the path of the default IstioOperator spec to use
// on external istiod config clusters for integration tests
IntegrationTestExternalIstiodConfigDefaultsIOP = "tests/integration/iop-externalistiod-config-integration-test-defaults.yaml"
// IntegrationTestAmbientDefaultsIOP is the path of the default IstioOperator for ambient
IntegrationTestAmbientDefaultsIOP = "tests/integration/iop-ambient-test-defaults.yaml"
// IntegrationTestPeerMetadataDiscoveryDefaultsIOP is the path of the default IstioOperator to force WDS usage
IntegrationTestPeerMetadataDiscoveryDefaultsIOP = "tests/integration/iop-wds.yaml"
// hubValuesKey values key for the Docker image hub.
hubValuesKey = "global.hub"
// tagValuesKey values key for the Docker image tag.
tagValuesKey = "global.tag"
// variantValuesKey values key for the Docker image variant.
variantValuesKey = "global.variant"
// imagePullPolicyValuesKey values key for the Docker image pull policy.
imagePullPolicyValuesKey = "global.imagePullPolicy"
// DefaultEgressGatewayLabel is the default Istio label for the egress gateway.
DefaultEgressGatewayIstioLabel = "egressgateway"
// DefaultEgressGatewayServiceName is the default service name for the egress gateway.
DefaultEgressGatewayServiceName = "istio-egressgateway"
)
var (
helmValues string
operatorOptions string
settingsFromCommandline = &Config{
SystemNamespace: DefaultSystemNamespace,
TelemetryNamespace: DefaultSystemNamespace,
DeployIstio: true,
PrimaryClusterIOPFile: IntegrationTestDefaultsIOP,
ConfigClusterIOPFile: IntegrationTestDefaultsIOP,
RemoteClusterIOPFile: IntegrationTestRemoteDefaultsIOP,
BaseIOPFile: BaseIOP,
DeployEastWestGW: true,
DumpKubernetesManifests: false,
IstiodlessRemotes: true,
EnableCNI: false,
EgressGatewayServiceNamespace: DefaultSystemNamespace,
EgressGatewayServiceName: DefaultEgressGatewayServiceName,
EgressGatewayIstioLabel: DefaultEgressGatewayIstioLabel,
}
)
// Config provide kube-specific Config from flags.
type Config struct {
// The namespace where the Istio components (<=1.1) reside in a typical deployment (default: "istio-system").
SystemNamespace string
// The namespace in which kiali, tracing providers, graphana, prometheus are deployed.
TelemetryNamespace string
// The IstioOperator spec file to be used for Control plane cluster by default
PrimaryClusterIOPFile string
// The IstioOperator spec file to be used for Config cluster by default
ConfigClusterIOPFile string
// The IstioOperator spec file to be used for Remote cluster by default
RemoteClusterIOPFile string
// The IstioOperator spec file used as the base for all installs
BaseIOPFile string
// Override values specifically for the ICP crd
// This is mostly required for cases where --set cannot be used
// These values are applied to non-remote clusters
ControlPlaneValues string
// Override values specifically for the ICP crd
// This is mostly required for cases where --set cannot be used
// These values are only applied to remote clusters
// Default value will be ControlPlaneValues if no remote values provided
RemoteClusterValues string
// Override values specifically for the ICP crd
// This is mostly required for cases where --set cannot be used
// These values are only applied to remote config clusters
// Default value will be ControlPlaneValues if no remote values provided
ConfigClusterValues string
// Overrides for the Helm values file.
Values map[string]string
// Indicates that the test should deploy Istio into the target Kubernetes cluster before running tests.
DeployIstio bool
// Do not wait for the validation webhook before completing the deployment. This is useful for
// doing deployments without Galley.
SkipWaitForValidationWebhook bool
// Indicates that the test should deploy Istio's east west gateway into the target Kubernetes cluster
// before running tests.
DeployEastWestGW bool
// DumpKubernetesManifests will cause Kubernetes YAML generated by istioctl install/generate to be dumped to artifacts.
DumpKubernetesManifests bool
// IstiodlessRemotes makes remote clusters run without istiod, using webhooks/ca from the primary cluster.
// TODO we could set this per-cluster if istiod was smarter about patching remotes.
IstiodlessRemotes bool
// OperatorOptions overrides default operator configuration.
OperatorOptions map[string]string
// EnableCNI indicates the test should have CNI enabled.
EnableCNI bool
// custom deployment for ingress and egress gateway on remote clusters.
GatewayValues string
// Custom deployment for east-west gateway
EastWestGatewayValues string
// IngressGatewayServiceName is the service name to use to reference the ingressgateway
// This field should only be set when DeployIstio is false
IngressGatewayServiceName string
// IngressGatewayServiceNamespace allows overriding the namespace of the ingressgateway service (defaults to SystemNamespace)
// This field should only be set when DeployIstio is false
IngressGatewayServiceNamespace string
// IngressGatewayIstioLabel allows overriding the selector of the ingressgateway service (defaults to istio=ingressgateway)
// This field should only be set when DeployIstio is false
IngressGatewayIstioLabel string
// EgressGatewayServiceName is the service name to use to reference the egressgateway
// This field should only be set when DeployIstio is false
EgressGatewayServiceName string
// EgressGatewayServiceNamespace allows overriding the namespace of the egressgateway service (defaults to SystemNamespace)
// This field should only be set when DeployIstio is false
EgressGatewayServiceNamespace string
// EgressGatewayIstioLabel allows overriding the selector of the egressgateway service (defaults to istio=egressgateway)
// This field should only be set when DeployIstio is false
EgressGatewayIstioLabel string
// SharedMeshConfigName is the name of the user's local ConfigMap to be patched, which the user sets as the SHARED_MESH_CONFIG pilot env variable
// upon installing Istio.
// This field should only be set when DeployIstio is false.
SharedMeshConfigName string
}
func (c *Config) OverridesYAML(s *resource.Settings) string {
return fmt.Sprintf(`
global:
hub: %s
tag: %s
`, s.Image.Hub, s.Image.Tag)
}
func (c *Config) IstioOperatorConfigYAML(iopYaml string) string {
data := ""
if iopYaml != "" {
data = Indent(iopYaml, " ")
}
return fmt.Sprintf(`
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
%s
`, data)
}
func (c *Config) fillDefaults(ctx resource.Context) {
if ctx.AllClusters().IsExternalControlPlane() {
c.PrimaryClusterIOPFile = IntegrationTestExternalIstiodPrimaryDefaultsIOP
c.ConfigClusterIOPFile = IntegrationTestExternalIstiodConfigDefaultsIOP
if c.ConfigClusterValues == "" {
c.ConfigClusterValues = c.RemoteClusterValues
}
} else if !c.IstiodlessRemotes {
c.RemoteClusterIOPFile = IntegrationTestDefaultsIOP
if c.RemoteClusterValues == "" {
c.RemoteClusterValues = c.ControlPlaneValues
}
}
}
// Indent indents a block of text with an indent string
func Indent(text, indent string) string {
if text[len(text)-1:] == "\n" {
result := ""
for _, j := range strings.Split(text[:len(text)-1], "\n") {
result += indent + j + "\n"
}
return result
}
result := ""
for _, j := range strings.Split(strings.TrimRight(text, "\n"), "\n") {
result += indent + j + "\n"
}
return result[:len(result)-1]
}
// DefaultConfig creates a new Config from defaults, environments variables, and command-line parameters.
func DefaultConfig(ctx resource.Context) (Config, error) {
// Make a local copy.
s := *settingsFromCommandline
iopFile := s.PrimaryClusterIOPFile
if iopFile != "" && !path.IsAbs(s.PrimaryClusterIOPFile) {
iopFile = filepath.Join(env.IstioSrc, s.PrimaryClusterIOPFile)
}
if err := checkFileExists(iopFile); err != nil {
scopes.Framework.Warnf("Default IOPFile missing: %v", err)
}
var err error
if s.Values, err = newHelmValues(ctx); err != nil {
return Config{}, err
}
if s.OperatorOptions, err = parseConfigOptions(operatorOptions); err != nil {
return Config{}, err
}
return s, nil
}
// DefaultConfigOrFail calls DefaultConfig and fails t if an error occurs.
func DefaultConfigOrFail(t test.Failer, ctx resource.Context) Config {
cfg, err := DefaultConfig(ctx)
if err != nil {
t.Fatalf("Get istio config: %v", err)
}
return cfg
}
func checkFileExists(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
return err
}
return nil
}
func newHelmValues(ctx resource.Context) (map[string]string, error) {
userValues, err := parseConfigOptions(helmValues)
if err != nil {
return nil, err
}
// Copy the defaults first.
values := make(map[string]string)
// Common values
s := ctx.Settings()
values[hubValuesKey] = s.Image.Hub
values[tagValuesKey] = s.Image.Tag
values[variantValuesKey] = s.Image.Variant
values[imagePullPolicyValuesKey] = s.Image.PullPolicy
// Copy the user values.
for k, v := range userValues {
values[k] = v
}
// Always pull Docker images if using the "latest".
if values[tagValuesKey] == "latest" {
values[imagePullPolicyValuesKey] = string(corev1.PullAlways)
}
// We need more information on Envoy logs to detect usage of any deprecated feature
if ctx.Settings().FailOnDeprecation {
values["global.proxy.logLevel"] = "debug"
values["global.proxy.componentLogLevel"] = "misc:debug"
}
return values, nil
}
func parseConfigOptions(options string) (map[string]string, error) {
out := make(map[string]string)
if options == "" {
return out, nil
}
values := strings.Split(options, ",")
for _, v := range values {
parts := strings.Split(v, "=")
if len(parts) != 2 {
return nil, fmt.Errorf("failed parsing config options: %s", options)
}
out[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}
return out, nil
}
// String implements fmt.Stringer
func (c *Config) String() string {
result := ""
result += fmt.Sprintf("SystemNamespace: %s\n", c.SystemNamespace)
result += fmt.Sprintf("TelemetryNamespace: %s\n", c.TelemetryNamespace)
result += fmt.Sprintf("DeployIstio: %v\n", c.DeployIstio)
result += fmt.Sprintf("DeployEastWestGW: %v\n", c.DeployEastWestGW)
result += fmt.Sprintf("Values: %v\n", c.Values)
result += fmt.Sprintf("PrimaryClusterIOPFile: %s\n", c.PrimaryClusterIOPFile)
result += fmt.Sprintf("ConfigClusterIOPFile: %s\n", c.ConfigClusterIOPFile)
result += fmt.Sprintf("RemoteClusterIOPFile: %s\n", c.RemoteClusterIOPFile)
result += fmt.Sprintf("BaseIOPFile: %s\n", c.BaseIOPFile)
result += fmt.Sprintf("SkipWaitForValidationWebhook: %v\n", c.SkipWaitForValidationWebhook)
result += fmt.Sprintf("DumpKubernetesManifests: %v\n", c.DumpKubernetesManifests)
result += fmt.Sprintf("IstiodlessRemotes: %v\n", c.IstiodlessRemotes)
result += fmt.Sprintf("OperatorOptions: %v\n", c.OperatorOptions)
result += fmt.Sprintf("EnableCNI: %v\n", c.EnableCNI)
result += fmt.Sprintf("IngressGatewayServiceName: %v\n", c.IngressGatewayServiceName)
result += fmt.Sprintf("IngressGatewayServiceNamespace: %v\n", c.IngressGatewayServiceNamespace)
result += fmt.Sprintf("IngressGatewayIstioLabel: %v\n", c.IngressGatewayIstioLabel)
result += fmt.Sprintf("EgressGatewayServiceName: %v\n", c.EgressGatewayServiceName)
result += fmt.Sprintf("EgressGatewayServiceNamespace: %v\n", c.EgressGatewayServiceNamespace)
result += fmt.Sprintf("EgressGatewayIstioLabel: %v\n", c.EgressGatewayIstioLabel)
result += fmt.Sprintf("SharedMeshConfigName: %v\n", c.SharedMeshConfigName)
return result
}
// ClaimSystemNamespace retrieves the namespace for the Istio system components from the environment.
func ClaimSystemNamespace(ctx resource.Context) (namespace.Instance, error) {
istioCfg, err := DefaultConfig(ctx)
if err != nil {
return nil, err
}
nsCfg := namespace.Config{
Prefix: istioCfg.SystemNamespace,
Inject: false,
// Already handled directly
SkipDump: true,
SkipCleanup: true,
}
return namespace.Claim(ctx, nsCfg)
}
// ClaimSystemNamespaceOrFail calls ClaimSystemNamespace, failing the test if an error occurs.
func ClaimSystemNamespaceOrFail(t test.Failer, ctx resource.Context) namespace.Instance {
t.Helper()
i, err := ClaimSystemNamespace(ctx)
if err != nil {
t.Fatal(err)
}
return i
}