diff --git a/pkg/asset/installconfig/clustername.go b/pkg/asset/installconfig/clustername.go index 46060bef4e..da311a300a 100644 --- a/pkg/asset/installconfig/clustername.go +++ b/pkg/asset/installconfig/clustername.go @@ -4,8 +4,6 @@ import ( survey "gopkg.in/AlecAivazis/survey.v1" "github.com/openshift/installer/pkg/asset" - azurevalidation "github.com/openshift/installer/pkg/types/azure/validation" - gcpvalidation "github.com/openshift/installer/pkg/types/gcp/validation" "github.com/openshift/installer/pkg/types/validation" "github.com/openshift/installer/pkg/validate" ) @@ -32,10 +30,10 @@ func (a *clusterName) Generate(parents asset.Parents) error { validator := survey.Required - if platform.GCP != nil { - validator = survey.ComposeValidators(validator, func(ans interface{}) error { return gcpvalidation.ValidateClusterName(ans.(string)) }) - } else if platform.Azure != nil { - validator = survey.ComposeValidators(validator, func(ans interface{}) error { return azurevalidation.ValidateClusterName(ans.(string)) }) + if platform.GCP != nil || platform.Azure != nil { + validator = survey.ComposeValidators(validator, func(ans interface{}) error { + return validate.ClusterName1035(ans.(string)) + }) } validator = survey.ComposeValidators(validator, func(ans interface{}) error { return validate.DomainName(validation.ClusterDomain(bd.BaseDomain, ans.(string)), false) diff --git a/pkg/types/azure/validation/platform.go b/pkg/types/azure/validation/platform.go index 2b5932e8da..d778973122 100644 --- a/pkg/types/azure/validation/platform.go +++ b/pkg/types/azure/validation/platform.go @@ -1,9 +1,6 @@ package validation import ( - "regexp" - - "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/validation/field" "github.com/openshift/installer/pkg/types" @@ -45,14 +42,3 @@ func ValidatePlatform(p *azure.Platform, publish types.PublishingStrategy, fldPa } return allErrs } - -// ValidateClusterName confirms that the provided cluster name matches Azure naming requirements. -func ValidateClusterName(clusterName string) error { - azureResourceFmt := `[a-z][a-z0-9-]{1,61}[a-z0-9]` - - re := regexp.MustCompile("^" + azureResourceFmt + "$") - if !re.MatchString(clusterName) { - return errors.Errorf("Azure requires cluster name to match regular expression %s", azureResourceFmt) - } - return nil -} diff --git a/pkg/types/gcp/validation/platform.go b/pkg/types/gcp/validation/platform.go index 7b6782cf2a..9f606b8851 100644 --- a/pkg/types/gcp/validation/platform.go +++ b/pkg/types/gcp/validation/platform.go @@ -1,10 +1,8 @@ package validation import ( - "regexp" "sort" - "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/validation/field" "github.com/openshift/installer/pkg/types/gcp" @@ -72,14 +70,3 @@ func ValidatePlatform(p *gcp.Platform, fldPath *field.Path) field.ErrorList { return allErrs } - -// ValidateClusterName confirms that the provided cluster name matches GCP naming requirements. -func ValidateClusterName(clusterName string) error { - gcpResourceFmt := `(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)` - - re := regexp.MustCompile("^" + gcpResourceFmt + "$") - if !re.MatchString(clusterName) { - return errors.Errorf("GCP requires cluster name to match regular expression %s", gcpResourceFmt) - } - return nil -} diff --git a/pkg/types/validation/installconfig.go b/pkg/types/validation/installconfig.go index 5674daa258..0453693c8e 100644 --- a/pkg/types/validation/installconfig.go +++ b/pkg/types/validation/installconfig.go @@ -63,11 +63,10 @@ func ValidateInstallConfig(c *types.InstallConfig, openStackValidValuesFetcher o } } nameErr := validate.ClusterName(c.ObjectMeta.Name) - if gcpNameErr := gcpvalidation.ValidateClusterName(c.ObjectMeta.Name); c.Platform.GCP != nil && gcpNameErr != nil { - allErrs = append(allErrs, field.Invalid(field.NewPath("metadata", "name"), c.ObjectMeta.Name, gcpNameErr.Error())) - } else if azureNameErr := azurevalidation.ValidateClusterName(c.ObjectMeta.Name); c.Platform.Azure != nil && azureNameErr != nil { - allErrs = append(allErrs, field.Invalid(field.NewPath("metadata", "name"), c.ObjectMeta.Name, azureNameErr.Error())) - } else if nameErr != nil { + if c.Platform.GCP != nil || c.Platform.Azure != nil { + nameErr = validate.ClusterName1035(c.ObjectMeta.Name) + } + if nameErr != nil { allErrs = append(allErrs, field.Invalid(field.NewPath("metadata", "name"), c.ObjectMeta.Name, nameErr.Error())) } baseDomainErr := validate.DomainName(c.BaseDomain, true) diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index 49b0981486..15345fb258 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -747,7 +747,7 @@ func TestValidateInstallConfig(t *testing.T) { c.ObjectMeta.Name = "1-invalid-cluster" return c }(), - expectedError: `^metadata\.name: Invalid value: "1-invalid-cluster": GCP requires cluster name to match regular expression \(\?:\[a-z\]\(\?:\[-a-z0-9\]\{0,61\}\[a-z0-9\]\)\?\)$`, + expectedError: `^metadata\.name: Invalid value: "1-invalid-cluster": cluster name must begin with a lower-case letter$`, }, { name: "release image source is not canonical", diff --git a/pkg/validate/validate.go b/pkg/validate/validate.go index e7b70a505d..3766a86e35 100644 --- a/pkg/validate/validate.go +++ b/pkg/validate/validate.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "net/url" + "regexp" "strings" uuid "github.com/google/uuid" @@ -97,6 +98,22 @@ func ImagePullSecret(secret string) error { return k8serrors.NewAggregate(errs) } +// ClusterName1035 checks the provided cluster name matches RFC1035 naming requirements. +// Some platform resource names must comply with RFC1035 "[a-z]([-a-z0-9]*[a-z0-9])?". They +// are based on the InfraID, which is a truncated version of the cluster name where all non- +// alphanumeric characters "[^A-Za-z0-9-]" have been replaced with dashes "-". As a result, +// if we first verify the name starts with a lower-case letter "^[a-z]" then we can rely on +// the ClusterName function to confirm compliance with the rest. The resulting name will +// therefore match RFC1035 with the exception of possible periods ".", which will be +// translated into dashes "-" in the InfraID before being used to create cloud resources. +func ClusterName1035(v string) error { + re := regexp.MustCompile("^[a-z]") + if !re.MatchString(v) { + return errors.New("cluster name must begin with a lower-case letter") + } + return ClusterName(v) +} + // ClusterName checks if the given string is a valid name for a cluster and returns an error if not. // The max length of the DNS label is `DNS1123LabelMaxLength + 9` because the public DNS zones have records // `api.clustername`, `*.apps.clustername`, and *.apps is rendered as the nine-character \052.apps in DNS records.