From 38ff3d3f4b4ff63f2db10afb6cd816fb4ebc8056 Mon Sep 17 00:00:00 2001 From: Anya Sabo <1638148+anyasabo@users.noreply.github.com> Date: Tue, 29 Oct 2019 19:19:42 -0500 Subject: [PATCH] Refactor validations (#2072) --- .golangci.yml | 6 +- Makefile | 2 +- ...search.k8s.elastic.co_elasticsearches.yaml | 5 + config/webhook/manifests.yaml | 26 + .../v1beta1/elasticsearch_types.go | 9 +- .../elasticsearch/v1beta1}/fields.go | 4 +- .../elasticsearch/v1beta1}/name.go | 22 +- .../elasticsearch/v1beta1}/name_test.go | 11 +- pkg/apis/elasticsearch/v1beta1/validations.go | 229 +++++ .../elasticsearch/v1beta1/validations_test.go | 785 +++++++++++++++++ pkg/apis/elasticsearch/v1beta1/webhook.go | 77 ++ .../v1beta1/zz_generated.deepcopy.go | 2 +- ...rverelasticsearchassociation_controller.go | 3 +- pkg/controller/common/association/ca.go | 4 +- pkg/controller/common/association/ca_test.go | 5 +- .../certificates/http/public_secret_test.go | 5 +- .../certificates/http/reconcile_test.go | 9 +- .../certificates/ca_reconcile.go | 9 +- .../certificates/transport/public_secret.go | 3 +- .../certificates/transport/reconcile.go | 3 +- .../certificates/transport/reconcile_test.go | 4 +- .../elasticsearch/configmap/configmap.go | 3 +- pkg/controller/elasticsearch/driver/driver.go | 7 +- .../elasticsearch/driver/upscale_test.go | 9 +- .../running_versions.go => driver/version.go} | 18 +- .../elasticsearch/driver/version_test.go | 201 +++++ .../elasticsearch/elasticsearch_controller.go | 15 +- .../elasticsearch/initcontainer/prepare_fs.go | 4 +- pkg/controller/elasticsearch/license/apply.go | 4 +- .../elasticsearch/license/apply_test.go | 10 +- .../elasticsearch/nodespec/podspec.go | 5 +- .../elasticsearch/nodespec/statefulset.go | 3 +- .../elasticsearch/nodespec/volumes.go | 9 +- pkg/controller/elasticsearch/pdb/reconcile.go | 5 +- .../elasticsearch/pdb/reconcile_test.go | 13 +- .../elasticsearch/reconcile/state.go | 7 +- .../elasticsearch/services/services.go | 3 +- .../elasticsearch/settings/config_volume.go | 3 +- .../elasticsearch/settings/masters.go | 3 +- .../elasticsearch/settings/masters_test.go | 3 +- .../elasticsearch/settings/merged_config.go | 59 +- .../settings/merged_config_test.go | 45 +- .../elasticsearch/user/credentials.go | 8 +- .../validation/upgrade_checks.go | 58 -- .../validation/upgrade_checks_test.go | 135 --- .../elasticsearch/validation/validation.go | 95 -- .../validation/validation_test.go | 230 ----- .../elasticsearch/validation/validations.go | 229 ----- .../validation/validations_test.go | 824 ------------------ .../version/running_versions_test.go | 96 -- .../version/supported_versions.go | 21 +- .../version/supported_versions_test.go | 111 +-- .../version/zen1/minimum_masters.go | 3 +- .../version/zen1/minimum_masters_test.go | 8 +- .../version/zen2/initial_master_nodes.go | 4 +- .../version/zen2/initial_master_nodes_test.go | 10 +- .../association_controller.go | 3 +- pkg/controller/license/license_controller.go | 3 +- .../license_controller_integration_test.go | 3 +- .../license/license_controller_test.go | 3 +- test/e2e/es/certs_test.go | 3 +- test/e2e/es/failure_test.go | 4 +- test/e2e/es/forced_upgrade_test.go | 10 +- test/e2e/test/elasticsearch/checks_k8s.go | 11 +- test/e2e/test/elasticsearch/http_client.go | 3 +- test/e2e/test/k8s_client.go | 5 +- 66 files changed, 1542 insertions(+), 1990 deletions(-) create mode 100644 config/webhook/manifests.yaml rename pkg/{controller/elasticsearch/settings => apis/elasticsearch/v1beta1}/fields.go (98%) rename pkg/{controller/elasticsearch/name => apis/elasticsearch/v1beta1}/name.go (84%) rename pkg/{controller/elasticsearch/name => apis/elasticsearch/v1beta1}/name_test.go (86%) create mode 100644 pkg/apis/elasticsearch/v1beta1/validations.go create mode 100644 pkg/apis/elasticsearch/v1beta1/validations_test.go create mode 100644 pkg/apis/elasticsearch/v1beta1/webhook.go rename pkg/controller/elasticsearch/{version/running_versions.go => driver/version.go} (61%) create mode 100644 pkg/controller/elasticsearch/driver/version_test.go delete mode 100644 pkg/controller/elasticsearch/validation/upgrade_checks.go delete mode 100644 pkg/controller/elasticsearch/validation/upgrade_checks_test.go delete mode 100644 pkg/controller/elasticsearch/validation/validation.go delete mode 100644 pkg/controller/elasticsearch/validation/validation_test.go delete mode 100644 pkg/controller/elasticsearch/validation/validations.go delete mode 100644 pkg/controller/elasticsearch/validation/validations_test.go delete mode 100644 pkg/controller/elasticsearch/version/running_versions_test.go diff --git a/.golangci.yml b/.golangci.yml index 04c5e4ad8c..2c1ea88031 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -64,7 +64,7 @@ issues: text: 'struct of size 96 bytes could be of size 80 bytes' - path: pkg/controller/elasticsearch/reconcile/resources_state\.go text: 'ifElseChain: rewrite if\-else to switch statement' - - path: pkg/controller/elasticsearch/settings/fields\.go + - path: pkg/apis/elasticsearch/v1beta1/fields\.go text: 'const .* should be' - path: pkg/controller/elasticsearch/user/reconciler\.go text: 'Consider preallocating `allUsers`' @@ -90,6 +90,10 @@ issues: text: 'Consider preallocating `errs`' - path: test/e2e/test/elasticsearch/steps_license\.go text: 'G101: Potential hardcoded credentials' + - path: pkg/apis/elasticsearch/v1beta1/name\.go + text: 'G101: Potential hardcoded credentials' + - path: pkg/controller/elasticsearch/driver/version\.go + text: 'Consider preallocating `vs`' - linters: - stylecheck text: 'ST1016: methods on the same type should have the same receiver name.*"in".*' diff --git a/Makefile b/Makefile index 8afbb7ac2c..890baa05fb 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,7 @@ dependencies: generate: controller-gen # we use this in pkg/controller/common/license go generate -tags='$(GO_TAGS)' ./pkg/... ./cmd/... - $(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/... + $(CONTROLLER_GEN) webhook object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/... # Generate manifests e.g. CRD, RBAC etc. $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./pkg/apis/..." output:crd:artifacts:config=config/crds # verify that the available crd flavors still can generate cleanly diff --git a/config/crds/elasticsearch.k8s.elastic.co_elasticsearches.yaml b/config/crds/elasticsearch.k8s.elastic.co_elasticsearches.yaml index 96166e2079..ac7c05b7ba 100644 --- a/config/crds/elasticsearch.k8s.elastic.co_elasticsearches.yaml +++ b/config/crds/elasticsearch.k8s.elastic.co_elasticsearches.yaml @@ -5575,6 +5575,7 @@ spec: count: description: Count of Elasticsearch nodes to deploy. format: int32 + minimum: 1 type: integer name: description: Name of this set of nodes. Becomes a part of the @@ -10369,8 +10370,10 @@ spec: type: object type: array required: + - count - name type: object + minItems: 1 type: array podDisruptionBudget: description: PodDisruptionBudget provides access to the default pod @@ -10517,6 +10520,8 @@ spec: version: description: Version of Elasticsearch. type: string + required: + - nodeSets type: object status: description: ElasticsearchStatus defines the observed state of Elasticsearch diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 0000000000..f14a7c5f03 --- /dev/null +++ b/config/webhook/manifests.yaml @@ -0,0 +1,26 @@ + +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: validating-webhook-configuration +webhooks: +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-elasticsearch + failurePolicy: Ignore + name: elastic-es-validation + rules: + - apiGroups: + - elasticsearch.k8s.elastic.co + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - elasticsearches diff --git a/pkg/apis/elasticsearch/v1beta1/elasticsearch_types.go b/pkg/apis/elasticsearch/v1beta1/elasticsearch_types.go index 4bfdec98bf..636458be16 100644 --- a/pkg/apis/elasticsearch/v1beta1/elasticsearch_types.go +++ b/pkg/apis/elasticsearch/v1beta1/elasticsearch_types.go @@ -22,13 +22,16 @@ type ElasticsearchSpec struct { Image string `json:"image,omitempty"` // HTTP holds HTTP layer settings for Elasticsearch. + // +kubebuilder:validation:Optional HTTP commonv1beta1.HTTPConfig `json:"http,omitempty"` // NodeSets allow specifying groups of Elasticsearch nodes sharing the same configuration and Pod templates. // See: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-orchestration.html - NodeSets []NodeSet `json:"nodeSets,omitempty"` + // +kubebuilder:validation:MinItems=1 + NodeSets []NodeSet `json:"nodeSets"` // UpdateStrategy specifies how updates to the cluster should be performed. + // +kubebuilder:validation:Optional UpdateStrategy UpdateStrategy `json:"updateStrategy,omitempty"` // PodDisruptionBudget provides access to the default pod disruption budget for the Elasticsearch cluster. @@ -39,6 +42,7 @@ type ElasticsearchSpec struct { // SecureSettings is a list of references to Kubernetes secrets containing sensitive configuration options for Elasticsearch. // See: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-es-secure-settings.html + // +kubebuilder:validation:Optional SecureSettings []commonv1beta1.SecretSource `json:"secureSettings,omitempty"` } @@ -62,7 +66,8 @@ type NodeSet struct { Config *commonv1beta1.Config `json:"config,omitempty"` // Count of Elasticsearch nodes to deploy. - Count int32 `json:"count,omitempty"` + // +kubebuilder:validation:Minimum=1 + Count int32 `json:"count"` // PodTemplate provides customisation options (labels, annotations, affinity rules, resource requests, and so on) for the Pods belonging to this NodeSet. // +kubebuilder:validation:Optional diff --git a/pkg/controller/elasticsearch/settings/fields.go b/pkg/apis/elasticsearch/v1beta1/fields.go similarity index 98% rename from pkg/controller/elasticsearch/settings/fields.go rename to pkg/apis/elasticsearch/v1beta1/fields.go index 4c83325304..4875a67b54 100644 --- a/pkg/controller/elasticsearch/settings/fields.go +++ b/pkg/apis/elasticsearch/v1beta1/fields.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package settings +package v1beta1 const ( ClusterName = "cluster.name" @@ -41,7 +41,7 @@ const ( XPackSecurityTransportSslVerificationMode = "xpack.security.transport.ssl.verification_mode" ) -var Blacklist = []string{ +var SettingsBlacklist = []string{ ClusterName, DiscoveryZenMinimumMasterNodes, ClusterInitialMasterNodes, diff --git a/pkg/controller/elasticsearch/name/name.go b/pkg/apis/elasticsearch/v1beta1/name.go similarity index 84% rename from pkg/controller/elasticsearch/name/name.go rename to pkg/apis/elasticsearch/v1beta1/name.go index 8718f8039a..3f09034d5d 100644 --- a/pkg/controller/elasticsearch/name/name.go +++ b/pkg/apis/elasticsearch/v1beta1/name.go @@ -2,19 +2,17 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package name +package v1beta1 import ( "fmt" "strconv" "strings" - "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" common_name "github.com/elastic/cloud-on-k8s/pkg/controller/common/name" - "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/pkg/errors" apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation" - "k8s.io/apimachinery/pkg/util/validation" + utilvalidation "k8s.io/apimachinery/pkg/util/validation" ) const ( @@ -52,20 +50,18 @@ var ( } ) -// Validate checks the validity of resource names that will be generated by the given Elasticsearch object. -func Validate(es v1beta1.Elasticsearch) error { - esName := k8s.ExtractNamespacedName(&es).Name - if len(esName) > common_name.MaxResourceNameLength { +// validateNames checks the validity of resource names that will be generated by the given Elasticsearch object. +func validateNames(es *Elasticsearch) error { + if len(es.Name) > common_name.MaxResourceNameLength { return fmt.Errorf("name exceeds maximum allowed length of %d", common_name.MaxResourceNameLength) } - // validate ssets for _, nodeSet := range es.Spec.NodeSets { if errs := apimachineryvalidation.NameIsDNSSubdomain(nodeSet.Name, false); len(errs) > 0 { return fmt.Errorf("invalid nodeSet name '%s': [%s]", nodeSet.Name, strings.Join(errs, ",")) } - ssetName, err := ESNamer.SafeSuffix(esName, nodeSet.Name) + ssetName, err := ESNamer.SafeSuffix(es.Name, nodeSet.Name) if err != nil { return errors.Wrapf(err, "error generating StatefulSet name for nodeSet: '%s'", nodeSet.Name) } @@ -73,16 +69,16 @@ func Validate(es v1beta1.Elasticsearch) error { // length of the ordinal suffix that will be added to the pods of this sset (dash + ordinal) podOrdinalSuffixLen := len(strconv.FormatInt(int64(nodeSet.Count), 10)) + 1 // there should be enough space for the ordinal suffix and the controller revision hash - if validation.LabelValueMaxLength-len(ssetName) < podOrdinalSuffixLen+controllerRevisionHashLen { + if utilvalidation.LabelValueMaxLength-len(ssetName) < podOrdinalSuffixLen+controllerRevisionHashLen { return fmt.Errorf("generated StatefulSet name '%s' exceeds allowed length of %d", ssetName, - validation.LabelValueMaxLength-podOrdinalSuffixLen-controllerRevisionHashLen) + utilvalidation.LabelValueMaxLength-podOrdinalSuffixLen-controllerRevisionHashLen) } } // validate other suffixes for _, suffix := range suffixes { - if _, err := ESNamer.SafeSuffix(esName, suffix); err != nil { + if _, err := ESNamer.SafeSuffix(es.Name, suffix); err != nil { return err } } diff --git a/pkg/controller/elasticsearch/name/name_test.go b/pkg/apis/elasticsearch/v1beta1/name_test.go similarity index 86% rename from pkg/controller/elasticsearch/name/name_test.go rename to pkg/apis/elasticsearch/v1beta1/name_test.go index 7e4bc1b7b1..09f8b77a7f 100644 --- a/pkg/controller/elasticsearch/name/name_test.go +++ b/pkg/apis/elasticsearch/v1beta1/name_test.go @@ -2,12 +2,11 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package name +package v1beta1 import ( "testing" - "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -51,19 +50,19 @@ func TestValidate(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - es := v1beta1.Elasticsearch{ + es := &Elasticsearch{ ObjectMeta: metav1.ObjectMeta{ Name: tc.esName, Namespace: "test", }, - Spec: v1beta1.ElasticsearchSpec{}, + Spec: ElasticsearchSpec{}, } for _, nodeSpecName := range tc.nodeSpecNames { - es.Spec.NodeSets = append(es.Spec.NodeSets, v1beta1.NodeSet{Name: nodeSpecName, Count: 10}) + es.Spec.NodeSets = append(es.Spec.NodeSets, NodeSet{Name: nodeSpecName, Count: 10}) } - err := Validate(es) + err := validateNames(es) if tc.wantErr { require.Error(t, err) require.Contains(t, err.Error(), tc.wantErrMsg) diff --git a/pkg/apis/elasticsearch/v1beta1/validations.go b/pkg/apis/elasticsearch/v1beta1/validations.go new file mode 100644 index 0000000000..0ccd5b5f87 --- /dev/null +++ b/pkg/apis/elasticsearch/v1beta1/validations.go @@ -0,0 +1,229 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package v1beta1 + +import ( + "fmt" + "net" + "reflect" + + common "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" + esversion "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/version" + netutil "github.com/elastic/cloud-on-k8s/pkg/utils/net" + "k8s.io/apimachinery/pkg/util/validation/field" +) + +const ( + cfgInvalidMsg = "Configuration invalid" + masterRequiredMsg = "Elasticsearch needs to have at least one master node" + parseVersionErrMsg = "Cannot parse Elasticsearch version" + parseStoredVersionErrMsg = "Cannot parse current Elasticsearch version" + invalidSanIPErrMsg = "Invalid SAN IP address" + pvcImmutableMsg = "Volume claim templates cannot be modified" + invalidNamesErrMsg = "Elasticsearch configuration would generate resources with invalid names" + unsupportedVersionErrMsg = "Unsupported version" + blacklistedConfigErrMsg = "Configuration setting is not user-configurable" + duplicateNodeSets = "NodeSet names must be unique" + noDowngradesMsg = "Downgrades are not supported" + unsupportedVersionMsg = "Unsupported version" + unsupportedUpgradeMsg = "Unsupported version upgrade path" +) + +type validation func(*Elasticsearch) field.ErrorList + +// validations are the validation funcs that apply to creates or updates +var validations = []validation{ + validName, + hasMaster, + supportedVersion, + noBlacklistedSettings, + validSanIP, +} + +type updateValidation func(*Elasticsearch, *Elasticsearch) field.ErrorList + +// updateValidations are the validation funcs that only apply to updates +var updateValidations = []updateValidation{ + noDowngrades, + validUpgradePath, + pvcModification, +} + +// validName checks whether the name is valid. +func validName(es *Elasticsearch) field.ErrorList { + var errs field.ErrorList + if err := validateNames(es); err != nil { + errs = append(errs, field.Invalid(field.NewPath("metadata").Child("name"), es.Name, fmt.Sprintf("%s: %s", invalidNamesErrMsg, err))) + } + return errs +} + +func supportedVersion(es *Elasticsearch) field.ErrorList { + ver, err := version.Parse(es.Spec.Version) + if err != nil { + return field.ErrorList{field.Invalid(field.NewPath("spec").Child("version"), es.Spec.Version, parseVersionErrMsg)} + } + if v := esversion.SupportedVersions(*ver); v != nil { + if err := v.Supports(*ver); err == nil { + return field.ErrorList{} + } + } + return field.ErrorList{field.Invalid(field.NewPath("spec").Child("version"), es.Spec.Version, unsupportedVersionErrMsg)} +} + +// hasMaster checks if the given Elasticsearch cluster has at least one master node. +func hasMaster(es *Elasticsearch) field.ErrorList { + var errs field.ErrorList + var hasMaster bool + for i, t := range es.Spec.NodeSets { + cfg, err := UnpackConfig(t.Config) + if err != nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("nodeSets").Index(i), t.Config, cfgInvalidMsg)) + } + hasMaster = hasMaster || (cfg.Node.Master && t.Count > 0) + } + if !hasMaster { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("nodeSets"), es.Spec.NodeSets, masterRequiredMsg)) + } + return errs +} + +func noBlacklistedSettings(es *Elasticsearch) field.ErrorList { + var errs field.ErrorList + for i, nodeSet := range es.Spec.NodeSets { + if nodeSet.Config == nil { + continue + } + config, err := common.NewCanonicalConfigFrom(nodeSet.Config.Data) + if err != nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("nodeSets").Index(i).Child("config"), es.Spec.NodeSets[i].Config, cfgInvalidMsg)) + continue + } + forbidden := config.HasKeys(SettingsBlacklist) + for _, setting := range forbidden { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("nodeSets").Index(i).Child("config"), setting, blacklistedConfigErrMsg)) + } + } + return errs +} + +func validSanIP(es *Elasticsearch) field.ErrorList { + var errs field.ErrorList + selfSignedCerts := es.Spec.HTTP.TLS.SelfSignedCertificate + if selfSignedCerts != nil { + for _, san := range selfSignedCerts.SubjectAlternativeNames { + if san.IP != "" { + ip := netutil.MaybeIPTo4(net.ParseIP(san.IP)) + if ip == nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("http", "tls", "selfSignedCertificate", "subjectAlternativeNames"), san.IP, invalidSanIPErrMsg)) + } + } + } + } + return errs +} + +func checkNodeSetNameUniqueness(es *Elasticsearch) field.ErrorList { + var errs field.ErrorList + nodeSets := es.Spec.NodeSets + names := make(map[string]struct{}) + duplicates := make(map[string]struct{}) + for _, nodeSet := range nodeSets { + if _, found := names[nodeSet.Name]; found { + duplicates[nodeSet.Name] = struct{}{} + } + names[nodeSet.Name] = struct{}{} + } + for _, dupe := range duplicates { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("nodeSets"), dupe, duplicateNodeSets)) + } + return errs +} + +// pvcModification ensures no PVCs are changed, as volume claim templates are immutable in stateful sets +func pvcModification(current, proposed *Elasticsearch) field.ErrorList { + var errs field.ErrorList + if current == nil || proposed == nil { + return errs + } + for i, node := range proposed.Spec.NodeSets { + currNode := getNode(node.Name, current) + if currNode == nil { + // this is a new sset, so there is nothing to check + continue + } + + // ssets do not allow modifications to fields other than 'replicas', 'template', and 'updateStrategy' + // reflection isn't ideal, but okay here since the ES object does not have the status of the claims + if !reflect.DeepEqual(node.VolumeClaimTemplates, currNode.VolumeClaimTemplates) { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("nodeSet").Index(i).Child("volumeClaimTemplates"), node.VolumeClaimTemplates, pvcImmutableMsg)) + } + } + return errs +} + +func noDowngrades(current, proposed *Elasticsearch) field.ErrorList { + var errs field.ErrorList + if current == nil || proposed == nil { + return errs + } + currentVer, err := version.Parse(current.Spec.Version) + if err != nil { + // this should not happen, since this is the already persisted version + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), current.Spec.Version, parseStoredVersionErrMsg)) + } + currVer, err := version.Parse(proposed.Spec.Version) + if err != nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), proposed.Spec.Version, parseVersionErrMsg)) + } + if len(errs) != 0 { + return errs + } + if !currVer.IsSameOrAfter(*currentVer) { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), proposed.Spec.Version, noDowngradesMsg)) + } + return errs +} + +func validUpgradePath(current, proposed *Elasticsearch) field.ErrorList { + var errs field.ErrorList + if current == nil || proposed == nil { + return errs + } + currentVer, err := version.Parse(current.Spec.Version) + if err != nil { + // this should not happen, since this is the already persisted version + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), current.Spec.Version, parseStoredVersionErrMsg)) + } + currVer, err := version.Parse(proposed.Spec.Version) + if err != nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), proposed.Spec.Version, parseVersionErrMsg)) + } + if len(errs) != 0 { + return errs + } + + v := esversion.SupportedVersions(*currVer) + if v == nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), proposed.Spec.Version, unsupportedVersionMsg)) + return errs + } + + err = v.Supports(*currentVer) + if err != nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("version"), proposed.Spec.Version, unsupportedUpgradeMsg)) + } + return errs +} + +func getNode(name string, es *Elasticsearch) *NodeSet { + for i := range es.Spec.NodeSets { + if es.Spec.NodeSets[i].Name == name { + return &es.Spec.NodeSets[i] + } + } + return nil +} diff --git a/pkg/apis/elasticsearch/v1beta1/validations_test.go b/pkg/apis/elasticsearch/v1beta1/validations_test.go new file mode 100644 index 0000000000..b32b78305c --- /dev/null +++ b/pkg/apis/elasticsearch/v1beta1/validations_test.go @@ -0,0 +1,785 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package v1beta1 + +import ( + "testing" + + common "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_checkNodeSetNameUniqueness(t *testing.T) { + type args struct { + name string + es *Elasticsearch + expectErrors bool + } + tests := []args{ + { + name: "several duplicate nodeSets", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.4.0", + NodeSets: []NodeSet{ + {Name: "foo", Count: 1}, {Name: "foo", Count: 1}, + {Name: "bar", Count: 1}, {Name: "bar", Count: 1}, + }, + }, + }, + expectErrors: true, + }, + { + name: "good spec with 1 nodeSet", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.4.0", + NodeSets: []NodeSet{{Name: "foo", Count: 1}}, + }, + }, + expectErrors: false, + }, + { + name: "good spec with 2 nodeSets", + es: &Elasticsearch{ + TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, + Spec: ElasticsearchSpec{ + Version: "7.4.0", + NodeSets: []NodeSet{{Name: "foo", Count: 1}, {Name: "bar", Count: 1}}, + }, + }, + expectErrors: false, + }, + { + name: "duplicate nodeSet", + es: &Elasticsearch{ + TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, + Spec: ElasticsearchSpec{ + Version: "7.4.0", + NodeSets: []NodeSet{{Name: "foo", Count: 1}, {Name: "foo", Count: 1}}, + }, + }, + expectErrors: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := checkNodeSetNameUniqueness(tt.es) + actualErrors := len(actual) > 0 + + if tt.expectErrors != actualErrors { + t.Errorf("failed checkNodeSetNameUniqueness(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.es.Spec.NodeSets) + } + }) + } +} + +func Test_hasMaster(t *testing.T) { + tests := []struct { + name string + es *Elasticsearch + expectErrors bool + }{ + { + name: "no topology", + es: es("6.8.0"), + expectErrors: true, + }, + { + name: "topology but no master", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + NodeMaster: "false", + NodeData: "false", + NodeIngest: "false", + NodeML: "false", + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + { + name: "master but zero sized", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + NodeMaster: "true", + NodeData: "false", + NodeIngest: "false", + NodeML: "false", + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + { + name: "has master", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + NodeMaster: "false", + NodeData: "true", + NodeIngest: "false", + NodeML: "false", + }, + }, + Count: 1, + }, + + { + Config: &common.Config{ + Data: map[string]interface{}{ + NodeMaster: "true", + NodeData: "false", + NodeIngest: "false", + NodeML: "false", + }, + }, + Count: 1, + }, + }, + }, + }, + expectErrors: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := hasMaster(tt.es) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed hasMaster(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.es.Spec.NodeSets) + } + }) + } +} + +func Test_supportedVersion(t *testing.T) { + tests := []struct { + name string + es *Elasticsearch + expectErrors bool + }{ + { + name: "unsupported minor version should fail", + es: es("6.0.0"), + + expectErrors: true, + }, + { + name: "unsupported major should fail", + es: es("1.0.0"), + expectErrors: true, + }, + { + name: "supported OK", + es: es("6.8.0"), + expectErrors: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := supportedVersion(tt.es) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed supportedVersion(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.es.Spec.Version) + } + }) + } +} + +func Test_noBlacklistedSettings(t *testing.T) { + tests := []struct { + name string + es *Elasticsearch + expectErrors bool + }{ + + { + name: "no settings OK", + es: es("7.0.0"), + expectErrors: false, + }, + { + name: "enforce blacklist FAIL", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + ClusterInitialMasterNodes: "foo", + }, + }, + Count: 1, + }, + }, + }, + }, + expectErrors: true, + }, + { + name: "enforce blacklist in multiple nodes FAIL", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + ClusterInitialMasterNodes: "foo", + }, + }, + }, + { + Config: &common.Config{ + Data: map[string]interface{}{ + XPackSecurityTransportSslVerificationMode: "bar", + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + { + name: "non blacklisted setting OK", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + "node.attr.box_type": "foo", + }, + }, + }, + }, + }, + }, + expectErrors: false, + }, + { + name: "non blacklisted settings with blacklisted string prefix OK", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + XPackSecurityTransportSslCertificateAuthorities: "foo", + }, + }, + }, + }, + }, + }, + expectErrors: false, + }, + { + name: "settings are canonicalized before validation", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.0.0", + NodeSets: []NodeSet{ + { + Config: &common.Config{ + Data: map[string]interface{}{ + "cluster": map[string]interface{}{ + "initial_master_nodes": []string{"foo", "bar"}, + }, + "node.attr.box_type": "foo", + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := noBlacklistedSettings(tt.es) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed noBlacklistedSettings(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.es.Spec.Version) + } + }) + } +} + +func Test_validName(t *testing.T) { + tests := []struct { + name string + es *Elasticsearch + expectErrors bool + }{ + { + name: "name length too long", + es: &Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "that-is-a-very-long-name-with-37chars", + }, + }, + expectErrors: true, + }, + { + name: "name length OK", + es: &Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "that-is-a-very-long-name-with-36char", + }, + }, + expectErrors: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := validName(tt.es) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed validName(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.es.Name) + } + }) + } +} + +func Test_validSanIP(t *testing.T) { + validIP := "3.4.5.6" + validIP2 := "192.168.12.13" + validIPv6 := "2001:db8:0:85a3:0:0:ac1f:8001" + invalidIP := "notanip" + + tests := []struct { + name string + es *Elasticsearch + expectErrors bool + }{ + { + name: "no SAN IP: OK", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{}, + }, + expectErrors: false, + }, + { + name: "valid SAN IPs: OK", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + HTTP: common.HTTPConfig{ + TLS: common.TLSOptions{ + SelfSignedCertificate: &common.SelfSignedCertificate{ + SubjectAlternativeNames: []common.SubjectAlternativeName{ + { + IP: validIP, + }, + { + IP: validIP2, + }, + { + IP: validIPv6, + }, + }, + }, + }, + }, + }, + }, + expectErrors: false, + }, + { + name: "invalid SAN IPs: NOT OK", + es: &Elasticsearch{ + Spec: ElasticsearchSpec{ + HTTP: common.HTTPConfig{ + TLS: common.TLSOptions{ + SelfSignedCertificate: &common.SelfSignedCertificate{ + SubjectAlternativeNames: []common.SubjectAlternativeName{ + { + IP: invalidIP, + }, + { + IP: validIP2, + }, + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := validSanIP(tt.es) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed validSanIP(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.es.Spec) + } + }) + } +} + +func Test_pvcModified(t *testing.T) { + current := getEsCluster() + + tests := []struct { + name string + current *Elasticsearch + proposed *Elasticsearch + expectErrors bool + }{ + { + name: "resize fails", + current: current, + proposed: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.2.0", + NodeSets: []NodeSet{ + { + Name: "master", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("10Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + + { + name: "same size accepted", + current: current, + proposed: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.2.0", + NodeSets: []NodeSet{ + { + Name: "master", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("5Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectErrors: false, + }, + + { + name: "additional PVC fails", + current: current, + proposed: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.2.0", + NodeSets: []NodeSet{ + { + Name: "master", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("5Gi"), + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data1", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("5Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + + { + name: "name change rejected", + current: current, + proposed: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.2.0", + NodeSets: []NodeSet{ + { + Name: "master", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data1", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("5Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectErrors: true, + }, + + { + name: "add new node set accepted", + current: current, + proposed: &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.2.0", + NodeSets: []NodeSet{ + { + Name: "master", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("5Gi"), + }, + }, + }, + }, + }, + }, + { + Name: "ingest", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("10Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectErrors: false, + }, + + { + name: "new instance accepted", + current: nil, + proposed: current, + expectErrors: false, + }, + } + + for _, tt := range tests { + actual := pvcModification(tt.current, tt.proposed) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed pvcModification(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.proposed) + } + } +} + +func TestValidation_noDowngrades(t *testing.T) { + tests := []struct { + name string + current *Elasticsearch + proposed *Elasticsearch + expectErrors bool + }{ + { + name: "no validation on create", + current: nil, + proposed: es("6.8.0"), + expectErrors: false, + }, + { + name: "prevent downgrade", + current: es("2.0.0"), + proposed: es("1.0.0"), + expectErrors: true, + }, + { + name: "allow upgrades", + current: es("1.0.0"), + proposed: es("1.2.0"), + expectErrors: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := noDowngrades(tt.current, tt.proposed) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed noDowngrades(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.proposed) + } + }) + } +} + +func Test_validUpgradePath(t *testing.T) { + + tests := []struct { + name string + current *Elasticsearch + proposed *Elasticsearch + expectErrors bool + }{ + { + name: "new cluster accepted", + current: nil, + proposed: es("1.0.0"), + expectErrors: false, + }, + { + name: "unsupported version rejected", + current: es("1.0.0"), + proposed: es("2.0.0"), + + expectErrors: true, + }, + { + name: "too old version rejected", + current: es("6.5.0"), + proposed: es("7.0.0"), + expectErrors: true, + }, + { + name: "too new rejected", + current: es("7.0.0"), + proposed: es("6.5.0"), + expectErrors: true, + }, + { + name: "in range accepted", + current: es("6.8.0"), + proposed: es("7.1.0"), + expectErrors: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := validUpgradePath(tt.current, tt.proposed) + actualErrors := len(actual) > 0 + if tt.expectErrors != actualErrors { + t.Errorf("failed validUpgradePath(). Name: %v, actual %v, wanted: %v, value: %v", tt.name, actual, tt.expectErrors, tt.proposed) + } + }) + } +} + +// es returns an es fixture at a given version +func es(v string) *Elasticsearch { + return &Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "foo", + }, + Spec: ElasticsearchSpec{Version: v}, + } +} + +// // getEsCluster returns a ES cluster test fixture +func getEsCluster() *Elasticsearch { + return &Elasticsearch{ + Spec: ElasticsearchSpec{ + Version: "7.2.0", + NodeSets: []NodeSet{ + { + Name: "master", + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "elasticsearch-data", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("5Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + } +} diff --git a/pkg/apis/elasticsearch/v1beta1/webhook.go b/pkg/apis/elasticsearch/v1beta1/webhook.go new file mode 100644 index 0000000000..816bcd2840 --- /dev/null +++ b/pkg/apis/elasticsearch/v1beta1/webhook.go @@ -0,0 +1,77 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package v1beta1 + +import ( + "errors" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +// +kubebuilder:webhook:path=/validate-elasticsearch,mutating=false,failurePolicy=ignore,groups=elasticsearch.k8s.elastic.co,resources=elasticsearches,verbs=create;update,versions=v1beta1,name=elastic-es-validation + +func (r *Elasticsearch) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +var eslog = logf.Log.WithName("es-validation") + +var _ webhook.Validator = &Elasticsearch{} + +func (r *Elasticsearch) ValidateCreate() error { + eslog.V(1).Info("validate create", "name", r.Name) + return r.validateElasticsearch() +} + +// ValidateDelete is required to implement webhook.Validator, but we do not actually validate deletes +func (r *Elasticsearch) ValidateDelete() error { + return nil +} + +func (r *Elasticsearch) ValidateUpdate(old runtime.Object) error { + eslog.V(1).Info("validate update", "name", r.Name) + oldEs, ok := old.(*Elasticsearch) + if !ok { + return errors.New("cannot cast old object to Elasticsearch type") + } + + var errs field.ErrorList + for _, val := range updateValidations { + if err := val(oldEs, r); err != nil { + errs = append(errs, err...) + } + } + if len(errs) > 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "elasticsearch.k8s.elastic.co", Kind: "Elasticsearch"}, + r.Name, errs) + } + return r.validateElasticsearch() +} + +func (r *Elasticsearch) validateElasticsearch() error { + var errs field.ErrorList + for _, val := range validations { + if err := val(r); err != nil { + errs = append(errs, err...) + } + } + + if len(errs) == 0 { + return nil + } + + return apierrors.NewInvalid( + schema.GroupKind{Group: "elasticsearch.k8s.elastic.co", Kind: "Elasticsearch"}, + r.Name, errs) +} diff --git a/pkg/apis/elasticsearch/v1beta1/zz_generated.deepcopy.go b/pkg/apis/elasticsearch/v1beta1/zz_generated.deepcopy.go index 209fd868ac..53cca5c1b8 100644 --- a/pkg/apis/elasticsearch/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/elasticsearch/v1beta1/zz_generated.deepcopy.go @@ -11,7 +11,7 @@ package v1beta1 import ( commonv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" "k8s.io/api/core/v1" - runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/pkg/controller/apmserverelasticsearchassociation/apmserverelasticsearchassociation_controller.go b/pkg/controller/apmserverelasticsearchassociation/apmserverelasticsearchassociation_controller.go index 04f624c981..62bd461ed4 100644 --- a/pkg/controller/apmserverelasticsearchassociation/apmserverelasticsearchassociation_controller.go +++ b/pkg/controller/apmserverelasticsearchassociation/apmserverelasticsearchassociation_controller.go @@ -21,7 +21,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" "github.com/elastic/cloud-on-k8s/pkg/controller/common/user" "github.com/elastic/cloud-on-k8s/pkg/controller/common/watches" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/services" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" @@ -316,7 +315,7 @@ func (r *ReconcileApmServerElasticsearchAssociation) reconcileElasticsearchCA(ap // watch ES CA secret to reconcile on any change if err := r.watches.Secrets.AddHandler(watches.NamedWatch{ Name: esCAWatchName(apmKey), - Watched: []types.NamespacedName{http.PublicCertsSecretRef(esname.ESNamer, es)}, + Watched: []types.NamespacedName{http.PublicCertsSecretRef(estype.ESNamer, es)}, Watcher: apmKey, }); err != nil { return association.CASecret{}, err diff --git a/pkg/controller/common/association/ca.go b/pkg/controller/common/association/ca.go index c227f2f1bb..1ebe7e8ad7 100644 --- a/pkg/controller/common/association/ca.go +++ b/pkg/controller/common/association/ca.go @@ -8,10 +8,10 @@ import ( "reflect" commonv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates/http" "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -42,7 +42,7 @@ func ReconcileCASecret( labels map[string]string, suffix string, ) (CASecret, error) { - publicESHTTPCertificatesNSN := http.PublicCertsSecretRef(esname.ESNamer, es) + publicESHTTPCertificatesNSN := http.PublicCertsSecretRef(v1beta1.ESNamer, es) // retrieve the HTTP certificates from ES namespace var publicESHTTPCertificatesSecret corev1.Secret diff --git a/pkg/controller/common/association/ca_test.go b/pkg/controller/common/association/ca_test.go index 8103775b4e..ac3ead2354 100644 --- a/pkg/controller/common/association/ca_test.go +++ b/pkg/controller/common/association/ca_test.go @@ -11,7 +11,6 @@ import ( kbtype "github.com/elastic/cloud-on-k8s/pkg/apis/kibana/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/watches" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -38,7 +37,7 @@ func TestReconcileAssociation_reconcileCASecret(t *testing.T) { esCA := corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: es.Namespace, - Name: certificates.PublicSecretName(esname.ESNamer, es.Name, certificates.HTTPCAType), + Name: certificates.PublicSecretName(estype.ESNamer, es.Name, certificates.HTTPCAType), }, Data: map[string][]byte{ certificates.CertFileName: []byte("fake-cert"), @@ -48,7 +47,7 @@ func TestReconcileAssociation_reconcileCASecret(t *testing.T) { updatedEsCA := corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: es.Namespace, - Name: certificates.PublicSecretName(esname.ESNamer, es.Name, certificates.HTTPCAType), + Name: certificates.PublicSecretName(estype.ESNamer, es.Name, certificates.HTTPCAType), }, Data: map[string][]byte{ certificates.CertFileName: []byte("updated-fake-cert"), diff --git a/pkg/controller/common/certificates/http/public_secret_test.go b/pkg/controller/common/certificates/http/public_secret_test.go index f1e5b0a8d8..1d0028c9cb 100644 --- a/pkg/controller/common/certificates/http/public_secret_test.go +++ b/pkg/controller/common/certificates/http/public_secret_test.go @@ -10,7 +10,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" @@ -37,7 +36,7 @@ func TestReconcileHTTPCertsPublicSecret(t *testing.T) { }, } - namespacedSecretName := PublicCertsSecretRef(name.ESNamer, k8s.ExtractNamespacedName(owner)) + namespacedSecretName := PublicCertsSecretRef(v1beta1.ESNamer, k8s.ExtractNamespacedName(owner)) mkClient := func(t *testing.T, objs ...runtime.Object) k8s.Client { t.Helper() @@ -127,7 +126,7 @@ func TestReconcileHTTPCertsPublicSecret(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { client := tt.client(t) - err := ReconcileHTTPCertsPublicSecret(client, scheme.Scheme, owner, name.ESNamer, certificate) + err := ReconcileHTTPCertsPublicSecret(client, scheme.Scheme, owner, v1beta1.ESNamer, certificate) if tt.wantErr { require.Error(t, err, "Failed to reconcile") return diff --git a/pkg/controller/common/certificates/http/reconcile_test.go b/pkg/controller/common/certificates/http/reconcile_test.go index 045d989d55..6b4a426d98 100644 --- a/pkg/controller/common/certificates/http/reconcile_test.go +++ b/pkg/controller/common/certificates/http/reconcile_test.go @@ -19,7 +19,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/driver" "github.com/elastic/cloud-on-k8s/pkg/controller/common/watches" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -86,7 +85,7 @@ func init() { testCSR, _ := x509.ParseCertificateRequest(testCSRBytes) validatedCertificateTemplate := createValidatedHTTPCertificateTemplate( - k8s.ExtractNamespacedName(&testES), name.ESNamer, testES.Spec.HTTP.TLS, []corev1.Service{testSvc}, testCSR, certificates.DefaultCertValidity, + k8s.ExtractNamespacedName(&testES), v1beta1.ESNamer, testES.Spec.HTTP.TLS, []corev1.Service{testSvc}, testCSR, certificates.DefaultCertValidity, ) certData, err := testCA.CreateCertificate(*validatedCertificateTemplate) @@ -166,7 +165,7 @@ func TestReconcileHTTPCertificates(t *testing.T) { } got, err := ReconcileHTTPCertificates( - testDriver, &tt.args.es, name.ESNamer, tt.args.ca, tt.args.es.Spec.HTTP.TLS, map[string]string{}, tt.args.services, + testDriver, &tt.args.es, v1beta1.ESNamer, tt.args.ca, tt.args.es.Spec.HTTP.TLS, map[string]string{}, tt.args.services, certificates.RotationParams{ Validity: certificates.DefaultCertValidity, RotateBefore: certificates.DefaultRotateBefore, @@ -253,7 +252,7 @@ func Test_createValidatedHTTPCertificateTemplate(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got := createValidatedHTTPCertificateTemplate( k8s.ExtractNamespacedName(&tt.args.es), - name.ESNamer, + v1beta1.ESNamer, tt.args.es.Spec.HTTP.TLS, tt.args.svcs, &x509.CertificateRequest{}, @@ -355,7 +354,7 @@ func Test_shouldIssueNewCertificate(t *testing.T) { t.Run(tt.name, func(t *testing.T) { if got := shouldIssueNewHTTPCertificate( k8s.ExtractNamespacedName(&tt.args.es), - name.ESNamer, + v1beta1.ESNamer, tt.args.es.Spec.HTTP.TLS, &tt.args.secret, []corev1.Service{testSvc}, diff --git a/pkg/controller/elasticsearch/certificates/ca_reconcile.go b/pkg/controller/elasticsearch/certificates/ca_reconcile.go index f7671ec54f..d819ac87ed 100644 --- a/pkg/controller/elasticsearch/certificates/ca_reconcile.go +++ b/pkg/controller/elasticsearch/certificates/ca_reconcile.go @@ -15,7 +15,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/certificates/transport" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -47,7 +46,7 @@ func Reconcile( httpCA, err := certificates.ReconcileCAForOwner( driver.K8sClient(), driver.Scheme(), - name.ESNamer, + v1beta1.ESNamer, &es, labels, certificates.HTTPCAType, @@ -66,7 +65,7 @@ func Reconcile( httpCertificates, err := http.ReconcileHTTPCertificates( driver, &es, - name.ESNamer, + v1beta1.ESNamer, httpCA, es.Spec.HTTP.TLS, labels, @@ -78,14 +77,14 @@ func Reconcile( } // reconcile http public certs secret: - if err := http.ReconcileHTTPCertsPublicSecret(driver.K8sClient(), driver.Scheme(), &es, name.ESNamer, httpCertificates); err != nil { + if err := http.ReconcileHTTPCertsPublicSecret(driver.K8sClient(), driver.Scheme(), &es, v1beta1.ESNamer, httpCertificates); err != nil { return nil, results.WithError(err) } transportCA, err := certificates.ReconcileCAForOwner( driver.K8sClient(), driver.Scheme(), - name.ESNamer, + v1beta1.ESNamer, &es, labels, certificates.TransportCAType, diff --git a/pkg/controller/elasticsearch/certificates/transport/public_secret.go b/pkg/controller/elasticsearch/certificates/transport/public_secret.go index 9ce5e54e09..c3d496b6c9 100644 --- a/pkg/controller/elasticsearch/certificates/transport/public_secret.go +++ b/pkg/controller/elasticsearch/certificates/transport/public_secret.go @@ -11,7 +11,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/elastic/cloud-on-k8s/pkg/utils/maps" corev1 "k8s.io/api/core/v1" @@ -68,7 +67,7 @@ func ReconcileTransportCertsPublicSecret( // PublicCertsSecretRef returns the NamespacedName for the Secret containing the publicly available transport CA. func PublicCertsSecretRef(es types.NamespacedName) types.NamespacedName { return types.NamespacedName{ - Name: certificates.PublicSecretName(name.ESNamer, es.Name, certificates.TransportCAType), + Name: certificates.PublicSecretName(v1beta1.ESNamer, es.Name, certificates.TransportCAType), Namespace: es.Namespace, } } diff --git a/pkg/controller/elasticsearch/certificates/transport/reconcile.go b/pkg/controller/elasticsearch/certificates/transport/reconcile.go index 4b35a33af8..3c5a9f2eec 100644 --- a/pkg/controller/elasticsearch/certificates/transport/reconcile.go +++ b/pkg/controller/elasticsearch/certificates/transport/reconcile.go @@ -14,7 +14,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -116,7 +115,7 @@ func ensureTransportCertificatesSecretExists( expected := corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: es.Namespace, - Name: name.TransportCertificatesSecret(es.Name), + Name: v1beta1.TransportCertificatesSecret(es.Name), Labels: map[string]string{ // a label showing which es these certificates belongs to diff --git a/pkg/controller/elasticsearch/certificates/transport/reconcile_test.go b/pkg/controller/elasticsearch/certificates/transport/reconcile_test.go index 2495501a2c..05595ede62 100644 --- a/pkg/controller/elasticsearch/certificates/transport/reconcile_test.go +++ b/pkg/controller/elasticsearch/certificates/transport/reconcile_test.go @@ -7,8 +7,6 @@ package transport import ( "testing" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" - "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" @@ -23,7 +21,7 @@ import ( func Test_ensureTransportCertificateSecretExists(t *testing.T) { defaultSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: name.TransportCertificatesSecret(testES.Name), + Name: v1beta1.TransportCertificatesSecret(testES.Name), Namespace: testES.Namespace, Labels: map[string]string{ label.ClusterNameLabelName: testES.Name, diff --git a/pkg/controller/elasticsearch/configmap/configmap.go b/pkg/controller/elasticsearch/configmap/configmap.go index a70aadd107..86f0b23c9c 100644 --- a/pkg/controller/elasticsearch/configmap/configmap.go +++ b/pkg/controller/elasticsearch/configmap/configmap.go @@ -8,7 +8,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/initcontainer" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/nodespec" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" @@ -38,7 +37,7 @@ func ReconcileScriptsConfigMap(c k8s.Client, scheme *runtime.Scheme, es v1beta1. } scriptsConfigMap := NewConfigMapWithData( - types.NamespacedName{Namespace: es.Namespace, Name: name.ScriptsConfigMap(es.Name)}, + types.NamespacedName{Namespace: es.Namespace, Name: v1beta1.ScriptsConfigMap(es.Name)}, map[string]string{ nodespec.ReadinessProbeScriptConfigKey: nodespec.ReadinessProbeScript, initcontainer.PrepareFsScriptConfigKey: fsScript, diff --git a/pkg/controller/elasticsearch/driver/driver.go b/pkg/controller/elasticsearch/driver/driver.go index 4801db97d3..43a9bb0172 100644 --- a/pkg/controller/elasticsearch/driver/driver.go +++ b/pkg/controller/elasticsearch/driver/driver.go @@ -26,7 +26,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/initcontainer" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/license" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/observer" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/reconcile" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/services" @@ -145,7 +144,7 @@ func (d *defaultDriver) Reconcile() *reconciler.Results { if err != nil { return results.WithError(err) } - min, err := esversion.MinVersion(resourcesState.CurrentPods) + min, err := minVersion(resourcesState.CurrentPods) if err != nil { return results.WithError(err) } @@ -169,7 +168,7 @@ func (d *defaultDriver) Reconcile() *reconciler.Results { d.ReconcileState.UpdateElasticsearchState(*resourcesState, observedState) } - if err := d.SupportedVersions.VerifySupportsExistingPods(resourcesState.CurrentPods); err != nil { + if err := d.verifySupportsExistingPods(resourcesState.CurrentPods); err != nil { return results.WithError(err) } @@ -217,7 +216,7 @@ func (d *defaultDriver) Reconcile() *reconciler.Results { keystoreResources, err := keystore.NewResources( d, &d.ES, - name.ESNamer, + v1beta1.ESNamer, label.NewLabels(k8s.ExtractNamespacedName(&d.ES)), initcontainer.KeystoreParams, ) diff --git a/pkg/controller/elasticsearch/driver/upscale_test.go b/pkg/controller/elasticsearch/driver/upscale_test.go index 9d41975786..e755320399 100644 --- a/pkg/controller/elasticsearch/driver/upscale_test.go +++ b/pkg/controller/elasticsearch/driver/upscale_test.go @@ -11,7 +11,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/expectations" "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/nodespec" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/sset" @@ -114,8 +113,8 @@ func TestHandleUpscaleAndSpecChanges(t *testing.T) { require.NoError(t, k8sClient.Get(types.NamespacedName{Namespace: "ns", Name: nodespec.HeadlessServiceName("sset1")}, &corev1.Service{})) require.NoError(t, k8sClient.Get(types.NamespacedName{Namespace: "ns", Name: nodespec.HeadlessServiceName("sset2")}, &corev1.Service{})) // config should be created for both - require.NoError(t, k8sClient.Get(types.NamespacedName{Namespace: "ns", Name: name.ConfigSecret("sset1")}, &corev1.Secret{})) - require.NoError(t, k8sClient.Get(types.NamespacedName{Namespace: "ns", Name: name.ConfigSecret("sset2")}, &corev1.Secret{})) + require.NoError(t, k8sClient.Get(types.NamespacedName{Namespace: "ns", Name: v1beta1.ConfigSecret("sset1")}, &corev1.Secret{})) + require.NoError(t, k8sClient.Get(types.NamespacedName{Namespace: "ns", Name: v1beta1.ConfigSecret("sset2")}, &corev1.Secret{})) // upscale data nodes actualStatefulSets = sset.StatefulSetList{sset1, sset2} @@ -329,9 +328,9 @@ func Test_adjustZenConfig(t *testing.T) { err := adjustZenConfig(client, tt.es, resources) require.NoError(t, err) for _, res := range resources { - hasMinimumMasterNodes := len(res.Config.HasKeys([]string{settings.DiscoveryZenMinimumMasterNodes})) > 0 + hasMinimumMasterNodes := len(res.Config.HasKeys([]string{v1beta1.DiscoveryZenMinimumMasterNodes})) > 0 require.Equal(t, tt.wantMinimumMasterNodesSet, hasMinimumMasterNodes) - hasInitialMasterNodes := len(res.Config.HasKeys([]string{settings.ClusterInitialMasterNodes})) > 0 + hasInitialMasterNodes := len(res.Config.HasKeys([]string{v1beta1.ClusterInitialMasterNodes})) > 0 require.Equal(t, tt.wantInitialMasterNodesSet, hasInitialMasterNodes) } }) diff --git a/pkg/controller/elasticsearch/version/running_versions.go b/pkg/controller/elasticsearch/driver/version.go similarity index 61% rename from pkg/controller/elasticsearch/version/running_versions.go rename to pkg/controller/elasticsearch/driver/version.go index bb5f39092a..107c357760 100644 --- a/pkg/controller/elasticsearch/version/running_versions.go +++ b/pkg/controller/elasticsearch/driver/version.go @@ -2,9 +2,10 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package version +package driver import ( + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" @@ -12,7 +13,7 @@ import ( ) // MinVersion extracts the currently running Elasticsearch versions from the running pods -func MinVersion(pods []corev1.Pod) (*version.Version, error) { +func minVersion(pods []corev1.Pod) (*version.Version, error) { var vs []version.Version for _, pod := range pods { v, err := label.ExtractVersion(pod.Labels) @@ -23,3 +24,16 @@ func MinVersion(pods []corev1.Pod) (*version.Version, error) { } return version.Min(vs), nil } + +func (d *defaultDriver) verifySupportsExistingPods(pods []corev1.Pod) error { + for _, pod := range pods { + v, err := label.ExtractVersion(pod.Labels) + if err != nil { + return err + } + if err := d.SupportedVersions.Supports(*v); err != nil { + return errors.Wrapf(err, "%s has incompatible version", pod.Name) + } + } + return nil +} diff --git a/pkg/controller/elasticsearch/driver/version_test.go b/pkg/controller/elasticsearch/driver/version_test.go new file mode 100644 index 0000000000..3f1b7fa265 --- /dev/null +++ b/pkg/controller/elasticsearch/driver/version_test.go @@ -0,0 +1,201 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package driver + +import ( + "reflect" + "testing" + + "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" + "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" + esversion "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/version" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var ( + testPodWithoutVersionLabel = corev1.Pod{} +) + +func Test_lowestHighestSupportedVersions_VerifySupportsExistingPods(t *testing.T) { + newPodWithVersionLabel := func(v version.Version) corev1.Pod { + return corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + label.VersionLabelName: v.String(), + }, + }, + } + } + type fields struct { + lowestSupportedVersion version.Version + highestSupportedVersion version.Version + } + type args struct { + pods []corev1.Pod + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "no pods", + fields: fields{}, + args: args{pods: []corev1.Pod{}}, + wantErr: false, + }, + { + name: "pod with version label at higher bound", + fields: fields{ + lowestSupportedVersion: version.Version{Major: 6}, + highestSupportedVersion: version.Version{Major: 7}, + }, + args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 7})}}, + wantErr: false, + }, + { + name: "pod with version label at lower bound", + fields: fields{ + lowestSupportedVersion: version.Version{Major: 6}, + highestSupportedVersion: version.Version{Major: 7}, + }, + args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 6})}}, + wantErr: false, + }, + { + name: "pod with version label within bounds", + fields: fields{ + lowestSupportedVersion: version.Version{Major: 6}, + highestSupportedVersion: version.Version{Major: 7}, + }, + args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 6, Minor: 4, Patch: 2})}}, + wantErr: false, + }, + { + name: "pod without label", + fields: fields{}, + args: args{pods: []corev1.Pod{testPodWithoutVersionLabel}}, + wantErr: true, + }, + { + name: "pod with too low version label", + fields: fields{ + lowestSupportedVersion: version.Version{Major: 6}, + highestSupportedVersion: version.Version{Major: 7}, + }, + args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 5})}}, + wantErr: true, + }, + { + name: "pod with too high version label", + fields: fields{ + lowestSupportedVersion: version.Version{Major: 6}, + highestSupportedVersion: version.Version{Major: 7}, + }, + args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 8})}}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + lh := esversion.LowestHighestSupportedVersions{ + LowestSupportedVersion: tt.fields.lowestSupportedVersion, + HighestSupportedVersion: tt.fields.highestSupportedVersion, + } + d := defaultDriver{ + DefaultDriverParameters{ + SupportedVersions: lh, + }, + } + if err := d.verifySupportsExistingPods(tt.args.pods); (err != nil) != tt.wantErr { + t.Errorf("verifySupportsExistingPods() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCurrentVersions(t *testing.T) { + tests := []struct { + name string + args []corev1.Pod + want *version.Version + wantErr bool + }{ + { + name: "no pods", + args: nil, + want: nil, + wantErr: false, + }, + { + name: "no versions in pods", + args: []corev1.Pod{ + {}, + }, + want: nil, + wantErr: true, + }, + { + name: "one pod", + args: []corev1.Pod{ + { + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + label.VersionLabelName: "1.0.0", + }, + }, + }, + }, + want: &version.Version{ + Major: 1, + Minor: 0, + Patch: 0, + Label: "", + }, + wantErr: false, + }, + { + name: "n pods", + args: []corev1.Pod{ + { + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + label.VersionLabelName: "2.0.0", + }, + }, + }, + { + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + label.VersionLabelName: "1.0.0", + }, + }, + }, + }, + want: &version.Version{ + Major: 1, + Minor: 0, + Patch: 0, + Label: "", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := minVersion(tt.args) + if (err != nil) != tt.wantErr { + t.Errorf("minVersion() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("minVersion() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/controller/elasticsearch/elasticsearch_controller.go b/pkg/controller/elasticsearch/elasticsearch_controller.go index 489002ee51..0ef31229cd 100644 --- a/pkg/controller/elasticsearch/elasticsearch_controller.go +++ b/pkg/controller/elasticsearch/elasticsearch_controller.go @@ -22,10 +22,8 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/watches" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/driver" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/observer" esreconcile "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/reconcile" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/validation" esversion "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/version" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" @@ -246,19 +244,16 @@ func (r *ReconcileElasticsearch) internalReconcile( return results } - violations, err := validation.Validate(es) + // this is the same validation as the webhook, but we run it again here in case the webhook has not been configured + err := es.ValidateCreate() if err != nil { - return results.WithError(err) - } - if len(violations) > 0 { log.Error( - fmt.Errorf("manifest validation failed"), + err, "Elasticsearch manifest validation failed", "namespace", es.Namespace, "es_name", es.Name, - "violations", violations, ) - reconcileState.UpdateElasticsearchInvalid(violations) + reconcileState.UpdateElasticsearchInvalid(err) return results } @@ -310,6 +305,6 @@ func (r *ReconcileElasticsearch) finalizersFor( return []finalizer.Finalizer{ r.esObservers.Finalizer(clusterName), keystore.Finalizer(k8s.ExtractNamespacedName(&es), r.dynamicWatches, es.Kind), - http.DynamicWatchesFinalizer(r.dynamicWatches, es.Kind, es.Name, esname.ESNamer), + http.DynamicWatchesFinalizer(r.dynamicWatches, es.Kind, es.Name, elasticsearchv1beta1.ESNamer), } } diff --git a/pkg/controller/elasticsearch/initcontainer/prepare_fs.go b/pkg/controller/elasticsearch/initcontainer/prepare_fs.go index c92a272237..6eca2f9b8c 100644 --- a/pkg/controller/elasticsearch/initcontainer/prepare_fs.go +++ b/pkg/controller/elasticsearch/initcontainer/prepare_fs.go @@ -7,9 +7,9 @@ package initcontainer import ( "path" + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/user" esvolume "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/volume" @@ -95,7 +95,7 @@ func NewPrepareFSInitContainer( certificatesVolumeMount.MountPath = initContainerTransportCertificatesVolumeMountPath scriptsVolume := volume.NewConfigMapVolumeWithMode( - name.ScriptsConfigMap(clusterName), + v1beta1.ScriptsConfigMap(clusterName), esvolume.ScriptsVolumeName, esvolume.ScriptsVolumeMountPath, 0755) diff --git a/pkg/controller/elasticsearch/license/apply.go b/pkg/controller/elasticsearch/license/apply.go index 2a3df49faf..4eeabc97f8 100644 --- a/pkg/controller/elasticsearch/license/apply.go +++ b/pkg/controller/elasticsearch/license/apply.go @@ -9,9 +9,9 @@ import ( "encoding/json" "fmt" + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" common_license "github.com/elastic/cloud-on-k8s/pkg/controller/common/license" esclient "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" pkgerrors "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" @@ -32,7 +32,7 @@ func applyLinkedLicense( err := c.Get( types.NamespacedName{ Namespace: esCluster.Namespace, - Name: name.LicenseSecretName(esCluster.Name), + Name: v1beta1.LicenseSecretName(esCluster.Name), }, &license, ) diff --git a/pkg/controller/elasticsearch/license/apply_test.go b/pkg/controller/elasticsearch/license/apply_test.go index 117063e367..740a1e97d5 100644 --- a/pkg/controller/elasticsearch/license/apply_test.go +++ b/pkg/controller/elasticsearch/license/apply_test.go @@ -8,10 +8,10 @@ import ( "net/http" "testing" + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" esclient "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" fixtures "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client/test_fixtures" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/pkg/errors" "github.com/stretchr/testify/require" @@ -116,7 +116,7 @@ func Test_applyLinkedLicense(t *testing.T) { initialObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: name.LicenseSecretName("test"), + Name: v1beta1.LicenseSecretName("test"), Namespace: "default", }, Data: map[string][]byte{ @@ -135,7 +135,7 @@ func Test_applyLinkedLicense(t *testing.T) { initialObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: name.LicenseSecretName("test"), + Name: v1beta1.LicenseSecretName("test"), Namespace: "default", }, }, @@ -147,7 +147,7 @@ func Test_applyLinkedLicense(t *testing.T) { initialObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: name.LicenseSecretName("test"), + Name: v1beta1.LicenseSecretName("test"), Namespace: "default", }, Data: map[string][]byte{ @@ -162,7 +162,7 @@ func Test_applyLinkedLicense(t *testing.T) { errors: map[client.ObjectKey]error{ types.NamespacedName{ Namespace: clusterName.Namespace, - Name: name.LicenseSecretName("test"), + Name: v1beta1.LicenseSecretName("test"), }: errors.New("boom"), }, }, diff --git a/pkg/controller/elasticsearch/nodespec/podspec.go b/pkg/controller/elasticsearch/nodespec/podspec.go index 887458f53d..10c1c54a0b 100644 --- a/pkg/controller/elasticsearch/nodespec/podspec.go +++ b/pkg/controller/elasticsearch/nodespec/podspec.go @@ -18,7 +18,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/initcontainer" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" esvolume "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/volume" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" @@ -69,7 +68,7 @@ func BuildPodTemplateSpec( func transportCertificatesVolume(esName string) volume.SecretVolume { return volume.NewSecretVolumeWithMountPath( - name.TransportCertificatesSecret(esName), + v1beta1.TransportCertificatesSecret(esName), esvolume.TransportCertificatesSecretVolumeName, esvolume.TransportCertificatesSecretVolumeMountPath, ) @@ -97,7 +96,7 @@ func buildLabels( podLabels, err := label.NewPodLabels( k8s.ExtractNamespacedName(&es), - name.StatefulSet(es.Name, nodeSet.Name), + v1beta1.StatefulSet(es.Name, nodeSet.Name), *ver, nodeRoles, cfgHash, es.Spec.HTTP.Scheme(), ) if err != nil { diff --git a/pkg/controller/elasticsearch/nodespec/statefulset.go b/pkg/controller/elasticsearch/nodespec/statefulset.go index 9963041759..6659766e95 100644 --- a/pkg/controller/elasticsearch/nodespec/statefulset.go +++ b/pkg/controller/elasticsearch/nodespec/statefulset.go @@ -12,7 +12,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" "github.com/elastic/cloud-on-k8s/pkg/controller/common/keystore" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" esvolume "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/volume" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" @@ -56,7 +55,7 @@ func BuildStatefulSet( keystoreResources *keystore.Resources, scheme *runtime.Scheme, ) (appsv1.StatefulSet, error) { - statefulSetName := name.StatefulSet(es.Name, nodeSet.Name) + statefulSetName := v1beta1.StatefulSet(es.Name, nodeSet.Name) // ssetSelector is used to match the sset pods ssetSelector := label.NewStatefulSetLabels(k8s.ExtractNamespacedName(&es), statefulSetName) diff --git a/pkg/controller/elasticsearch/nodespec/volumes.go b/pkg/controller/elasticsearch/nodespec/volumes.go index df062c0c66..ffe458ea8a 100644 --- a/pkg/controller/elasticsearch/nodespec/volumes.go +++ b/pkg/controller/elasticsearch/nodespec/volumes.go @@ -12,7 +12,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/keystore" "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/initcontainer" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/user" esvolume "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/volume" @@ -20,19 +19,19 @@ import ( func buildVolumes(esName string, nodeSpec v1beta1.NodeSet, keystoreResources *keystore.Resources) ([]corev1.Volume, []corev1.VolumeMount) { - configVolume := settings.ConfigSecretVolume(name.StatefulSet(esName, nodeSpec.Name)) + configVolume := settings.ConfigSecretVolume(v1beta1.StatefulSet(esName, nodeSpec.Name)) probeSecret := volume.NewSelectiveSecretVolumeWithMountPath( user.ElasticInternalUsersSecretName(esName), esvolume.ProbeUserVolumeName, esvolume.ProbeUserSecretMountPath, []string{user.InternalProbeUserName}, ) httpCertificatesVolume := volume.NewSecretVolumeWithMountPath( - certificates.HTTPCertsInternalSecretName(name.ESNamer, esName), + certificates.HTTPCertsInternalSecretName(v1beta1.ESNamer, esName), esvolume.HTTPCertificatesSecretVolumeName, esvolume.HTTPCertificatesSecretVolumeMountPath, ) transportCertificatesVolume := transportCertificatesVolume(esName) unicastHostsVolume := volume.NewConfigMapVolume( - name.UnicastHostsConfigMap(esName), esvolume.UnicastHostsVolumeName, esvolume.UnicastHostsVolumeMountPath, + v1beta1.UnicastHostsConfigMap(esName), esvolume.UnicastHostsVolumeName, esvolume.UnicastHostsVolumeMountPath, ) usersSecretVolume := volume.NewSecretVolumeWithMountPath( user.XPackFileRealmSecretName(esName), @@ -40,7 +39,7 @@ func buildVolumes(esName string, nodeSpec v1beta1.NodeSet, keystoreResources *ke esvolume.XPackFileRealmVolumeMountPath, ) scriptsVolume := volume.NewConfigMapVolumeWithMode( - name.ScriptsConfigMap(esName), + v1beta1.ScriptsConfigMap(esName), esvolume.ScriptsVolumeName, esvolume.ScriptsVolumeMountPath, 0755) diff --git a/pkg/controller/elasticsearch/pdb/reconcile.go b/pkg/controller/elasticsearch/pdb/reconcile.go index 017f2e672b..509623ff26 100644 --- a/pkg/controller/elasticsearch/pdb/reconcile.go +++ b/pkg/controller/elasticsearch/pdb/reconcile.go @@ -10,7 +10,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/sset" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "k8s.io/api/policy/v1beta1" @@ -65,7 +64,7 @@ func deleteDefaultPDB(k8sClient k8s.Client, es esv1beta1.Elasticsearch) error { pdb := v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Namespace: es.Namespace, - Name: name.DefaultPodDisruptionBudget(es.Name), + Name: esv1beta1.DefaultPodDisruptionBudget(es.Name), }, } if err := k8sClient.Get(k8s.ExtractNamespacedName(&pdb), &pdb); err != nil && !errors.IsNotFound(err) { @@ -96,7 +95,7 @@ func expectedPDB(es esv1beta1.Elasticsearch, statefulSets sset.StatefulSetList, } // inherit user-provided ObjectMeta, but set our own name & namespace - expected.Name = name.DefaultPodDisruptionBudget(es.Name) + expected.Name = esv1beta1.DefaultPodDisruptionBudget(es.Name) expected.Namespace = es.Namespace // and append our labels expected.Labels = defaults.SetDefaultLabels(expected.Labels, label.NewLabels(k8s.ExtractNamespacedName(&es))) diff --git a/pkg/controller/elasticsearch/pdb/reconcile_test.go b/pkg/controller/elasticsearch/pdb/reconcile_test.go index d2d86356b2..1fbadaa98e 100644 --- a/pkg/controller/elasticsearch/pdb/reconcile_test.go +++ b/pkg/controller/elasticsearch/pdb/reconcile_test.go @@ -13,7 +13,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common" "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/sset" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/stretchr/testify/require" @@ -30,7 +29,7 @@ func TestReconcile(t *testing.T) { defaultPDB := func() *v1beta1.PodDisruptionBudget { return &v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: name.DefaultPodDisruptionBudget("cluster"), + Name: esv1beta1.DefaultPodDisruptionBudget("cluster"), Namespace: "ns", Labels: map[string]string{label.ClusterNameLabelName: "cluster", common.TypeLabelName: label.Type}, }, @@ -83,7 +82,7 @@ func TestReconcile(t *testing.T) { }, wantPDB: &v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: name.DefaultPodDisruptionBudget("cluster"), + Name: esv1beta1.DefaultPodDisruptionBudget("cluster"), Namespace: "ns", Labels: map[string]string{label.ClusterNameLabelName: "cluster", common.TypeLabelName: label.Type}, }, @@ -115,7 +114,7 @@ func TestReconcile(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := Reconcile(tt.args.k8sClient, scheme.Scheme, tt.args.es, tt.args.statefulSets) require.NoError(t, err) - pdbNsn := types.NamespacedName{Namespace: tt.args.es.Namespace, Name: name.DefaultPodDisruptionBudget(tt.args.es.Name)} + pdbNsn := types.NamespacedName{Namespace: tt.args.es.Namespace, Name: esv1beta1.DefaultPodDisruptionBudget(tt.args.es.Name)} var retrieved v1beta1.PodDisruptionBudget err = tt.args.k8sClient.Get(pdbNsn, &retrieved) if tt.wantPDB == nil { @@ -172,7 +171,7 @@ func Test_expectedPDB(t *testing.T) { }, want: &v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: name.DefaultPodDisruptionBudget("cluster"), + Name: esv1beta1.DefaultPodDisruptionBudget("cluster"), Namespace: "ns", Labels: map[string]string{label.ClusterNameLabelName: "cluster", common.TypeLabelName: label.Type}, }, @@ -203,7 +202,7 @@ func Test_expectedPDB(t *testing.T) { }, want: &v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: name.DefaultPodDisruptionBudget("cluster"), + Name: esv1beta1.DefaultPodDisruptionBudget("cluster"), Namespace: "ns", Labels: map[string]string{"a": "b", "c": "d", label.ClusterNameLabelName: "cluster", common.TypeLabelName: label.Type}, }, @@ -232,7 +231,7 @@ func Test_expectedPDB(t *testing.T) { }, want: &v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: name.DefaultPodDisruptionBudget("cluster"), + Name: esv1beta1.DefaultPodDisruptionBudget("cluster"), Namespace: "ns", Labels: map[string]string{label.ClusterNameLabelName: "cluster", common.TypeLabelName: label.Type}, }, diff --git a/pkg/controller/elasticsearch/reconcile/state.go b/pkg/controller/elasticsearch/reconcile/state.go index 0e38e7ddf5..720234e1e3 100644 --- a/pkg/controller/elasticsearch/reconcile/state.go +++ b/pkg/controller/elasticsearch/reconcile/state.go @@ -9,7 +9,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/events" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/validation" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/observer" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" @@ -112,9 +111,7 @@ func (s *State) Apply() ([]events.Event, *v1beta1.Elasticsearch) { return s.Events(), &s.cluster } -func (s *State) UpdateElasticsearchInvalid(results []validation.Result) { +func (s *State) UpdateElasticsearchInvalid(err error) { s.status.Phase = v1beta1.ElasticsearchResourceInvalid - for _, r := range results { - s.AddEvent(corev1.EventTypeWarning, events.EventReasonValidation, r.Reason) - } + s.AddEvent(corev1.EventTypeWarning, events.EventReasonValidation, err.Error()) } diff --git a/pkg/controller/elasticsearch/services/services.go b/pkg/controller/elasticsearch/services/services.go index ae9f3da10f..23262fda83 100644 --- a/pkg/controller/elasticsearch/services/services.go +++ b/pkg/controller/elasticsearch/services/services.go @@ -15,7 +15,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/network" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/elastic/cloud-on-k8s/pkg/utils/stringsutil" @@ -28,7 +27,7 @@ const ( // ExternalServiceName returns the name for the external service // associated to this cluster func ExternalServiceName(esName string) string { - return name.HTTPService(esName) + return v1beta1.HTTPService(esName) } // ExternalServiceURL returns the URL used to reach Elasticsearch's external endpoint diff --git a/pkg/controller/elasticsearch/settings/config_volume.go b/pkg/controller/elasticsearch/settings/config_volume.go index 132fa896c8..2ae5291d04 100644 --- a/pkg/controller/elasticsearch/settings/config_volume.go +++ b/pkg/controller/elasticsearch/settings/config_volume.go @@ -18,7 +18,6 @@ import ( common "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" ) @@ -31,7 +30,7 @@ const ( // ConfigSecretName is the name of the secret that holds the ES config for the given StatefulSet. func ConfigSecretName(ssetName string) string { - return name.ConfigSecret(ssetName) + return v1beta1.ConfigSecret(ssetName) } // ConfigSecretVolume returns a SecretVolume to hold the config of nodes in the given stateful set.. diff --git a/pkg/controller/elasticsearch/settings/masters.go b/pkg/controller/elasticsearch/settings/masters.go index 087f0b5389..dc47191c68 100644 --- a/pkg/controller/elasticsearch/settings/masters.go +++ b/pkg/controller/elasticsearch/settings/masters.go @@ -13,7 +13,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/annotation" "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/network" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/volume" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" @@ -64,7 +63,7 @@ func UpdateSeedHostsConfigMap( } expected := corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: name.UnicastHostsConfigMap(es.Name), + Name: v1beta1.UnicastHostsConfigMap(es.Name), Namespace: es.Namespace, Labels: label.NewLabels(k8s.ExtractNamespacedName(&es)), }, diff --git a/pkg/controller/elasticsearch/settings/masters_test.go b/pkg/controller/elasticsearch/settings/masters_test.go index 10143fc242..f6fdf665f0 100644 --- a/pkg/controller/elasticsearch/settings/masters_test.go +++ b/pkg/controller/elasticsearch/settings/masters_test.go @@ -9,7 +9,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/volume" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/stretchr/testify/assert" @@ -136,7 +135,7 @@ func TestUpdateSeedHostsConfigMap(t *testing.T) { if err := tt.args.c.Get( types.NamespacedName{ Namespace: "ns1", - Name: name.UnicastHostsConfigMap(es.Name), + Name: v1beta1.UnicastHostsConfigMap(es.Name), }, file); err != nil { t.Errorf("Error while getting the seed hosts configmap: %v", err) } diff --git a/pkg/controller/elasticsearch/settings/merged_config.go b/pkg/controller/elasticsearch/settings/merged_config.go index e397929a56..deee391520 100644 --- a/pkg/controller/elasticsearch/settings/merged_config.go +++ b/pkg/controller/elasticsearch/settings/merged_config.go @@ -7,7 +7,8 @@ package settings import ( "path" - "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" + commonv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" + estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" common "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" @@ -20,8 +21,8 @@ import ( func NewMergedESConfig( clusterName string, ver version.Version, - httpConfig v1beta1.HTTPConfig, - userConfig v1beta1.Config, + httpConfig commonv1beta1.HTTPConfig, + userConfig commonv1beta1.Config, certResources *escerts.CertificateResources, ) (CanonicalConfig, error) { config, err := common.NewCanonicalConfigFrom(userConfig.Data) @@ -42,74 +43,74 @@ func NewMergedESConfig( func baseConfig(clusterName string, ver version.Version) *CanonicalConfig { cfg := map[string]interface{}{ // derive node name dynamically from the pod name, injected as env var - NodeName: "${" + EnvPodName + "}", - ClusterName: clusterName, + estype.NodeName: "${" + EnvPodName + "}", + estype.ClusterName: clusterName, // derive IP dynamically from the pod IP, injected as env var - NetworkPublishHost: "${" + EnvPodIP + "}", - NetworkHost: "0.0.0.0", + estype.NetworkPublishHost: "${" + EnvPodIP + "}", + estype.NetworkHost: "0.0.0.0", - PathData: volume.ElasticsearchDataMountPath, - PathLogs: volume.ElasticsearchLogsMountPath, + estype.PathData: volume.ElasticsearchDataMountPath, + estype.PathLogs: volume.ElasticsearchLogsMountPath, } // seed hosts setting name changed starting ES 7.X fileProvider := "file" if ver.Major < 7 { - cfg[DiscoveryZenHostsProvider] = fileProvider + cfg[estype.DiscoveryZenHostsProvider] = fileProvider } else { - cfg[DiscoverySeedProviders] = fileProvider + cfg[estype.DiscoverySeedProviders] = fileProvider } return &CanonicalConfig{common.MustCanonicalConfig(cfg)} } // xpackConfig returns the configuration bit related to XPack settings -func xpackConfig(ver version.Version, httpCfg v1beta1.HTTPConfig, certResources *escerts.CertificateResources) *CanonicalConfig { +func xpackConfig(ver version.Version, httpCfg commonv1beta1.HTTPConfig, certResources *escerts.CertificateResources) *CanonicalConfig { // enable x-pack security, including TLS cfg := map[string]interface{}{ // x-pack security general settings - XPackSecurityEnabled: "true", - XPackSecurityAuthcReservedRealmEnabled: "false", - XPackSecurityTransportSslVerificationMode: "certificate", + estype.XPackSecurityEnabled: "true", + estype.XPackSecurityAuthcReservedRealmEnabled: "false", + estype.XPackSecurityTransportSslVerificationMode: "certificate", // x-pack security http settings - XPackSecurityHttpSslEnabled: httpCfg.TLS.Enabled(), - XPackSecurityHttpSslKey: path.Join(volume.HTTPCertificatesSecretVolumeMountPath, certificates.KeyFileName), - XPackSecurityHttpSslCertificate: path.Join(volume.HTTPCertificatesSecretVolumeMountPath, certificates.CertFileName), + estype.XPackSecurityHttpSslEnabled: httpCfg.TLS.Enabled(), + estype.XPackSecurityHttpSslKey: path.Join(volume.HTTPCertificatesSecretVolumeMountPath, certificates.KeyFileName), + estype.XPackSecurityHttpSslCertificate: path.Join(volume.HTTPCertificatesSecretVolumeMountPath, certificates.CertFileName), // x-pack security transport settings - XPackSecurityTransportSslEnabled: "true", - XPackSecurityTransportSslKey: path.Join( + estype.XPackSecurityTransportSslEnabled: "true", + estype.XPackSecurityTransportSslKey: path.Join( volume.ConfigVolumeMountPath, volume.NodeTransportCertificatePathSegment, volume.NodeTransportCertificateKeyFile, ), - XPackSecurityTransportSslCertificate: path.Join( + estype.XPackSecurityTransportSslCertificate: path.Join( volume.ConfigVolumeMountPath, volume.NodeTransportCertificatePathSegment, volume.NodeTransportCertificateCertFile, ), - XPackSecurityTransportSslCertificateAuthorities: []string{ + estype.XPackSecurityTransportSslCertificateAuthorities: []string{ path.Join(volume.TransportCertificatesSecretVolumeMountPath, certificates.CAFileName), }, } if certResources.HTTPCACertProvided { - cfg[XPackSecurityHttpSslCertificateAuthorities] = path.Join(volume.HTTPCertificatesSecretVolumeMountPath, certificates.CAFileName) + cfg[estype.XPackSecurityHttpSslCertificateAuthorities] = path.Join(volume.HTTPCertificatesSecretVolumeMountPath, certificates.CAFileName) } // always enable the built-in file and native internal realms for user auth, ordered as first if ver.Major < 7 { // 6.x syntax - cfg[XPackSecurityAuthcRealmsFile1Type] = "file" - cfg[XPackSecurityAuthcRealmsFile1Order] = -100 - cfg[XPackSecurityAuthcRealmsNative1Type] = "native" - cfg[XPackSecurityAuthcRealmsNative1Order] = -99 + cfg[estype.XPackSecurityAuthcRealmsFile1Type] = "file" + cfg[estype.XPackSecurityAuthcRealmsFile1Order] = -100 + cfg[estype.XPackSecurityAuthcRealmsNative1Type] = "native" + cfg[estype.XPackSecurityAuthcRealmsNative1Order] = -99 } else { // 7.x syntax - cfg[XPackSecurityAuthcRealmsFileFile1Order] = -100 - cfg[XPackSecurityAuthcRealmsNativeNative1Order] = -99 + cfg[estype.XPackSecurityAuthcRealmsFileFile1Order] = -100 + cfg[estype.XPackSecurityAuthcRealmsNativeNative1Order] = -99 } return &CanonicalConfig{common.MustCanonicalConfig(cfg)} diff --git a/pkg/controller/elasticsearch/settings/merged_config_test.go b/pkg/controller/elasticsearch/settings/merged_config_test.go index 4af3e7d3c8..13e3b2b17b 100644 --- a/pkg/controller/elasticsearch/settings/merged_config_test.go +++ b/pkg/controller/elasticsearch/settings/merged_config_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" + estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/certificates" "github.com/stretchr/testify/require" @@ -31,10 +32,10 @@ func TestNewMergedESConfig(t *testing.T) { cfgData: map[string]interface{}{}, assert: func(cfg CanonicalConfig) { require.Equal(t, 0, len(cfg.HasKeys([]string{nodeML}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFile1Type}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFile1Order}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNative1Type}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNative1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFile1Type}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFile1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNative1Type}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNative1Order}))) }, }, { @@ -45,10 +46,10 @@ func TestNewMergedESConfig(t *testing.T) { }, assert: func(cfg CanonicalConfig) { require.Equal(t, 1, len(cfg.HasKeys([]string{nodeML}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFile1Type}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFile1Order}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNative1Type}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNative1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFile1Type}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFile1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNative1Type}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNative1Order}))) }, }, { @@ -61,10 +62,10 @@ func TestNewMergedESConfig(t *testing.T) { }, assert: func(cfg CanonicalConfig) { require.Equal(t, 1, len(cfg.HasKeys([]string{nodeML}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFile1Type}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFile1Order}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNative1Type}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNative1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFile1Type}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFile1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNative1Type}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNative1Order}))) require.Equal(t, 1, len(cfg.HasKeys([]string{xPackSecurityAuthcRealmsAD1Type}))) require.Equal(t, 1, len(cfg.HasKeys([]string{xPackSecurityAuthcRealmsAD1Order}))) }, @@ -75,8 +76,8 @@ func TestNewMergedESConfig(t *testing.T) { cfgData: map[string]interface{}{}, assert: func(cfg CanonicalConfig) { require.Equal(t, 0, len(cfg.HasKeys([]string{nodeML}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFileFile1Order}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNativeNative1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFileFile1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNativeNative1Order}))) }, }, { @@ -87,8 +88,8 @@ func TestNewMergedESConfig(t *testing.T) { }, assert: func(cfg CanonicalConfig) { require.Equal(t, 1, len(cfg.HasKeys([]string{nodeML}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFileFile1Order}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNativeNative1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFileFile1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNativeNative1Order}))) }, }, { @@ -100,8 +101,8 @@ func TestNewMergedESConfig(t *testing.T) { }, assert: func(cfg CanonicalConfig) { require.Equal(t, 1, len(cfg.HasKeys([]string{nodeML}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsFileFile1Order}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{XPackSecurityAuthcRealmsNativeNative1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsFileFile1Order}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.XPackSecurityAuthcRealmsNativeNative1Order}))) require.Equal(t, 1, len(cfg.HasKeys([]string{xPackSecurityAuthcRealmsActiveDirectoryAD1Order}))) }, }, @@ -110,8 +111,8 @@ func TestNewMergedESConfig(t *testing.T) { version: "6.8.0", cfgData: map[string]interface{}{}, assert: func(cfg CanonicalConfig) { - require.Equal(t, 1, len(cfg.HasKeys([]string{DiscoveryZenHostsProvider}))) - require.Equal(t, 0, len(cfg.HasKeys([]string{DiscoverySeedProviders}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.DiscoveryZenHostsProvider}))) + require.Equal(t, 0, len(cfg.HasKeys([]string{estype.DiscoverySeedProviders}))) }, }, { @@ -119,8 +120,8 @@ func TestNewMergedESConfig(t *testing.T) { version: "7.0.0", cfgData: map[string]interface{}{}, assert: func(cfg CanonicalConfig) { - require.Equal(t, 0, len(cfg.HasKeys([]string{DiscoveryZenHostsProvider}))) - require.Equal(t, 1, len(cfg.HasKeys([]string{DiscoverySeedProviders}))) + require.Equal(t, 0, len(cfg.HasKeys([]string{estype.DiscoveryZenHostsProvider}))) + require.Equal(t, 1, len(cfg.HasKeys([]string{estype.DiscoverySeedProviders}))) }, }, } diff --git a/pkg/controller/elasticsearch/user/credentials.go b/pkg/controller/elasticsearch/user/credentials.go index 289c1d1744..55d1262631 100644 --- a/pkg/controller/elasticsearch/user/credentials.go +++ b/pkg/controller/elasticsearch/user/credentials.go @@ -10,10 +10,10 @@ import ( "sort" "strings" + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" common "github.com/elastic/cloud-on-k8s/pkg/controller/common/user" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/ghodss/yaml" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,17 +31,17 @@ const ( // XPackFileRealmSecretName is the name of the secret containing all users and roles information in ES format. func XPackFileRealmSecretName(ownerName string) string { - return name.XPackFileRealmSecret(ownerName) + return v1beta1.XPackFileRealmSecret(ownerName) } // ElasticInternalUsersSecretName is the name of the secret containing the internal users' credentials. func ElasticInternalUsersSecretName(ownerName string) string { - return name.InternalUsersSecret(ownerName) + return v1beta1.InternalUsersSecret(ownerName) } // ElasticExternalUsersSecretName is the name of the secret containing the external users' credentials. func ElasticExternalUsersSecretName(ownerName string) string { - return name.ElasticUserSecret(ownerName) + return v1beta1.ElasticUserSecret(ownerName) } // UserCredentials captures Elasticsearch user credentials and their representation in a k8s secret. diff --git a/pkg/controller/elasticsearch/validation/upgrade_checks.go b/pkg/controller/elasticsearch/validation/upgrade_checks.go deleted file mode 100644 index 0f880772e5..0000000000 --- a/pkg/controller/elasticsearch/validation/upgrade_checks.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package validation - -import ( - "fmt" - - "github.com/elastic/cloud-on-k8s/pkg/controller/common/validation" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - esversion "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/version" -) - -const ( - noDowngradesMsg = "Downgrades are not supported" -) - -func unsupportedVersion(v *version.Version) string { - return fmt.Sprintf("unsupported version: %v", v) -} - -func unsupportedUpgradePath(v1, v2 version.Version) string { - return fmt.Sprintf("unsupported version upgrade from %v to %v", v1, v2) -} - -func noDowngrades(ctx Context) validation.Result { - if ctx.isCreate() { - return validation.OK - } - if !ctx.Proposed.Version.IsSameOrAfter(ctx.Current.Version) { - return validation.Result{Allowed: false, Reason: noDowngradesMsg} - } - return validation.OK -} - -func validUpgradePath(ctx Context) validation.Result { - if ctx.isCreate() { - return validation.OK - } - - v := esversion.SupportedVersions(ctx.Proposed.Version) - if v == nil { - return validation.Result{Allowed: false, Reason: unsupportedVersion(&ctx.Proposed.Version)} - } - err := v.Supports(ctx.Current.Version) - if err != nil { - return validation.Result{ - Allowed: false, - Reason: unsupportedUpgradePath(ctx.Current.Version, ctx.Proposed.Version), - } - } - return validation.OK -} - -func invalidName(err error) string { - return fmt.Sprintf("%s: %v", invalidNamesErrMsg, err) -} diff --git a/pkg/controller/elasticsearch/validation/upgrade_checks_test.go b/pkg/controller/elasticsearch/validation/upgrade_checks_test.go deleted file mode 100644 index 0e2bdc0aea..0000000000 --- a/pkg/controller/elasticsearch/validation/upgrade_checks_test.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package validation - -import ( - "reflect" - "testing" - - estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/validation" - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func es(v string) *estype.Elasticsearch { - return &estype.Elasticsearch{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "foo", - }, - Spec: estype.ElasticsearchSpec{Version: v}, - } -} - -func TestValidation_noDowngrades(t *testing.T) { - type args struct { - toValidate estype.Elasticsearch - } - tests := []struct { - name string - args args - current *estype.Elasticsearch - want validation.Result - wantErr bool - }{ - { - name: "no validation on create", - args: args{ - toValidate: *es("6.8.0"), - }, - current: nil, - want: validation.OK, - }, - { - name: "prevent downgrade", - args: args{ - toValidate: *es("1.0.0"), - }, - current: es("2.0.0"), - want: validation.Result{Allowed: false, Reason: noDowngradesMsg}, - }, - { - name: "allow upgrades", - args: args{ - toValidate: *es("1.2.0"), - }, - current: es("1.0.0"), - want: validation.OK, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(tt.current, tt.args.toValidate) - require.NoError(t, err) - got := noDowngrades(*ctx) - if got.Allowed != tt.want.Allowed || got.Reason != tt.want.Reason || got.Error != nil != tt.wantErr { - t.Errorf("ValidationHandler.noDowngrades() = %+v, want %+v", got, tt.want) - } - }) - } -} - -func Test_validUpgradePath(t *testing.T) { - type args struct { - current *estype.Elasticsearch - proposed estype.Elasticsearch - } - tests := []struct { - name string - args args - want validation.Result - }{ - { - name: "new cluster validation.OK", - args: args{ - current: nil, - proposed: *es("1.0.0"), - }, - want: validation.OK, - }, - { - name: "unsupported version FAIL", - args: args{ - current: es("1.0.0"), - proposed: *es("2.0.0"), - }, - want: validation.Result{Allowed: false, Reason: "unsupported version: 2.0.0"}, - }, - { - name: "too old FAIL", - args: args{ - current: es("6.5.0"), - proposed: *es("7.0.0"), - }, - want: validation.Result{Allowed: false, Reason: "unsupported version upgrade from 6.5.0 to 7.0.0"}, - }, - { - name: "too new FAIL", - args: args{ - current: es("7.0.0"), - proposed: *es("6.5.0"), - }, - want: validation.Result{Allowed: false, Reason: "unsupported version upgrade from 7.0.0 to 6.5.0"}, - }, - { - name: "in range validation.OK", - args: args{ - current: es("6.8.0"), - proposed: *es("7.1.0"), - }, - want: validation.OK, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(tt.args.current, tt.args.proposed) - require.NoError(t, err) - if got := validUpgradePath(*ctx); !reflect.DeepEqual(got, tt.want) { - t.Errorf("validUpgradePath() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/controller/elasticsearch/validation/validation.go b/pkg/controller/elasticsearch/validation/validation.go deleted file mode 100644 index 6c4013c05f..0000000000 --- a/pkg/controller/elasticsearch/validation/validation.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package validation - -import ( - estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/validation" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - pkgerrors "github.com/pkg/errors" -) - -const ( - cfgInvalidMsg = "configuration invalid" - validationFailedMsg = "Spec validation failed" - masterRequiredMsg = "Elasticsearch needs to have at least one master node" - parseVersionErrMsg = "Cannot parse Elasticsearch version" - parseStoredVersionErrMsg = "Cannot parse current Elasticsearch version" - invalidSanIPErrMsg = "invalid SAN IP address" - pvcImmutableMsg = "Volume claim templates cannot be modified" - invalidNamesErrMsg = "Elasticsearch configuration would generate resources with invalid names" -) - -// Validation is a function from a currently stored Elasticsearch spec and proposed new spec -// (both inside a Context struct) to a validation.Result. -type Validation func(ctx Context) validation.Result - -// ElasticsearchVersion groups an ES resource and its parsed version. -type ElasticsearchVersion struct { - Elasticsearch estype.Elasticsearch - Version version.Version -} - -// Context is structured input for validation functions. -type Context struct { - // Current is the Elasticsearch spec/version currently stored in the api server. Can be nil on new clusters. - Current *ElasticsearchVersion - // Proposed is the Elasticsearch spec/version submitted for validation. - Proposed ElasticsearchVersion -} - -// NewValidationContext constructs a new Context. -func NewValidationContext(current *estype.Elasticsearch, proposed estype.Elasticsearch) (*Context, error) { - proposedVersion, err := version.Parse(proposed.Spec.Version) - if err != nil { - return nil, pkgerrors.Wrap(err, parseVersionErrMsg) - } - ctx := Context{ - Proposed: ElasticsearchVersion{ - Elasticsearch: proposed, - Version: *proposedVersion, - }, - } - if current != nil { - currentVersion, err := version.Parse(current.Spec.Version) - if err != nil { - return nil, pkgerrors.Wrap(err, parseStoredVersionErrMsg) - } - ctx.Current = &ElasticsearchVersion{ - Elasticsearch: *current, - Version: *currentVersion, - } - } - return &ctx, nil -} - -func (v Context) isCreate() bool { - return v.Current == nil -} - -// Validate runs validation logic in contexts where we don't have current and proposed Elasticsearch versions. -func Validate(es estype.Elasticsearch) ([]validation.Result, error) { - v, err := version.Parse(es.Spec.Version) - if err != nil { - return nil, err - } - - vCtx := Context{ - Current: nil, - Proposed: ElasticsearchVersion{ - Elasticsearch: es, - Version: *v, - }, - } - var errs []validation.Result - for _, v := range Validations { - r := v(vCtx) - if r.Allowed { - continue - } - errs = append(errs, r) - } - return errs, nil -} diff --git a/pkg/controller/elasticsearch/validation/validation_test.go b/pkg/controller/elasticsearch/validation/validation_test.go deleted file mode 100644 index 486b47cbf3..0000000000 --- a/pkg/controller/elasticsearch/validation/validation_test.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package validation - -import ( - "reflect" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - common "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" - estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" -) - -func TestNewValidationContext(t *testing.T) { - type args struct { - current *estype.Elasticsearch - proposed estype.Elasticsearch - } - tests := []struct { - name string - args args - want *Context - wantErr bool - }{ - { - name: "garbage version FAIL", - args: args{ - current: nil, - proposed: *es("garbage"), - }, - wantErr: true, - }, - { - name: "current version garbage SHOULD NEVER HAPPEN", - args: args{ - current: es("garbage"), - proposed: *es("6.0.0"), - }, - wantErr: true, - }, - { - name: "create current is nil OK", - args: args{ - current: nil, - proposed: *es("7.0.0"), - }, - want: &Context{ - Proposed: ElasticsearchVersion{ - Elasticsearch: *es("7.0.0"), - Version: version.MustParse("7.0.0"), - }, - }, - wantErr: false, - }, - { - name: "update both OK", - args: args{ - current: es("6.5.0"), - proposed: *es("7.0.0"), - }, - want: &Context{ - Current: &ElasticsearchVersion{ - Elasticsearch: *es("6.5.0"), - Version: version.MustParse("6.5.0"), - }, - Proposed: ElasticsearchVersion{ - Elasticsearch: *es("7.0.0"), - Version: version.MustParse("7.0.0"), - }, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := NewValidationContext(tt.args.current, tt.args.proposed) - if (err != nil) != tt.wantErr { - t.Errorf("NewValidationContext() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("NewValidationContext() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestValidate(t *testing.T) { - invalidIP := "notanip" - type args struct { - es estype.Elasticsearch - } - tests := []struct { - name string - args args - wantErr bool - errContains []string - }{ - { - name: "happy path", - args: args{ - es: estype.Elasticsearch{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "test-es", - }, - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Name: "default", - Config: &common.Config{ - Data: map[string]interface{}{ - estype.NodeMaster: "true", - estype.NodeData: "false", - estype.NodeIngest: "false", - estype.NodeML: "false", - }, - }, - Count: 1, - }}, - }, - }, - }, - wantErr: false, - }, - { - name: "single failure", - args: args{ - es: estype.Elasticsearch{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "test-es", - }, - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Name: "name", - Count: 1, - Config: &common.Config{ - Data: map[string]interface{}{ - estype.NodeMaster: "false", - }, - }, - }, - }, - }, - }, - }, - wantErr: false, - errContains: []string{ - masterRequiredMsg, - }, - }, - { - name: "multiple failures", - args: args{ - es: estype.Elasticsearch{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "that-is-a-very-long-name-with-37chars", - }, - Spec: estype.ElasticsearchSpec{ - Version: "1.0.0", - HTTP: common.HTTPConfig{ - TLS: common.TLSOptions{ - SelfSignedCertificate: &common.SelfSignedCertificate{ - SubjectAlternativeNames: []common.SubjectAlternativeName{ - { - IP: invalidIP, - }, - }, - }, - }, - }, - NodeSets: []estype.NodeSet{ - { - Count: 1, - Config: &common.Config{ - Data: map[string]interface{}{ - estype.NodeMaster: false, - settings.XPackSecurityTransportSslCertificate: "blacklisted setting", - }, - }, - }, - }, - }, - }, - }, - wantErr: false, - errContains: []string{ - invalidNamesErrMsg, - masterRequiredMsg, - "unsupported version", - "is not user configurable", - invalidSanIPErrMsg, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - validations, err := Validate(tt.args.es) - if (err != nil) != tt.wantErr { - t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) - } - require.Equal(t, len(tt.errContains), len(validations)) - for _, errStr := range tt.errContains { - found := false - for _, v := range validations { - if strings.Contains(v.Reason, errStr) { - found = true - break - } - } - assert.True(t, found, "wanted %v, but not found", errStr) - } - - }) - - } -} diff --git a/pkg/controller/elasticsearch/validation/validations.go b/pkg/controller/elasticsearch/validation/validations.go deleted file mode 100644 index 53f40f3df7..0000000000 --- a/pkg/controller/elasticsearch/validation/validations.go +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package validation - -import ( - "errors" - "fmt" - "net" - "reflect" - "strconv" - "strings" - - "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" - common "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/validation" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" - esversion "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/version" - netutil "github.com/elastic/cloud-on-k8s/pkg/utils/net" - "github.com/elastic/cloud-on-k8s/pkg/utils/set" -) - -// Validations are all registered Elasticsearch validations. -var Validations = []Validation{ - validName, - specUpdatedToBeta, - hasMaster, - supportedVersion, - noDowngrades, - validUpgradePath, - noBlacklistedSettings, - validSanIP, - pvcModification, - checkNodeSetNameUniqueness, -} - -type duplicates map[string]struct{} - -func (d duplicates) String() string { - keys := make([]string, len(d)) - i := 0 - for key := range d { - keys[i] = key - i++ - } - return strings.Join(keys, ", ") -} - -func checkNodeSetNameUniqueness(ctx Context) validation.Result { - nodeSets := ctx.Proposed.Elasticsearch.Spec.NodeSets - names := make(map[string]struct{}) - duplicates := make(duplicates) - for _, nodeSet := range nodeSets { - if _, found := names[nodeSet.Name]; found { - duplicates[nodeSet.Name] = struct{}{} - } - names[nodeSet.Name] = struct{}{} - } - if len(duplicates) > 0 { - return validation.Result{ - Reason: fmt.Sprintf("%s: duplicate node set(s) %s", validationFailedMsg, duplicates), - } - } - return validation.OK -} - -// validName checks whether the name is valid. -func validName(ctx Context) validation.Result { - if err := name.Validate(ctx.Proposed.Elasticsearch); err != nil { - return validation.Result{Allowed: false, Reason: invalidName(err)} - } - return validation.OK -} - -func specUpdatedToBeta(ctx Context) validation.Result { - oldAPIVersion := "elasticsearch.k8s.elastic.co/v1alpha1" - - es := ctx.Proposed.Elasticsearch - if es.APIVersion == oldAPIVersion { - return validation.Result{Reason: fmt.Sprintf("%s: outdated APIVersion", validationFailedMsg)} - } - - if len(es.Spec.NodeSets) == 0 { - return validation.Result{Reason: fmt.Sprintf("%s: at least one nodeSet must be defined", validationFailedMsg)} - } - - for _, set := range es.Spec.NodeSets { - if set.Count == 0 { - msg := fmt.Sprintf("node count of node set '%s' should not be zero", set.Name) - return validation.Result{Reason: fmt.Sprintf("%s: %s", validationFailedMsg, msg)} - } - } - - return validation.OK -} - -// supportedVersion checks if the version is supported. -func supportedVersion(ctx Context) validation.Result { - if v := esversion.SupportedVersions(ctx.Proposed.Version); v != nil { - if err := v.Supports(ctx.Proposed.Version); err == nil { - return validation.OK - } - } - return validation.Result{Allowed: false, Reason: unsupportedVersion(&ctx.Proposed.Version)} - -} - -// hasMaster checks if the given Elasticsearch cluster has at least one master node. -func hasMaster(ctx Context) validation.Result { - var hasMaster bool - for _, t := range ctx.Proposed.Elasticsearch.Spec.NodeSets { - cfg, err := v1beta1.UnpackConfig(t.Config) - if err != nil { - return validation.Result{Reason: cfgInvalidMsg} - } - hasMaster = hasMaster || (cfg.Node.Master && t.Count > 0) - } - if hasMaster { - return validation.OK - } - return validation.Result{Reason: masterRequiredMsg} -} - -func noBlacklistedSettings(ctx Context) validation.Result { - violations := make(map[int]set.StringSet) - for i, n := range ctx.Proposed.Elasticsearch.Spec.NodeSets { - if n.Config == nil { - continue - } - config, err := common.NewCanonicalConfigFrom(n.Config.Data) - if err != nil { - violations[i] = map[string]struct{}{ - cfgInvalidMsg: {}, - } - continue - } - forbidden := config.HasKeys(settings.Blacklist) - // remove duplicates - set := set.Make(forbidden...) - if set.Count() > 0 { - violations[i] = set - } - } - if len(violations) == 0 { - return validation.OK - } - var sb strings.Builder - var sep string - // iterate again to build validation message in node order - for i := range ctx.Proposed.Elasticsearch.Spec.NodeSets { - vs := violations[i] - if vs == nil { - continue - } - sb.WriteString(sep) - sb.WriteString("node[") - sb.WriteString(strconv.FormatInt(int64(i), 10)) - sb.WriteString("]: ") - var sep2 string - list := vs.AsSlice() - list.Sort() - for _, msg := range list { - sb.WriteString(sep2) - sb.WriteString(msg) - sep2 = ", " - } - sep = "; " - } - sb.WriteString(" is not user configurable") - return validation.Result{ - Allowed: false, - Reason: sb.String(), - } -} - -func validSanIP(ctx Context) validation.Result { - selfSignedCerts := ctx.Proposed.Elasticsearch.Spec.HTTP.TLS.SelfSignedCertificate - if selfSignedCerts != nil { - for _, san := range selfSignedCerts.SubjectAlternativeNames { - if san.IP != "" { - ip := netutil.MaybeIPTo4(net.ParseIP(san.IP)) - if ip == nil { - msg := fmt.Sprintf("%s: %s", invalidSanIPErrMsg, san.IP) - return validation.Result{ - Error: errors.New(msg), - Reason: msg, - Allowed: false, - } - } - } - } - } - return validation.OK -} - -// pvcModification ensures no PVCs are changed, as volume claim templates are immutable in stateful sets -func pvcModification(ctx Context) validation.Result { - if ctx.Current == nil { - return validation.OK - } - for _, node := range ctx.Proposed.Elasticsearch.Spec.NodeSets { - currNodeSet := getNodeSet(node.Name, ctx.Current.Elasticsearch) - if currNodeSet == nil { - // this is a new sset, so there is nothing to check - continue - } - - // ssets do not allow modifications to fields other than 'replicas', 'template', and 'updateStrategy' - // reflection isn't ideal, but okay here since the ES object does not have the status of the claims - if !reflect.DeepEqual(node.VolumeClaimTemplates, currNodeSet.VolumeClaimTemplates) { - return validation.Result{ - Allowed: false, - Reason: pvcImmutableMsg, - } - } - } - return validation.OK -} - -func getNodeSet(name string, es v1beta1.Elasticsearch) *v1beta1.NodeSet { - for i := range es.Spec.NodeSets { - if es.Spec.NodeSets[i].Name == name { - return &es.Spec.NodeSets[i] - } - } - return nil -} diff --git a/pkg/controller/elasticsearch/validation/validations_test.go b/pkg/controller/elasticsearch/validation/validations_test.go deleted file mode 100644 index cbc9568fcd..0000000000 --- a/pkg/controller/elasticsearch/validation/validations_test.go +++ /dev/null @@ -1,824 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package validation - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "k8s.io/apimachinery/pkg/api/resource" - - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - common "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" - "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" - estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" - common_name "github.com/elastic/cloud-on-k8s/pkg/controller/common/name" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/validation" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" - corev1 "k8s.io/api/core/v1" -) - -func Test_checkNodeSetNameUniqueness(t *testing.T) { - type args struct { - name string - es v1beta1.Elasticsearch - wantReason string - wantAllowed bool - } - tests := []args{ - { - name: "several duplicate nodeSets", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{ - {Name: "foo", Count: 1}, {Name: "foo", Count: 1}, - {Name: "bar", Count: 1}, {Name: "bar", Count: 1}, - }, - }, - }, - wantAllowed: false, - wantReason: validationFailedMsg, - }, - { - name: "good spec with 1 nodeSet", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{{Name: "foo", Count: 1}}, - }, - }, - wantAllowed: true, - }, - { - name: "good spec with 2 nodeSets", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{{Name: "foo", Count: 1}, {Name: "bar", Count: 1}}, - }, - }, - wantAllowed: true, - }, - { - name: "duplicate nodeSet", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{{Name: "foo", Count: 1}, {Name: "foo", Count: 1}}, - }, - }, - wantAllowed: false, - wantReason: validationFailedMsg, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.es) - require.NoError(t, err) - got := checkNodeSetNameUniqueness(*ctx) - if got.Allowed != tt.wantAllowed { - t.Errorf("checkNodeSetNameUniqueness() = %v, want %v", got.Allowed, tt.wantAllowed) - } - if !strings.Contains(got.Reason, tt.wantReason) { - t.Errorf("checkNodeSetNameUniqueness() = %v, want %v", got.Reason, tt.wantReason) - } - }) - } -} - -func Test_hasMaster(t *testing.T) { - failedValidation := validation.Result{Allowed: false, Reason: masterRequiredMsg} - type args struct { - esCluster v1beta1.Elasticsearch - } - tests := []struct { - name string - args args - want validation.Result - }{ - { - name: "no topology", - args: args{ - esCluster: *es("6.8.0"), - }, - want: failedValidation, - }, - { - name: "topology but no master", - args: args{ - esCluster: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []v1beta1.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - v1beta1.NodeMaster: "false", - v1beta1.NodeData: "false", - v1beta1.NodeIngest: "false", - v1beta1.NodeML: "false", - }, - }, - }, - }, - }, - }, - }, - want: failedValidation, - }, - { - name: "master but zero sized", - args: args{ - esCluster: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []v1beta1.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - v1beta1.NodeMaster: "true", - v1beta1.NodeData: "false", - v1beta1.NodeIngest: "false", - v1beta1.NodeML: "false", - }, - }, - }, - }, - }, - }, - }, - want: failedValidation, - }, - { - name: "has master", - args: args{ - esCluster: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []v1beta1.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - v1beta1.NodeMaster: "true", - v1beta1.NodeData: "false", - v1beta1.NodeIngest: "false", - v1beta1.NodeML: "false", - }, - }, - Count: 1, - }, - }, - }, - }, - }, - want: validation.Result{Allowed: true}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.args.esCluster) - require.NoError(t, err) - if got := hasMaster(*ctx); got != tt.want { - t.Errorf("hasMaster() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_specUpdatedToBeta(t *testing.T) { - type args struct { - name string - es v1beta1.Elasticsearch - wantReason string - wantAllowed bool - } - tests := []args{ - { - name: "good spec", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{{Count: 1}}, - }, - }, - wantAllowed: true, - }, - { - name: "nodes instead of nodeSets", - es: v1beta1.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - }, - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - }, - wantReason: validationFailedMsg, - }, - { - name: "nodeCount instead of count", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1beta1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{{}}, - }, - }, - wantReason: validationFailedMsg, - wantAllowed: false, - }, - { - name: "alpha instead of beta version", - es: v1beta1.Elasticsearch{ - TypeMeta: metav1.TypeMeta{APIVersion: "elasticsearch.k8s.elastic.co/v1alpha1"}, - Spec: estype.ElasticsearchSpec{ - Version: "7.4.0", - NodeSets: []estype.NodeSet{{Count: 1}}, - }, - }, - wantReason: validationFailedMsg, - wantAllowed: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.es) - require.NoError(t, err) - got := specUpdatedToBeta(*ctx) - if got.Allowed != tt.wantAllowed { - t.Errorf("specUpdatedToBeta() = %v, want %v", got.Allowed, tt.wantAllowed) - } - if !strings.Contains(got.Reason, tt.wantReason) { - t.Errorf("specUpdatedToBeta() = %v, want %v", got.Reason, tt.wantReason) - } - }) - } -} - -func Test_supportedVersion(t *testing.T) { - type args struct { - esCluster estype.Elasticsearch - } - tests := []struct { - name string - args args - want validation.Result - }{ - { - name: "unsupported major version should fail", - args: args{ - esCluster: *es("6.0.0"), - }, - want: validation.Result{Allowed: false, Reason: unsupportedVersion(&version.Version{ - Major: 6, - Minor: 0, - Patch: 0, - Label: "", - })}, - }, - { - name: "unsupported FAIL", - args: args{ - esCluster: *es("1.0.0"), - }, - want: validation.Result{Allowed: false, Reason: unsupportedVersion(&version.Version{ - Major: 1, - Minor: 0, - Patch: 0, - Label: "", - })}, - }, - { - name: "supported OK", - args: args{ - esCluster: *es("6.8.0"), - }, - want: validation.OK, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.args.esCluster) - require.NoError(t, err) - if got := supportedVersion(*ctx); !reflect.DeepEqual(got, tt.want) { - t.Errorf("supportedVersion() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_noBlacklistedSettings(t *testing.T) { - type args struct { - es estype.Elasticsearch - } - tests := []struct { - name string - args args - want validation.Result - }{ - { - name: "no settings OK", - args: args{ - es: *es("7.0.0"), - }, - want: validation.OK, - }, - { - name: "enforce blacklist FAIL", - args: args{ - es: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - settings.ClusterInitialMasterNodes: "foo", - }, - }, - Count: 1, - }, - }, - }, - }, - }, - want: validation.Result{Allowed: false, Reason: "node[0]: cluster.initial_master_nodes is not user configurable"}, - }, - { - name: "enforce blacklist in multiple nodes FAIL", - args: args{ - es: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - settings.ClusterInitialMasterNodes: "foo", - }, - }, - }, - { - Config: &common.Config{ - Data: map[string]interface{}{ - settings.XPackSecurityTransportSslVerificationMode: "bar", - }, - }, - }, - }, - }, - }, - }, - want: validation.Result{ - Allowed: false, - Reason: "node[0]: cluster.initial_master_nodes; node[1]: xpack.security.transport.ssl.verification_mode is not user configurable", - }, - }, - { - name: "non blacklisted setting OK", - args: args{ - es: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - "node.attr.box_type": "foo", - }, - }, - }, - }, - }, - }, - }, - want: validation.OK, - }, - { - name: "non blacklisted settings with blacklisted string prefix OK", - args: args{ - es: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - settings.XPackSecurityTransportSslCertificateAuthorities: "foo", - }, - }, - }, - }, - }, - }, - }, - want: validation.OK, - }, - { - name: "settings are canonicalized before validation", - args: args{ - es: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "7.0.0", - NodeSets: []estype.NodeSet{ - { - Config: &common.Config{ - Data: map[string]interface{}{ - "cluster": map[string]interface{}{ - "initial_master_nodes": []string{"foo", "bar"}, - }, - "node.attr.box_type": "foo", - }, - }, - }, - }, - }, - }, - }, - want: validation.Result{Allowed: false, Reason: "node[0]: cluster.initial_master_nodes is not user configurable"}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.args.es) - require.NoError(t, err) - if got := noBlacklistedSettings(*ctx); !reflect.DeepEqual(got, tt.want) { - t.Errorf("noBlacklistedSettings() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestValidNames(t *testing.T) { - type args struct { - esCluster estype.Elasticsearch - } - tests := []struct { - name string - args args - want validation.Result - }{ - { - name: "name length too long", - args: args{ - esCluster: estype.Elasticsearch{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "that-is-a-very-long-name-with-37chars", - }, - Spec: estype.ElasticsearchSpec{Version: "6.8.0"}, - }, - }, - want: validation.Result{ - Allowed: false, - Reason: invalidName(fmt.Errorf("name exceeds maximum allowed length of %d", common_name.MaxResourceNameLength)), - }, - }, - { - name: "name length OK", - args: args{ - esCluster: estype.Elasticsearch{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "that-is-a-very-long-name-with-36char", - }, - Spec: estype.ElasticsearchSpec{Version: "6.8.0"}, - }, - }, - want: validation.OK, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.args.esCluster) - require.NoError(t, err) - if got := validName(*ctx); !reflect.DeepEqual(got, tt.want) { - t.Errorf("supportedVersion() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_validSanIP(t *testing.T) { - validIP := "3.4.5.6" - validIP2 := "192.168.12.13" - validIPv6 := "2001:db8:0:85a3:0:0:ac1f:8001" - invalidIP := "notanip" - tests := []struct { - name string - esCluster estype.Elasticsearch - want validation.Result - }{ - { - name: "no SAN IP: OK", - esCluster: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{Version: "6.8.0"}, - }, - want: validation.OK, - }, - { - name: "valid SAN IPs: OK", - esCluster: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "6.8.0", - HTTP: common.HTTPConfig{ - TLS: common.TLSOptions{ - SelfSignedCertificate: &common.SelfSignedCertificate{ - SubjectAlternativeNames: []common.SubjectAlternativeName{ - { - IP: validIP, - }, - { - IP: validIP2, - }, - { - IP: validIPv6, - }, - }, - }, - }, - }, - }, - }, - want: validation.OK, - }, - { - name: "invalid SAN IPs: NOT OK", - esCluster: estype.Elasticsearch{ - Spec: estype.ElasticsearchSpec{ - Version: "6.8.0", - HTTP: common.HTTPConfig{ - TLS: common.TLSOptions{ - SelfSignedCertificate: &common.SelfSignedCertificate{ - SubjectAlternativeNames: []common.SubjectAlternativeName{ - { - IP: invalidIP, - }, - { - IP: validIP2, - }, - }, - }, - }, - }, - }, - }, - want: validation.Result{Allowed: false, Reason: "invalid SAN IP address: notanip", Error: fmt.Errorf("invalid SAN IP address: notanip")}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(nil, tt.esCluster) - require.NoError(t, err) - if got := validSanIP(*ctx); !reflect.DeepEqual(got, tt.want) { - t.Errorf("validSanIP() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_pvcModified(t *testing.T) { - failedValidation := validation.Result{Allowed: false, Reason: pvcImmutableMsg} - current := getEsCluster() - tests := []struct { - name string - current *v1beta1.Elasticsearch - proposed v1beta1.Elasticsearch - want validation.Result - }{ - { - name: "resize fails", - current: current, - proposed: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.2.0", - NodeSets: []v1beta1.NodeSet{ - { - Name: "master", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("10Gi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - want: failedValidation, - }, - - { - name: "same size accepted", - current: current, - proposed: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.2.0", - NodeSets: []v1beta1.NodeSet{ - { - Name: "master", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("5Gi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - want: validation.OK, - }, - - { - name: "additional PVC fails", - current: current, - proposed: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.2.0", - NodeSets: []v1beta1.NodeSet{ - { - Name: "master", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("5Gi"), - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data1", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("5Gi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - want: failedValidation, - }, - - { - name: "name change rejected", - current: current, - proposed: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.2.0", - NodeSets: []v1beta1.NodeSet{ - { - Name: "master", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data1", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("5Gi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - want: failedValidation, - }, - - { - name: "add new node set accepted", - current: current, - proposed: v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.2.0", - NodeSets: []v1beta1.NodeSet{ - { - Name: "master", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("5Gi"), - }, - }, - }, - }, - }, - }, - { - Name: "ingest", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("10Gi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - want: validation.OK, - }, - - { - name: "new instance accepted", - current: nil, - proposed: *current, - want: validation.OK, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, err := NewValidationContext(current, tt.proposed) - require.NoError(t, err) - require.Equal(t, tt.want, pvcModification(*ctx)) - }) - } -} - -// getEsCluster returns a ES cluster test fixture -func getEsCluster() *v1beta1.Elasticsearch { - return &v1beta1.Elasticsearch{ - Spec: v1beta1.ElasticsearchSpec{ - Version: "7.2.0", - NodeSets: []v1beta1.NodeSet{ - { - Name: "master", - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "elasticsearch-data", - }, - Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: resource.MustParse("5Gi"), - }, - }, - }, - }, - }, - }, - }, - }, - } -} diff --git a/pkg/controller/elasticsearch/version/running_versions_test.go b/pkg/controller/elasticsearch/version/running_versions_test.go deleted file mode 100644 index 4f1a84b643..0000000000 --- a/pkg/controller/elasticsearch/version/running_versions_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package version - -import ( - "reflect" - "testing" - - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestCurrentVersions(t *testing.T) { - tests := []struct { - name string - args []corev1.Pod - want *version.Version - wantErr bool - }{ - { - name: "no pods", - args: nil, - want: nil, - wantErr: false, - }, - { - name: "no versions in pods", - args: []corev1.Pod{ - {}, - }, - want: nil, - wantErr: true, - }, - { - name: "one pod", - args: []corev1.Pod{ - { - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - label.VersionLabelName: "1.0.0", - }, - }, - }, - }, - want: &version.Version{ - Major: 1, - Minor: 0, - Patch: 0, - Label: "", - }, - wantErr: false, - }, - { - name: "n pods", - args: []corev1.Pod{ - { - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - label.VersionLabelName: "2.0.0", - }, - }, - }, - { - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - label.VersionLabelName: "1.0.0", - }, - }, - }, - }, - want: &version.Version{ - Major: 1, - Minor: 0, - Patch: 0, - Label: "", - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := MinVersion(tt.args) - if (err != nil) != tt.wantErr { - t.Errorf("MinVersion() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("MinVersion() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/controller/elasticsearch/version/supported_versions.go b/pkg/controller/elasticsearch/version/supported_versions.go index 22ddb2be9c..2350bcbe92 100644 --- a/pkg/controller/elasticsearch/version/supported_versions.go +++ b/pkg/controller/elasticsearch/version/supported_versions.go @@ -7,11 +7,7 @@ package version import ( "fmt" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/pkg/errors" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - corev1 "k8s.io/api/core/v1" ) // LowestHighestSupportedVersions expresses the wire-format compatibility range for a version. @@ -20,6 +16,7 @@ type LowestHighestSupportedVersions struct { HighestSupportedVersion version.Version } +// SupportedVersions returns the supported minor versions for given major version func SupportedVersions(v version.Version) *LowestHighestSupportedVersions { switch v.Major { case 6: @@ -41,22 +38,6 @@ func SupportedVersions(v version.Version) *LowestHighestSupportedVersions { } } -// VerifySupportsExistingPods checks the given pods against the supported version range in lh. -func (lh LowestHighestSupportedVersions) VerifySupportsExistingPods( - pods []corev1.Pod, -) error { - for _, pod := range pods { - v, err := label.ExtractVersion(pod.Labels) - if err != nil { - return err - } - if err := lh.Supports(*v); err != nil { - return errors.Wrapf(err, "%s has incompatible version", pod.Name) - } - } - return nil -} - // Supports compares a given with the supported version range and returns an error if out of bounds. func (lh LowestHighestSupportedVersions) Supports(v version.Version) error { if !v.IsSameOrAfter(lh.LowestSupportedVersion) { diff --git a/pkg/controller/elasticsearch/version/supported_versions_test.go b/pkg/controller/elasticsearch/version/supported_versions_test.go index b9442894cf..917a7cb6fd 100644 --- a/pkg/controller/elasticsearch/version/supported_versions_test.go +++ b/pkg/controller/elasticsearch/version/supported_versions_test.go @@ -7,17 +7,8 @@ package version import ( "testing" - "github.com/stretchr/testify/require" - - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var ( - testPodWithoutVersionLabel = corev1.Pod{} + "github.com/stretchr/testify/require" ) func TestSupportedVersions(t *testing.T) { @@ -73,95 +64,39 @@ func TestSupportedVersions(t *testing.T) { } } -func Test_lowestHighestSupportedVersions_VerifySupportsExistingPods(t *testing.T) { - newPodWithVersionLabel := func(v version.Version) corev1.Pod { - return corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - label.VersionLabelName: v.String(), - }, - }, - } - } - type fields struct { - lowestSupportedVersion version.Version - highestSupportedVersion version.Version - } - type args struct { - pods []corev1.Pod - } +func TestSupports(t *testing.T) { tests := []struct { - name string - fields fields - args args - wantErr bool + name string + lhsv LowestHighestSupportedVersions + ver version.Version + expectError bool }{ { - name: "no pods", - fields: fields{}, - args: args{pods: []corev1.Pod{}}, - wantErr: false, - }, - { - name: "pod with version label at higher bound", - fields: fields{ - lowestSupportedVersion: version.Version{Major: 6}, - highestSupportedVersion: version.Version{Major: 7}, + name: "in range", + lhsv: LowestHighestSupportedVersions{ + LowestSupportedVersion: version.MustParse("2.0.1"), + HighestSupportedVersion: version.MustParse("3.0.0"), }, - args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 7})}}, - wantErr: false, + ver: version.MustParse("2.0.2-rc0"), + expectError: false, }, { - name: "pod with version label at lower bound", - fields: fields{ - lowestSupportedVersion: version.Version{Major: 6}, - highestSupportedVersion: version.Version{Major: 7}, + name: "out of range", + lhsv: LowestHighestSupportedVersions{ + LowestSupportedVersion: version.MustParse("2.0.1"), + HighestSupportedVersion: version.MustParse("3.0.0"), }, - args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 6})}}, - wantErr: false, - }, - { - name: "pod with version label within bounds", - fields: fields{ - lowestSupportedVersion: version.Version{Major: 6}, - highestSupportedVersion: version.Version{Major: 7}, - }, - args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 6, Minor: 4, Patch: 2})}}, - wantErr: false, - }, - { - name: "pod without label", - fields: fields{}, - args: args{pods: []corev1.Pod{testPodWithoutVersionLabel}}, - wantErr: true, - }, - { - name: "pod with too low version label", - fields: fields{ - lowestSupportedVersion: version.Version{Major: 6}, - highestSupportedVersion: version.Version{Major: 7}, - }, - args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 5})}}, - wantErr: true, - }, - { - name: "pod with too high version label", - fields: fields{ - lowestSupportedVersion: version.Version{Major: 6}, - highestSupportedVersion: version.Version{Major: 7}, - }, - args: args{pods: []corev1.Pod{newPodWithVersionLabel(version.Version{Major: 8})}}, - wantErr: true, + ver: version.MustParse("3.0.1"), + expectError: true, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - lh := LowestHighestSupportedVersions{ - LowestSupportedVersion: tt.fields.lowestSupportedVersion, - HighestSupportedVersion: tt.fields.highestSupportedVersion, - } - if err := lh.VerifySupportsExistingPods(tt.args.pods); (err != nil) != tt.wantErr { - t.Errorf("LowestHighestSupportedVersions.VerifySupportsExistingPods() error = %v, wantErr %v", err, tt.wantErr) + err := tt.lhsv.Supports(tt.ver) + actual := err != nil + if tt.expectError != actual { + t.Errorf("failed Supports(). Name: %v, actual: %v, wanted: %v, value: %v", tt.name, err, tt.expectError, tt.ver) } }) } diff --git a/pkg/controller/elasticsearch/version/zen1/minimum_masters.go b/pkg/controller/elasticsearch/version/zen1/minimum_masters.go index 68e726a0c6..c2093fb505 100644 --- a/pkg/controller/elasticsearch/version/zen1/minimum_masters.go +++ b/pkg/controller/elasticsearch/version/zen1/minimum_masters.go @@ -63,7 +63,6 @@ func SetupMinimumMasterNodesConfig( actualMasters := len(label.FilterMasterNodePods(actualPods)) masters += actualMasters } - } quorum := settings.Quorum(masters) @@ -72,7 +71,7 @@ func SetupMinimumMasterNodesConfig( // patch config with the expected minimum master nodes if err := nodeSpecResources[i].Config.MergeWith( common.MustNewSingleValue( - settings.DiscoveryZenMinimumMasterNodes, + v1beta1.DiscoveryZenMinimumMasterNodes, strconv.Itoa(quorum), ), ); err != nil { diff --git a/pkg/controller/elasticsearch/version/zen1/minimum_masters_test.go b/pkg/controller/elasticsearch/version/zen1/minimum_masters_test.go index 9e34fdd9fa..d6d914f30c 100644 --- a/pkg/controller/elasticsearch/version/zen1/minimum_masters_test.go +++ b/pkg/controller/elasticsearch/version/zen1/minimum_masters_test.go @@ -48,13 +48,13 @@ func TestSetupMinimumMasterNodesConfig(t *testing.T) { }, expected: []settings.CanonicalConfig{ {CanonicalConfig: settings2.MustCanonicalConfig(map[string]string{ - settings.DiscoveryZenMinimumMasterNodes: "4", + v1beta1.DiscoveryZenMinimumMasterNodes: "4", })}, {CanonicalConfig: settings2.MustCanonicalConfig(map[string]string{ - settings.DiscoveryZenMinimumMasterNodes: "4", + v1beta1.DiscoveryZenMinimumMasterNodes: "4", })}, {CanonicalConfig: settings2.MustCanonicalConfig(map[string]string{ - settings.DiscoveryZenMinimumMasterNodes: "4", + v1beta1.DiscoveryZenMinimumMasterNodes: "4", })}, }, pods: []runtime.Object{}, @@ -66,7 +66,7 @@ func TestSetupMinimumMasterNodesConfig(t *testing.T) { }, expected: []settings.CanonicalConfig{ {CanonicalConfig: settings2.MustCanonicalConfig(map[string]string{ - settings.DiscoveryZenMinimumMasterNodes: "2", + v1beta1.DiscoveryZenMinimumMasterNodes: "2", })}, settings.NewCanonicalConfig(), }, diff --git a/pkg/controller/elasticsearch/version/zen2/initial_master_nodes.go b/pkg/controller/elasticsearch/version/zen2/initial_master_nodes.go index 0091aef411..0bc4c178b1 100644 --- a/pkg/controller/elasticsearch/version/zen2/initial_master_nodes.go +++ b/pkg/controller/elasticsearch/version/zen2/initial_master_nodes.go @@ -5,9 +5,9 @@ package zen2 import ( + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/nodespec" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" ) // SetupInitialMasterNodes modifies the ES config of the given resources to setup @@ -28,7 +28,7 @@ func SetupInitialMasterNodes( continue } // patch config with the expected initial master nodes - if err := nodeSpecResources[i].Config.SetStrings(settings.ClusterInitialMasterNodes, masters...); err != nil { + if err := nodeSpecResources[i].Config.SetStrings(v1beta1.ClusterInitialMasterNodes, masters...); err != nil { return err } } diff --git a/pkg/controller/elasticsearch/version/zen2/initial_master_nodes_test.go b/pkg/controller/elasticsearch/version/zen2/initial_master_nodes_test.go index a1e662b192..70e4d5da3f 100644 --- a/pkg/controller/elasticsearch/version/zen2/initial_master_nodes_test.go +++ b/pkg/controller/elasticsearch/version/zen2/initial_master_nodes_test.go @@ -7,12 +7,12 @@ package zen2 import ( "testing" - "github.com/stretchr/testify/require" - + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" settings2 "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/nodespec" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/settings" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/sset" + "github.com/stretchr/testify/require" ) func TestSetupInitialMasterNodes(t *testing.T) { @@ -37,10 +37,10 @@ func TestSetupInitialMasterNodes(t *testing.T) { }, expected: []settings.CanonicalConfig{ {CanonicalConfig: settings2.MustCanonicalConfig(map[string][]string{ - settings.ClusterInitialMasterNodes: {"master-0", "master-1", "master-2", "masterdata-0", "masterdata-1", "masterdata-2"}, + v1beta1.ClusterInitialMasterNodes: {"master-0", "master-1", "master-2", "masterdata-0", "masterdata-1", "masterdata-2"}, })}, {CanonicalConfig: settings2.MustCanonicalConfig(map[string][]string{ - settings.ClusterInitialMasterNodes: {"master-0", "master-1", "master-2", "masterdata-0", "masterdata-1", "masterdata-2"}, + v1beta1.ClusterInitialMasterNodes: {"master-0", "master-1", "master-2", "masterdata-0", "masterdata-1", "masterdata-2"}, })}, // no config set on non-master nodes {CanonicalConfig: settings2.NewCanonicalConfig()}, @@ -62,7 +62,7 @@ func TestSetupInitialMasterNodes(t *testing.T) { expected: []settings.CanonicalConfig{ settings.NewCanonicalConfig(), {CanonicalConfig: settings2.MustCanonicalConfig(map[string][]string{ - settings.ClusterInitialMasterNodes: {"masterv6-0", "masterv6-1", "masterv6-2", "masterv7-0", "masterv7-1", "masterv7-2"}, + v1beta1.ClusterInitialMasterNodes: {"masterv6-0", "masterv6-1", "masterv6-2", "masterv7-0", "masterv7-1", "masterv7-2"}, })}, }, }, diff --git a/pkg/controller/kibanaassociation/association_controller.go b/pkg/controller/kibanaassociation/association_controller.go index fe19722968..8468e54474 100644 --- a/pkg/controller/kibanaassociation/association_controller.go +++ b/pkg/controller/kibanaassociation/association_controller.go @@ -20,7 +20,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" "github.com/elastic/cloud-on-k8s/pkg/controller/common/user" "github.com/elastic/cloud-on-k8s/pkg/controller/common/watches" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/services" elasticsearchuser "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/user" "github.com/elastic/cloud-on-k8s/pkg/controller/kibana/label" @@ -317,7 +316,7 @@ func (r *ReconcileAssociation) reconcileElasticsearchCA(kibana *kbtype.Kibana, e // watch ES CA secret to reconcile on any change if err := r.watches.Secrets.AddHandler(watches.NamedWatch{ Name: esCAWatchName(kibanaKey), - Watched: []types.NamespacedName{http.PublicCertsSecretRef(esname.ESNamer, es)}, + Watched: []types.NamespacedName{http.PublicCertsSecretRef(estype.ESNamer, es)}, Watcher: kibanaKey, }); err != nil { return association.CASecret{}, err diff --git a/pkg/controller/license/license_controller.go b/pkg/controller/license/license_controller.go index 5c375afaa0..c29d4bac11 100644 --- a/pkg/controller/license/license_controller.go +++ b/pkg/controller/license/license_controller.go @@ -16,7 +16,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" esclient "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -166,7 +165,7 @@ func reconcileSecret( parent string, esLicense esclient.License, ) error { - secretName := esname.LicenseSecretName(cluster.Name) + secretName := v1beta1.LicenseSecretName(cluster.Name) licenseBytes, err := json.Marshal(esLicense) if err != nil { diff --git a/pkg/controller/license/license_controller_integration_test.go b/pkg/controller/license/license_controller_integration_test.go index 941079b2f1..8a7d699282 100644 --- a/pkg/controller/license/license_controller_integration_test.go +++ b/pkg/controller/license/license_controller_integration_test.go @@ -16,7 +16,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/license" "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" esclient "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/chrono" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/elastic/cloud-on-k8s/pkg/utils/test" @@ -108,7 +107,7 @@ func TestReconcile(t *testing.T) { // test license assignment and ownership being triggered on cluster create test.RetryUntilSuccess(t, func() error { var clusterLicense corev1.Secret - if err := c.Get(types.NamespacedName{Namespace: "default", Name: esname.LicenseSecretName("foo")}, &clusterLicense); err != nil { + if err := c.Get(types.NamespacedName{Namespace: "default", Name: v1beta1.LicenseSecretName("foo")}, &clusterLicense); err != nil { return err } return validateOwnerRef(&clusterLicense, cluster.ObjectMeta) diff --git a/pkg/controller/license/license_controller_test.go b/pkg/controller/license/license_controller_test.go index b12ddcc635..8f9332b7d3 100644 --- a/pkg/controller/license/license_controller_test.go +++ b/pkg/controller/license/license_controller_test.go @@ -13,7 +13,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" commonlicense "github.com/elastic/cloud-on-k8s/pkg/controller/common/license" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/utils/chrono" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/stretchr/testify/require" @@ -195,7 +194,7 @@ func TestReconcileLicenses_reconcileInternal(t *testing.T) { // verify that a cluster license was created // following the es naming convention licenseNsn := nsn - licenseNsn.Name = esname.LicenseSecretName(licenseNsn.Name) + licenseNsn.Name = v1beta1.LicenseSecretName(licenseNsn.Name) var license corev1.Secret err = client.Get(licenseNsn, &license) if !tt.wantNewLicense { diff --git a/test/e2e/es/certs_test.go b/test/e2e/es/certs_test.go index 9a540347f2..8264b2a222 100644 --- a/test/e2e/es/certs_test.go +++ b/test/e2e/es/certs_test.go @@ -15,7 +15,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/dev/portforward" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/elastic/cloud-on-k8s/test/e2e/test" @@ -94,7 +93,7 @@ func getCert(k *test.K8sClient, ns string, esName string) ([]byte, error) { var secret corev1.Secret key := types.NamespacedName{ Namespace: ns, - Name: certificates.PublicSecretName(esname.ESNamer, esName, certificates.HTTPCAType), + Name: certificates.PublicSecretName(v1beta1.ESNamer, esName, certificates.HTTPCAType), } if err := k.Client.Get(key, &secret); err != nil { return nil, err diff --git a/test/e2e/es/failure_test.go b/test/e2e/es/failure_test.go index d0b296a849..4abc4da35d 100644 --- a/test/e2e/es/failure_test.go +++ b/test/e2e/es/failure_test.go @@ -7,8 +7,8 @@ package es import ( "testing" + "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/test/e2e/test" "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" "github.com/stretchr/testify/require" @@ -68,7 +68,7 @@ func TestDeleteServices(t *testing.T) { { Name: "Delete external service", Test: func(t *testing.T) { - s, err := k.GetService(b.Elasticsearch.Namespace, esname.HTTPService(b.Elasticsearch.Name)) + s, err := k.GetService(b.Elasticsearch.Namespace, v1beta1.HTTPService(b.Elasticsearch.Name)) require.NoError(t, err) err = k.Client.Delete(s) require.NoError(t, err) diff --git a/test/e2e/es/forced_upgrade_test.go b/test/e2e/es/forced_upgrade_test.go index 6d65437d9c..8087af32fd 100644 --- a/test/e2e/es/forced_upgrade_test.go +++ b/test/e2e/es/forced_upgrade_test.go @@ -9,11 +9,9 @@ import ( "fmt" "testing" - "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" estype "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/test/e2e/test" "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" corev1 "k8s.io/api/core/v1" @@ -74,7 +72,7 @@ func TestForceUpgradePendingPodsInOneStatefulSet(t *testing.T) { { Name: "Wait for Pods of the first StatefulSet to be running, and second StatefulSet to be Pending", Test: test.Eventually(func() error { - pendingSset := name.StatefulSet(initial.Elasticsearch.Name, initial.Elasticsearch.Spec.NodeSets[1].Name) + pendingSset := estype.StatefulSet(initial.Elasticsearch.Name, initial.Elasticsearch.Spec.NodeSets[1].Name) pods, err := k.GetPods(test.ESPodListOptions(initial.Elasticsearch.Namespace, initial.Elasticsearch.Name)...) if err != nil { return err @@ -97,7 +95,7 @@ func TestForceUpgradePendingPodsInOneStatefulSet(t *testing.T) { { Name: "Wait for the ES service to have endpoints and become technically reachable", Test: test.Eventually(func() error { - endpoints, err := k.GetEndpoints(initial.Elasticsearch.Namespace, name.HTTPService(initial.Elasticsearch.Name)) + endpoints, err := k.GetEndpoints(initial.Elasticsearch.Namespace, estype.HTTPService(initial.Elasticsearch.Name)) if err != nil { return err } @@ -137,7 +135,7 @@ func TestForceUpgradeBootloopingPods(t *testing.T) { "Pods should have restarted at least once due to wrong ES config", func(p corev1.Pod) error { for _, containerStatus := range p.Status.ContainerStatuses { - if containerStatus.Name != v1beta1.ElasticsearchContainerName { + if containerStatus.Name != estype.ElasticsearchContainerName { continue } if containerStatus.RestartCount < 1 { @@ -145,7 +143,7 @@ func TestForceUpgradeBootloopingPods(t *testing.T) { } return nil } - return fmt.Errorf("container %s not found in pod %s", v1beta1.ElasticsearchContainerName, p.Name) + return fmt.Errorf("container %s not found in pod %s", estype.ElasticsearchContainerName, p.Name) }, ), }, diff --git a/test/e2e/test/elasticsearch/checks_k8s.go b/test/e2e/test/elasticsearch/checks_k8s.go index 48527386c0..cae72cf7b3 100644 --- a/test/e2e/test/elasticsearch/checks_k8s.go +++ b/test/e2e/test/elasticsearch/checks_k8s.go @@ -14,7 +14,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/sset" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/elastic/cloud-on-k8s/test/e2e/test" @@ -170,7 +169,7 @@ func CheckServices(b Builder, k *test.K8sClient) test.Step { Name: "ES services should be created", Test: test.Eventually(func() error { for _, s := range []string{ - esname.HTTPService(b.Elasticsearch.Name), + estype.HTTPService(b.Elasticsearch.Name), } { if _, err := k.GetService(b.Elasticsearch.Namespace, s); err != nil { return err @@ -187,7 +186,7 @@ func CheckServicesEndpoints(b Builder, k *test.K8sClient) test.Step { Name: "ES services should have endpoints", Test: test.Eventually(func() error { for endpointName, addrCount := range map[string]int{ - esname.HTTPService(b.Elasticsearch.Name): int(b.Elasticsearch.Spec.NodeCount()), + estype.HTTPService(b.Elasticsearch.Name): int(b.Elasticsearch.Spec.NodeCount()), } { if addrCount == 0 { continue // maybe no Kibana @@ -249,7 +248,7 @@ func checkExpectedPodsReady(b Builder, k *test.K8sClient) error { if err := k.Client.Get( types.NamespacedName{ Namespace: b.Elasticsearch.Namespace, - Name: esname.StatefulSet(b.Elasticsearch.Name, nodeSet.Name), + Name: estype.StatefulSet(b.Elasticsearch.Name, nodeSet.Name), }, &statefulSet, ); err != nil { @@ -303,7 +302,7 @@ func checkStatefulSetsReplicas(b Builder, k *test.K8sClient) error { // build names and replicas count of expected StatefulSets expected := make(map[string]int32, len(b.Elasticsearch.Spec.NodeSets)) // map[StatefulSetName]Replicas for _, nodeSet := range b.Elasticsearch.Spec.NodeSets { - expected[esname.StatefulSet(b.Elasticsearch.Name, nodeSet.Name)] = nodeSet.Count + expected[estype.StatefulSet(b.Elasticsearch.Name, nodeSet.Name)] = nodeSet.Count } statefulSets, err := k.GetESStatefulSets(b.Elasticsearch.Namespace, b.Elasticsearch.Name) if err != nil { @@ -329,7 +328,7 @@ func AnnotatePodsWithBuilderHash(b Builder, k *test.K8sClient) []test.Step { for _, nodeSet := range b.Elasticsearch.Spec.NodeSets { pods, err := sset.GetActualPodsForStatefulSet(k.Client, types.NamespacedName{ Namespace: es.Namespace, - Name: esname.StatefulSet(es.Name, nodeSet.Name), + Name: estype.StatefulSet(es.Name, nodeSet.Name), }) if err != nil { return err diff --git a/test/e2e/test/elasticsearch/http_client.go b/test/e2e/test/elasticsearch/http_client.go index 6e14144e11..7c440c58dc 100644 --- a/test/e2e/test/elasticsearch/http_client.go +++ b/test/e2e/test/elasticsearch/http_client.go @@ -8,7 +8,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1beta1" "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" - "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/reconcile" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/services" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/sset" @@ -25,7 +24,7 @@ func NewElasticsearchClient(es v1beta1.Elasticsearch, k *test.K8sClient) (client } esUser := client.UserAuth{Name: "elastic", Password: password} - caCert, err := k.GetHTTPCerts(name.ESNamer, es.Namespace, es.Name) + caCert, err := k.GetHTTPCerts(v1beta1.ESNamer, es.Namespace, es.Name) if err != nil { return nil, err } diff --git a/test/e2e/test/k8s_client.go b/test/e2e/test/k8s_client.go index e3daca03ad..9598d80226 100644 --- a/test/e2e/test/k8s_client.go +++ b/test/e2e/test/k8s_client.go @@ -20,7 +20,6 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/common/name" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/certificates/transport" "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" - esname "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/name" kblabel "github.com/elastic/cloud-on-k8s/pkg/controller/kibana/label" "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" "github.com/pkg/errors" @@ -217,7 +216,7 @@ func (k *K8sClient) GetCA(ownerNamespace, ownerName string, caType certificates. var secret corev1.Secret key := types.NamespacedName{ Namespace: ownerNamespace, - Name: certificates.CAInternalSecretName(esname.ESNamer, ownerName, caType), + Name: certificates.CAInternalSecretName(estype.ESNamer, ownerName, caType), } if err := k.Client.Get(key, &secret); err != nil { return nil, err @@ -253,7 +252,7 @@ func (k *K8sClient) GetTransportCert(esName, podName string) (caCert, transportC var secret corev1.Secret key := types.NamespacedName{ Namespace: Ctx().ManagedNamespace(0), - Name: esname.TransportCertificatesSecret(esName), + Name: estype.TransportCertificatesSecret(esName), } if err = k.Client.Get(key, &secret); err != nil { return nil, nil, err