From 81aee4a956bd69aa1ad2f6daa9c531df4727e960 Mon Sep 17 00:00:00 2001 From: Charith Ellawala <52399125+charith-elastic@users.noreply.github.com> Date: Thu, 17 Oct 2019 16:11:03 +0100 Subject: [PATCH] Add multi-namespace cache support (#1995) * Add multi-namespace cache support * Address CR comments * Abandon backward compatibility --- Makefile | 9 +-- cmd/manager/main.go | 26 ++++++-- config/e2e/batch_job.yaml | 2 +- config/e2e/managed_namespaces.yaml | 4 +- config/e2e/namespace_operator.yaml | 44 +++++++------ config/e2e/operator_namespaces.yaml | 5 +- config/e2e/rbac.yaml | 6 +- config/operator/Makefile | 17 +++-- config/operator/README.md | 6 +- ... => managed_ns_role_binding.template.yaml} | 15 ----- .../operator/namespace/operator.template.yaml | 2 +- .../operator_ns_role_binding.template.yaml | 14 ++++ docs/operator-config.asciidoc | 4 +- test/e2e/apm/association_test.go | 9 +-- test/e2e/cmd/run/eventlog.go | 6 +- test/e2e/cmd/run/run.go | 34 +++++----- test/e2e/kb/association_test.go | 9 +-- test/e2e/test/context.go | 66 ++++++------------- 18 files changed, 129 insertions(+), 149 deletions(-) rename config/operator/namespace/{role_bindings.template.yaml => managed_ns_role_binding.template.yaml} (57%) create mode 100644 config/operator/namespace/operator_ns_role_binding.template.yaml diff --git a/Makefile b/Makefile index fa8a04ca5c..1ed7661243 100644 --- a/Makefile +++ b/Makefile @@ -82,8 +82,8 @@ SKIP_DOCKER_COMMAND ?= false GLOBAL_OPERATOR_NAMESPACE ?= elastic-system # namespace in which the namespace operator is deployed (see config/namespace-operator) NAMESPACE_OPERATOR_NAMESPACE ?= elastic-namespace-operators -# namespace in which the namespace operator should watch resources -MANAGED_NAMESPACE ?= default +# comma separated list of namespaces in which the namespace operator should watch resources +MANAGED_NAMESPACES ?= ## -- Security @@ -170,7 +170,8 @@ go-run: --development --operator-roles=global,namespace \ --log-verbosity=$(LOG_VERBOSITY) \ --ca-cert-validity=10h --ca-cert-rotate-before=1h \ - --operator-namespace=default --namespace= \ + --operator-namespace=default \ + --namespaces=$(MANAGED_NAMESPACES) \ --auto-install-webhooks=false go-debug: @@ -184,7 +185,7 @@ go-debug: --ca-cert-validity=10h \ --ca-cert-rotate-before=1h \ --operator-namespace=default \ - --namespace= \ + --namespaces=$(MANAGED_NAMESPACES) \ --auto-install-webhooks=false) build-operator-image: diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 94c3c3f655..518386e144 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -39,6 +39,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/cache" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/runtime/signals" ) @@ -48,7 +49,7 @@ const ( DefaultMetricPort = 0 // disabled AutoPortForwardFlagName = "auto-port-forward" - NamespaceFlagName = "namespace" + NamespacesFlag = "namespaces" CACertValidityFlag = "ca-cert-validity" CACertRotateBeforeFlag = "ca-cert-rotate-before" @@ -80,10 +81,10 @@ var ( func init() { - Cmd.Flags().String( - NamespaceFlagName, - "", - "namespace in which this operator should manage resources (defaults to all namespaces)", + Cmd.Flags().StringSlice( + NamespacesFlag, + nil, + "comma-separated list of namespaces in which this operator should manage resources (defaults to all namespaces)", ) Cmd.Flags().Bool( AutoPortForwardFlagName, @@ -213,8 +214,19 @@ func execute() { log.Info("Setting up manager") opts := ctrl.Options{ Scheme: clientgoscheme.Scheme, - // restrict the operator to watch resources within a single namespace, unless empty - Namespace: viper.GetString(NamespaceFlagName), + } + + // configure the manager cache based on the number of managed namespaces + managedNamespaces := viper.GetStringSlice(NamespacesFlag) + switch len(managedNamespaces) { + case 0: + log.Info("Operator configured to manage all namespaces") + case 1: + log.Info("Operator configured to manage a single namespace", "namespace", managedNamespaces[0]) + opts.Namespace = managedNamespaces[0] + default: + log.Info("Operator configured to manage multiple namespaces", "namespaces", managedNamespaces) + opts.NewCache = cache.MultiNamespacedCacheBuilder(managedNamespaces) } // only expose prometheus metrics if provided a non-zero port diff --git a/config/e2e/batch_job.yaml b/config/e2e/batch_job.yaml index c639f62266..017c1eebdd 100644 --- a/config/e2e/batch_job.yaml +++ b/config/e2e/batch_job.yaml @@ -33,7 +33,7 @@ spec: containers: - name: e2e image: {{ .E2EImage }} - imagePullPolicy: IfNotPresent + imagePullPolicy: Always args: [{{- if .TestRegex -}}"-run", "{{ .TestRegex }}",{{- end -}}"-args", "-testContextPath","/etc/e2e/testcontext.json"] volumeMounts: - name: test-config diff --git a/config/e2e/managed_namespaces.yaml b/config/e2e/managed_namespaces.yaml index 44b17135e1..9bd3f234ed 100644 --- a/config/e2e/managed_namespaces.yaml +++ b/config/e2e/managed_namespaces.yaml @@ -1,10 +1,10 @@ {{- $testRun := .TestRun -}} -{{- range .NamespaceOperators }} +{{- range .NamespaceOperator.ManagedNamespaces }} --- apiVersion: v1 kind: Namespace metadata: - name: {{ .ManagedNamespace }} + name: {{ . }} labels: test-run: {{ $testRun }} {{- end }} diff --git a/config/e2e/namespace_operator.yaml b/config/e2e/namespace_operator.yaml index b650d531fa..611538ef72 100644 --- a/config/e2e/namespace_operator.yaml +++ b/config/e2e/namespace_operator.yaml @@ -142,14 +142,12 @@ rules: - get - update - patch - -{{- range .NamespaceOperators }} --- apiVersion: v1 kind: ServiceAccount metadata: - name: {{ .Name }} - namespace: {{ .Namespace }} + name: {{ .NamespaceOperator.Name }} + namespace: {{ .NamespaceOperator.Namespace }} labels: test-run: {{ $testRun }} --- @@ -157,8 +155,8 @@ metadata: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ .Name }} - namespace: {{ .Namespace }} + name: {{ .NamespaceOperator.Name }} + namespace: {{ .NamespaceOperator.Namespace }} labels: test-run: {{ $testRun }} roleRef: @@ -167,15 +165,18 @@ roleRef: name: elastic-operator subjects: - kind: ServiceAccount - name: {{ .Name }} - namespace: {{ .Namespace }} + name: {{ .NamespaceOperator.Name }} + namespace: {{ .NamespaceOperator.Namespace }} + +{{- $nsOperator := .NamespaceOperator -}} +{{ range $nsOperator.ManagedNamespaces }} --- # allow operator to manage resources in the managed namespace apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ .Name }} - namespace: {{ .ManagedNamespace }} + name: {{ $nsOperator.Name }} + namespace: {{ . }} labels: test-run: {{ $testRun }} roleRef: @@ -184,34 +185,36 @@ roleRef: name: elastic-namespace-operator subjects: - kind: ServiceAccount - name: {{ .Name }} - namespace: {{ .Namespace }} + name: {{ $nsOperator.Name }} + namespace: {{ $nsOperator.Namespace }} +{{- end }} + --- apiVersion: apps/v1 kind: StatefulSet metadata: - name: {{ .Name }} - namespace: {{ .Namespace }} + name: {{ .NamespaceOperator.Name }} + namespace: {{ .NamespaceOperator.Namespace }} labels: - control-plane: {{ .Name }} + control-plane: {{ .NamespaceOperator.Name }} test-run: {{ $testRun }} spec: selector: matchLabels: - control-plane: {{ .Name }} - serviceName: {{ .Name }} + control-plane: {{ .NamespaceOperator.Name }} + serviceName: {{ .NamespaceOperator.Name }} template: metadata: labels: - control-plane: {{ .Name }} + control-plane: {{ .NamespaceOperator.Name }} test-run: {{ $testRun }} spec: - serviceAccountName: {{ .Name }} + serviceAccountName: {{ .NamespaceOperator.Name }} containers: - image: {{ $operatorImage }} imagePullPolicy: IfNotPresent name: manager - args: ["manager", "--namespace", "{{ .ManagedNamespace }}", "--operator-roles", "namespace"] + args: ["manager", "--namespaces", "{{ .NamespaceOperator.ManagedNamespaces | join "," }}", "--operator-roles", "namespace"] env: - name: OPERATOR_NAMESPACE valueFrom: @@ -227,4 +230,3 @@ spec: cpu: 100m memory: 20Mi terminationGracePeriodSeconds: 10 -{{- end }} diff --git a/config/e2e/operator_namespaces.yaml b/config/e2e/operator_namespaces.yaml index 2bdbfe124b..348e45fde6 100644 --- a/config/e2e/operator_namespaces.yaml +++ b/config/e2e/operator_namespaces.yaml @@ -6,13 +6,10 @@ metadata: name: {{ .GlobalOperator.Namespace }} labels: test-run: {{ $testRun }} - -{{- range .OperatorNamespaces }} --- apiVersion: v1 kind: Namespace metadata: - name: {{ . }} + name: {{ .NamespaceOperator.Namespace }} labels: test-run: {{ $testRun }} -{{- end }} diff --git a/config/e2e/rbac.yaml b/config/e2e/rbac.yaml index b42dbbe730..6bfe08f68f 100644 --- a/config/e2e/rbac.yaml +++ b/config/e2e/rbac.yaml @@ -59,11 +59,9 @@ subjects: - kind: ServiceAccount name: {{ .GlobalOperator.Name }} namespace: {{ .GlobalOperator.Namespace }} -{{- range .NamespaceOperators }} - kind: ServiceAccount - name: {{ .Name }} - namespace: {{ .Namespace }} -{{- end }} + name: {{ .NamespaceOperator.Name }} + namespace: {{ .NamespaceOperator.Namespace }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/config/operator/Makefile b/config/operator/Makefile index f7d99f249a..5d43f15a87 100644 --- a/config/operator/Makefile +++ b/config/operator/Makefile @@ -34,14 +34,23 @@ generate-global: -e "s||$$NAMESPACE|g" generate-namespace: -ifndef MANAGED_NAMESPACE - $(error MANAGED_NAMESPACE not set) +ifndef MANAGED_NAMESPACES + $(error MANAGED_NAMESPACES not set) endif - @ for yaml in $$(LC_COLLATE=C ls namespace/*yaml); do \ + @ for yaml in $(shell find namespace -type f -name '*.yaml' ! -name 'managed_ns_role_binding.template.yaml'); do \ printf "\n---\n" && cat $$yaml ; \ done | \ sed \ -e "/# /d" \ -e "s||$$OPERATOR_IMAGE|g" \ -e "s||$$NAMESPACE|g" \ - -e "s||$$MANAGED_NAMESPACE|g" + -e "s||$$MANAGED_NAMESPACES|g" + + @ (MANAGED_NS_LIST=$${MANAGED_NAMESPACES//,/ }; \ + for managed_ns in $$MANAGED_NS_LIST; do \ + printf "\n---\n" && sed \ + -e "/# /d" \ + -e "s||$$NAMESPACE|g" \ + -e "s||$$managed_ns|g" \ + namespace/managed_ns_role_binding.template.yaml ;\ + done) diff --git a/config/operator/README.md b/config/operator/README.md index 1a961f9408..a764bd7474 100644 --- a/config/operator/README.md +++ b/config/operator/README.md @@ -4,7 +4,7 @@ The Elastic Operator can be deployed in 2 different modes using the following ar * `--operator-roles`: namespace, global, webhook or all * `--operator-namespace`: namespace the operator runs in -* `--namespace`: namespace in which resources should be watched (defaults to all namespaces) +* `--namespaces`: comma-separated list of namespaces in which resources should be watched (defaults to all namespaces) ## Deployment mode @@ -34,7 +34,7 @@ OPERATOR_IMAGE= NAMESPACE= make generate-global | kubectl apply -f - A namespace operator that manages resources in a given namespace. ```bash -OPERATOR_IMAGE= NAMESPACE= MANAGED_NAMESPACE= make generate-namespace | kubectl apply -f - +OPERATOR_IMAGE= NAMESPACE= MANAGED_NAMESPACES= make generate-namespace | kubectl apply -f - ``` ## Role of each YAML file @@ -59,4 +59,4 @@ Describes permissions for several api calls the operator needs to perform. ### role_bindings.yaml or cluster_role_bindings.yaml -Allows the operator to perform calls described in `cluster_role.yaml` in the operator namespace. +Allows the operator to perform calls described in `cluster_role.yaml` in the operator namespace. diff --git a/config/operator/namespace/role_bindings.template.yaml b/config/operator/namespace/managed_ns_role_binding.template.yaml similarity index 57% rename from config/operator/namespace/role_bindings.template.yaml rename to config/operator/namespace/managed_ns_role_binding.template.yaml index 60afe2f9d1..f4b889b897 100644 --- a/config/operator/namespace/role_bindings.template.yaml +++ b/config/operator/namespace/managed_ns_role_binding.template.yaml @@ -1,18 +1,3 @@ -# allow operator to manage resources in its namespace -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: elastic-operator - namespace: -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: elastic-operator -subjects: -- kind: ServiceAccount - name: elastic-namespace-operator - namespace: ---- # allow operator to manage resources in the managed namespace apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/config/operator/namespace/operator.template.yaml b/config/operator/namespace/operator.template.yaml index 0dc369e833..ef1a0d53c2 100644 --- a/config/operator/namespace/operator.template.yaml +++ b/config/operator/namespace/operator.template.yaml @@ -21,7 +21,7 @@ spec: containers: - image: name: manager - args: ["manager", "--namespace", "", "--operator-roles", "namespace"] + args: ["manager", "--namespaces", "", "--operator-roles", "namespace"] env: - name: OPERATOR_NAMESPACE valueFrom: diff --git a/config/operator/namespace/operator_ns_role_binding.template.yaml b/config/operator/namespace/operator_ns_role_binding.template.yaml new file mode 100644 index 0000000000..8c2cbbc50d --- /dev/null +++ b/config/operator/namespace/operator_ns_role_binding.template.yaml @@ -0,0 +1,14 @@ +# allow operator to manage resources in its namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: elastic-operator + namespace: +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: elastic-operator +subjects: +- kind: ServiceAccount + name: elastic-namespace-operator + namespace: diff --git a/docs/operator-config.asciidoc b/docs/operator-config.asciidoc index 6c25ef23b1..6e4f2bc218 100644 --- a/docs/operator-config.asciidoc +++ b/docs/operator-config.asciidoc @@ -17,7 +17,7 @@ You can use several options to configure ECK. Unless otherwise noted, these opti |`enable-debug-logs` |bool |false |Enables debug logs. Equivalent to `log-verbosity=1` |`metrics-port` |int |0 |Port to use for exposing metrics in the Prometheus format. Set 0 to disable |`operator-roles` |[]string |all |Roles this operator should assume. Valid values are namespace, global, webhook or all. Accepts multiple comma separated values. See <<{p}-ns-config>> for more information -|`namespace` |string |`""` |Namespace in which this operator should manage resources. Defaults to all namespaces. See <<{p}-ns-config>> for more information +|`namespaces` |[]string |`""` |Namespaces in which this operator should manage resources. Accepts multiple comma-separated values. Defaults to all namespaces. See <<{p}-ns-config>> for more information |`ca-cert-validity` |duration (string) |1y |Duration representing how long before a newly created CA cert expires |`ca-cert-rotate-before` |duration (string) |1d |Duration representing how long before expiration CA certificates should be reissued |`cert-validity` |duration (string) |1y |Duration representing how long before a newly created TLS certificate expires @@ -68,6 +68,6 @@ to: [id="{p}-ns-config"] === Namespace and role configuration -The `operator-roles` and `namespace` flags have some intricacies that are worth discussing. A fully functioning operator will *require* both `global` and `namespace` roles running in the cluster (though potentially in different operator deployments). That is to say, with `--operator-roles=global,namespace` (or `--operator-roles=all`). If you want to limit the operator to a single namespace, you must set the `namespace` flag as well. For example `--operator-roles=global,namespace --namespace=my-namespace`. To have it listen on the entire cluster, you can simply omit the `namespace` flag. +The `operator-roles` and `namespaces` flags have some intricacies that are worth discussing. A fully functioning operator will *require* both `global` and `namespace` roles running in the cluster (though potentially in different operator deployments). That is to say, with `--operator-roles=global,namespace` (or `--operator-roles=all`). If you want to limit the operator to a specific set of namespaces, you must set the `namespaces` flag as well. For example `--operator-roles=global,namespace --namespaces=my-namespace1,mynamespace2`. To have it manage all namespaces, you can simply omit the `namespaces` flag. The global role acts across namespaces and is not related to a specific deployment of the Elastic stack. The global operator deployed cluster-wide is responsible for high-level cross-cluster features. diff --git a/test/e2e/apm/association_test.go b/test/e2e/apm/association_test.go index 8493caa1a4..9580071298 100644 --- a/test/e2e/apm/association_test.go +++ b/test/e2e/apm/association_test.go @@ -22,12 +22,6 @@ import ( // TestCrossNSAssociation tests associating Elasticsearch and an APM Server running in different namespaces. func TestCrossNSAssociation(t *testing.T) { - // This test currently does not work in the E2E environment because each namespace has a dedicated - // controller (see https://github.com/elastic/cloud-on-k8s/issues/1438) - if !(test.Ctx().Local) { - t.SkipNow() - } - esNamespace := test.Ctx().ManagedNamespace(0) apmNamespace := test.Ctx().ManagedNamespace(1) name := "test-cross-ns-assoc" @@ -46,8 +40,7 @@ func TestCrossNSAssociation(t *testing.T) { "setup.template.settings.index.number_of_replicas": 0, // avoid ES yellow state on a 1 node ES cluster }) - test.Sequence(nil, test.EmptySteps, esBuilder, apmBuilder). - RunSequential(t) + test.Sequence(nil, test.EmptySteps, esBuilder, apmBuilder).RunSequential(t) } func TestAPMAssociationWithNonExistentES(t *testing.T) { diff --git a/test/e2e/cmd/run/eventlog.go b/test/e2e/cmd/run/eventlog.go index bff462cbc4..ebc539d49f 100644 --- a/test/e2e/cmd/run/eventlog.go +++ b/test/e2e/cmd/run/eventlog.go @@ -67,9 +67,9 @@ func newEventLogger(client *kubernetes.Clientset, testCtx test.Context, logFileP s := struct{}{} el.interestingNamespaces[testCtx.E2ENamespace] = s el.interestingNamespaces[testCtx.GlobalOperator.Namespace] = s - for _, ns := range testCtx.NamespaceOperators { - el.interestingNamespaces[ns.Namespace] = s - el.interestingNamespaces[ns.ManagedNamespace] = s + el.interestingNamespaces[testCtx.NamespaceOperator.Namespace] = s + for _, ns := range testCtx.NamespaceOperator.ManagedNamespaces { + el.interestingNamespaces[ns] = s } return el diff --git a/test/e2e/cmd/run/run.go b/test/e2e/cmd/run/run.go index cf4b619d09..c9fa841e8e 100644 --- a/test/e2e/cmd/run/run.go +++ b/test/e2e/cmd/run/run.go @@ -64,7 +64,7 @@ func doRun(flags runFlags) error { helper.createOperatorNamespaces, helper.createManagedNamespaces, helper.deployGlobalOperator, - helper.deployNamespaceOperators, + helper.deployNamespaceOperator, helper.deployTestJob, helper.runTestJob, } @@ -129,23 +129,23 @@ func (h *helper) initTestContext() error { Name: fmt.Sprintf("%s-global-operator", h.testRunName), Namespace: fmt.Sprintf("%s-elastic-system", h.testRunName), }, - Local: h.local, - LogVerbosity: h.logVerbosity, - NamespaceOperators: make([]test.NamespaceOperator, len(h.managedNamespaces)), - OperatorImage: h.operatorImage, - TestLicence: h.testLicence, - TestRegex: h.testRegex, - TestRun: h.testRunName, - } - - for i, ns := range h.managedNamespaces { - h.testContext.NamespaceOperators[i] = test.NamespaceOperator{ + Local: h.local, + LogVerbosity: h.logVerbosity, + NamespaceOperator: test.NamespaceOperator{ ClusterResource: test.ClusterResource{ - Name: fmt.Sprintf("%s-%s-ns-operator", h.testRunName, ns), + Name: fmt.Sprintf("%s-ns-operator", h.testRunName), Namespace: fmt.Sprintf("%s-ns-operators", h.testRunName), }, - ManagedNamespace: fmt.Sprintf("%s-%s", h.testRunName, ns), - } + ManagedNamespaces: make([]string, len(h.managedNamespaces)), + }, + OperatorImage: h.operatorImage, + TestLicence: h.testLicence, + TestRegex: h.testRegex, + TestRun: h.testRunName, + } + + for i, ns := range h.managedNamespaces { + h.testContext.NamespaceOperator.ManagedNamespaces[i] = fmt.Sprintf("%s-%s", h.testRunName, ns) } // write the test context if required @@ -197,8 +197,8 @@ func (h *helper) deployGlobalOperator() error { return h.kubectlApplyTemplateWithCleanup("config/e2e/global_operator.yaml", h.testContext) } -func (h *helper) deployNamespaceOperators() error { - log.Info("Deploying namespace operators") +func (h *helper) deployNamespaceOperator() error { + log.Info("Deploying namespace operator") return h.kubectlApplyTemplateWithCleanup("config/e2e/namespace_operator.yaml", h.testContext) } diff --git a/test/e2e/kb/association_test.go b/test/e2e/kb/association_test.go index 8d1c89b19c..76a64b16ad 100644 --- a/test/e2e/kb/association_test.go +++ b/test/e2e/kb/association_test.go @@ -22,12 +22,6 @@ import ( // TestCrossNSAssociation tests associating Elasticsearch and Kibana running in different namespaces. func TestCrossNSAssociation(t *testing.T) { - // This test currently does not work in the E2E environment because each namespace has a dedicated - // controller (see https://github.com/elastic/cloud-on-k8s/issues/1438) - if !test.Ctx().Local { - t.SkipNow() - } - esNamespace := test.Ctx().ManagedNamespace(0) kbNamespace := test.Ctx().ManagedNamespace(1) name := "test-cross-ns-assoc" @@ -42,8 +36,7 @@ func TestCrossNSAssociation(t *testing.T) { WithNodeCount(1). WithRestrictedSecurityContext() - builders := []test.Builder{esBuilder, kbBuilder} - test.RunMutations(t, builders, builders) + test.Sequence(nil, test.EmptySteps, esBuilder, kbBuilder).RunSequential(t) } func TestKibanaAssociationWithNonExistentES(t *testing.T) { diff --git a/test/e2e/test/context.go b/test/e2e/test/context.go index a70b9bad95..488c0faafc 100644 --- a/test/e2e/test/context.go +++ b/test/e2e/test/context.go @@ -16,7 +16,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" ) -const defaultElasticStackVersion = "7.2.0" +const defaultElasticStackVersion = "7.4.0" var ( testContextPath = flag.String("testContextPath", "", "Path to the test context file") @@ -66,21 +66,12 @@ func defaultContext() Context { Name: "elastic-global-operator", Namespace: "elastic-system", }, - NamespaceOperators: []NamespaceOperator{ - { - ClusterResource: ClusterResource{ - Name: "mercury-ns-operator", - Namespace: "elastic-ns-operators", - }, - ManagedNamespace: "mercury", - }, - { - ClusterResource: ClusterResource{ - Name: "venus-ns-operator", - Namespace: "elastic-ns-operators", - }, - ManagedNamespace: "venus", + NamespaceOperator: NamespaceOperator{ + ClusterResource: ClusterResource{ + Name: "elastic-ns-operator", + Namespace: "elastic-ns-operators", }, + ManagedNamespaces: []string{"mercury", "venus"}, }, TestRun: "e2e-default", } @@ -88,39 +79,24 @@ func defaultContext() Context { // Context encapsulates data about a specific test run type Context struct { - GlobalOperator ClusterResource `json:"global_operator"` - NamespaceOperators []NamespaceOperator `json:"namespace_operators"` - E2EImage string `json:"e2e_image"` - E2ENamespace string `json:"e2e_namespace"` - E2EServiceAccount string `json:"e2e_service_account"` - ElasticStackVersion string `json:"elastic_stack_version"` - LogVerbosity int `json:"log_verbosity"` - OperatorImage string `json:"operator_image"` - TestLicence string `json:"test_licence"` - TestRegex string `json:"test_regex"` - TestRun string `json:"test_run"` - AutoPortForwarding bool `json:"auto_port_forwarding"` - Local bool `json:"local"` + GlobalOperator ClusterResource `json:"global_operator"` + NamespaceOperator NamespaceOperator `json:"namespace_operator"` + E2EImage string `json:"e2e_image"` + E2ENamespace string `json:"e2e_namespace"` + E2EServiceAccount string `json:"e2e_service_account"` + ElasticStackVersion string `json:"elastic_stack_version"` + LogVerbosity int `json:"log_verbosity"` + OperatorImage string `json:"operator_image"` + TestLicence string `json:"test_licence"` + TestRegex string `json:"test_regex"` + TestRun string `json:"test_run"` + AutoPortForwarding bool `json:"auto_port_forwarding"` + Local bool `json:"local"` } // ManagedNamespace returns the nth managed namespace. func (c Context) ManagedNamespace(n int) string { - return c.NamespaceOperators[n].ManagedNamespace -} - -// OperatorNamespaces returns the unique set of namespaces that have operators deployed. -func (c Context) OperatorNamespaces() []string { - seen := make(map[string]struct{}, len(c.NamespaceOperators)) - for _, ns := range c.NamespaceOperators { - seen[ns.Namespace] = struct{}{} - } - - namespaces := make([]string, 0, len(seen)) - for ns := range seen { - namespaces = append(namespaces, ns) - } - - return namespaces + return c.NamespaceOperator.ManagedNamespaces[n] } // ClusterResource is a generic cluster resource. @@ -132,5 +108,5 @@ type ClusterResource struct { // NamespaceOperator is cluster resource with an associated namespace to manage. type NamespaceOperator struct { ClusterResource - ManagedNamespace string `json:"managed_namespace"` + ManagedNamespaces []string `json:"managed_namespaces"` }