pkg/apis/elasticsearch/v1/name.go (145 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package v1 import ( "strconv" "strings" "github.com/pkg/errors" apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation" utilvalidation "k8s.io/apimachinery/pkg/util/validation" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/hash" common_name "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/name" ) const ( configSecretSuffix = "config" secureSettingsSecretSuffix = "secure-settings" fileSettingsSecretSuffix = "file-settings" policyEsConfigSecretSuffix = "policy-config" //nolint:gosec httpServiceSuffix = "http" internalHTTPServiceSuffix = "internal-http" remoteClusterServiceSuffix = "remote-cluster" transportServiceSuffix = "transport" elasticUserSecretSuffix = "elastic-user" internalUsersSecretSuffix = "internal-users" unicastHostsConfigMapSuffix = "unicast-hosts" licenseSecretSuffix = "license" defaultPodDisruptionBudget = "default" scriptsConfigMapSuffix = "scripts" legacyTransportCertsSecretSuffix = "transport-certificates" statefulSetTransportCertificatesSecretSuffix = "transport-certs" // calling this secret "xpack-file-realm" is conceptually wrong since it also holds the file-based roles which // are not part of the file realm - let's still keep this legacy name for convenience rolesAndFileRealmSecretSuffix = "xpack-file-realm" //nolint:gosec // remoteCaNameSuffix is a suffix for the secret that contains the concatenation of all the remote CAs remoteCaNameSuffix = "remote-ca" // remoteAPIKeysNameSuffix is a suffix for the secret that contains the API keys for the remote clusters. remoteAPIKeysNameSuffix = "remote-api-keys" controllerRevisionHashLen = 10 ) var ( // ESNamer is a Namer that is configured with the defaults for resources related to an ES cluster. ESNamer = common_name.NewNamer("es") suffixes = []string{ configSecretSuffix, secureSettingsSecretSuffix, httpServiceSuffix, elasticUserSecretSuffix, rolesAndFileRealmSecretSuffix, internalUsersSecretSuffix, unicastHostsConfigMapSuffix, licenseSecretSuffix, defaultPodDisruptionBudget, scriptsConfigMapSuffix, statefulSetTransportCertificatesSecretSuffix, remoteCaNameSuffix, remoteAPIKeysNameSuffix, } ) // 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 errors.Errorf("name exceeds maximum allowed length of %d", common_name.MaxResourceNameLength) } nodeSetNames := map[string]struct{}{} // validate ssets for _, nodeSet := range es.Spec.NodeSets { if _, ok := nodeSetNames[nodeSet.Name]; ok { return errors.Errorf("duplicated nodeSet name: '%s'", nodeSet.Name) } nodeSetNames[nodeSet.Name] = struct{}{} if errs := apimachineryvalidation.NameIsDNSSubdomain(nodeSet.Name, false); len(errs) > 0 { return errors.Errorf("invalid nodeSet name '%s': [%s]", nodeSet.Name, strings.Join(errs, ",")) } ssetName, err := ESNamer.SafeSuffix(es.Name, nodeSet.Name) if err != nil { return errors.Wrapf(err, "error generating StatefulSet name for nodeSet: '%s'", nodeSet.Name) } // 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 utilvalidation.LabelValueMaxLength-len(ssetName) < podOrdinalSuffixLen+controllerRevisionHashLen { return errors.Errorf("generated StatefulSet name '%s' exceeds allowed length of %d", ssetName, utilvalidation.LabelValueMaxLength-podOrdinalSuffixLen-controllerRevisionHashLen) } } // validate other suffixes for _, suffix := range suffixes { if _, err := ESNamer.SafeSuffix(es.Name, suffix); err != nil { return err } } return nil } // StatefulSet returns the name of the StatefulSet corresponding to the given NodeSet. func StatefulSet(esName string, nodeSetName string) string { return ESNamer.Suffix(esName, nodeSetName) } func ConfigSecret(ssetName string) string { return ESNamer.Suffix(ssetName, configSecretSuffix) } func SecureSettingsSecret(esName string) string { return ESNamer.Suffix(esName, secureSettingsSecretSuffix) } func StatefulSetTransportCertificatesSecret(ssetName string) string { return ESNamer.Suffix(ssetName, statefulSetTransportCertificatesSecretSuffix) } // LegacyTransportCertsSecretSuffix returns the former name of the Secret which used to contain the transport certificates. // This function only exists to let the controller delete that Secret. func LegacyTransportCertsSecretSuffix(esName string) string { return ESNamer.Suffix(esName, legacyTransportCertsSecretSuffix) } func TransportService(esName string) string { return ESNamer.Suffix(esName, transportServiceSuffix) } func InternalHTTPService(esName string) string { return ESNamer.Suffix(esName, internalHTTPServiceSuffix) } func RemoteClusterService(esName string) string { return ESNamer.Suffix(esName, remoteClusterServiceSuffix) } func HTTPService(esName string) string { return ESNamer.Suffix(esName, httpServiceSuffix) } func ElasticUserSecret(esName string) string { return ESNamer.Suffix(esName, elasticUserSecretSuffix) } func RolesAndFileRealmSecret(esName string) string { return ESNamer.Suffix(esName, rolesAndFileRealmSecretSuffix) } func InternalUsersSecret(esName string) string { return ESNamer.Suffix(esName, internalUsersSecretSuffix) } // UnicastHostsConfigMap returns the name of the ConfigMap that holds the list of seed nodes for a given cluster. func UnicastHostsConfigMap(esName string) string { return ESNamer.Suffix(esName, unicastHostsConfigMapSuffix) } func ScriptsConfigMap(esName string) string { return ESNamer.Suffix(esName, scriptsConfigMapSuffix) } func LicenseSecretName(esName string) string { return ESNamer.Suffix(esName, licenseSecretSuffix) } func DefaultPodDisruptionBudget(esName string) string { return ESNamer.Suffix(esName, defaultPodDisruptionBudget) } func RemoteCaSecretName(esName string) string { return ESNamer.Suffix(esName, remoteCaNameSuffix) } func RemoteAPIKeysSecretName(esName string) string { return ESNamer.Suffix(esName, remoteAPIKeysNameSuffix) } func FileSettingsSecretName(esName string) string { return ESNamer.Suffix(esName, fileSettingsSecretSuffix) } func StackConfigElasticsearchConfigSecretName(esName string) string { return ESNamer.Suffix(esName, policyEsConfigSecretSuffix) } // StackConfigAdditionalSecretName returns the name of the stack config policy Secret suffixed with a hash to prevent conflicts. // This also helps keep the secret name size to within kubernetes name limits even if the secret name created by the user is long. func StackConfigAdditionalSecretName(esName string, secretName string) string { secretNameHash := hash.HashObject(secretName) return ESNamer.Suffix(esName, "scp", secretNameHash) }