diff --git a/frontend/packages/console-shared/locales/en/console-shared.json b/frontend/packages/console-shared/locales/en/console-shared.json index f24adfc7c339..431ceb33e54f 100644 --- a/frontend/packages/console-shared/locales/en/console-shared.json +++ b/frontend/packages/console-shared/locales/en/console-shared.json @@ -297,7 +297,7 @@ "Set minAvailable to 25%": "Set minAvailable to 25%", "An eviction is allowed if at least 25% of pods selected by \"selector\" will still be available after the eviction.": "An eviction is allowed if at least 25% of pods selected by \"selector\" will still be available after the eviction.", "Helm Release": "Helm Release", - "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.": "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.", + "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.": "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.", "Cannot be longer than {{characterCount}} characters.": "Cannot be longer than {{characterCount}} characters.", "Required": "Required" -} \ No newline at end of file +} diff --git a/frontend/packages/console-shared/src/utils/__tests__/yup-validations.spec.ts b/frontend/packages/console-shared/src/utils/__tests__/yup-validations.spec.ts index 449ac4fb5d10..dc30d24693c9 100644 --- a/frontend/packages/console-shared/src/utils/__tests__/yup-validations.spec.ts +++ b/frontend/packages/console-shared/src/utils/__tests__/yup-validations.spec.ts @@ -2,18 +2,31 @@ import { nameRegex } from '../yup-validations'; describe('nameRegex', () => { it('should match valid resource names', () => { - const validNames = ['appname', 'app-name', 'app-name123', 'app-name123-app']; + const validNames = [ + 'appname', + 'app-name', + 'app-name123', + 'app-name123-app', + 'app--name', + 'app-name.1', + 'app.name.1', + 'app-name-1', + '4appname', + ]; validNames.forEach((name) => expect(name).toMatch(nameRegex)); }); it('should not match invalid resource names', () => { const invalidNames = [ 'AppName', - '4appname', '-app-name', 'app$name!', 'app name', - 'app--name', + 'app.-name', + 'app-.name', + 'app..name', + 'app-name-', + 'app.name.', '', '-', ]; diff --git a/frontend/packages/console-shared/src/utils/yup-validations.ts b/frontend/packages/console-shared/src/utils/yup-validations.ts index d4f2de55cc4a..846c53dfcd9b 100644 --- a/frontend/packages/console-shared/src/utils/yup-validations.ts +++ b/frontend/packages/console-shared/src/utils/yup-validations.ts @@ -1,13 +1,15 @@ import { TFunction } from 'i18next'; import * as yup from 'yup'; -export const nameRegex = /^[a-z]([a-z0-9]-?)*[a-z0-9]$/; +// eslint-disable-next-line no-useless-escape +export const nameRegex = /^[a-z0-9](?!.*\.\.)(?!.*-\.)(?!.*\.-)[a-z0-9\.-]*[a-z0-9]$/; +export const containerNameRegex = /^[a-z]([a-z0-9]-?)*[a-z0-9]$/; export const nameValidationSchema = (t: TFunction, maxLength = 263) => yup .string() .matches(nameRegex, { message: t( - 'console-shared~Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'console-shared~Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ), excludeEmptyString: true, }) diff --git a/frontend/packages/dev-console/locales/en/devconsole.json b/frontend/packages/dev-console/locales/en/devconsole.json index 5f392b3793bb..bedf7f19ff6c 100644 --- a/frontend/packages/dev-console/locales/en/devconsole.json +++ b/frontend/packages/dev-console/locales/en/devconsole.json @@ -352,7 +352,7 @@ "This is not a supported in-context type": "This is not a supported in-context type", "{{label}} Utilization": "{{label}} Utilization", "{{label}} request and limit must be set before {{label}} utilization can be set.": "{{label}} request and limit must be set before {{label}} utilization can be set.", - "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.": "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.", + "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.": "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.", "Cannot be longer than 253 characters.": "Cannot be longer than 253 characters.", "Minimum Pods must be an integer.": "Minimum Pods must be an integer.", "Minimum Pods must greater than or equal to 1.": "Minimum Pods must greater than or equal to 1.", diff --git a/frontend/packages/dev-console/src/components/hpa/validation-utils.ts b/frontend/packages/dev-console/src/components/hpa/validation-utils.ts index 38d33c39afd3..aeb5debeb806 100644 --- a/frontend/packages/dev-console/src/components/hpa/validation-utils.ts +++ b/frontend/packages/dev-console/src/components/hpa/validation-utils.ts @@ -14,7 +14,7 @@ export const hpaValidationSchema = (t: TFunction) => .string() .matches(nameRegex, { message: t( - 'devconsole~Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'devconsole~Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ), excludeEmptyString: true, }) diff --git a/frontend/packages/dev-console/src/components/import/__tests__/deployImage-validation-utils.spec.ts b/frontend/packages/dev-console/src/components/import/__tests__/deployImage-validation-utils.spec.ts index a88f1f387dac..ad1d3d2dcda1 100644 --- a/frontend/packages/dev-console/src/components/import/__tests__/deployImage-validation-utils.spec.ts +++ b/frontend/packages/dev-console/src/components/import/__tests__/deployImage-validation-utils.spec.ts @@ -38,7 +38,7 @@ describe('Deploy Image ValidationUtils', () => { .validate(mockData) .catch((err) => { expect(err.message).toBe( - 'Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ); }); }); diff --git a/frontend/packages/dev-console/src/components/import/__tests__/import-validation-utils.spec.ts b/frontend/packages/dev-console/src/components/import/__tests__/import-validation-utils.spec.ts index d255a6870de9..bd2c7495e8a9 100644 --- a/frontend/packages/dev-console/src/components/import/__tests__/import-validation-utils.spec.ts +++ b/frontend/packages/dev-console/src/components/import/__tests__/import-validation-utils.spec.ts @@ -45,7 +45,7 @@ describe('ValidationUtils', () => { describe('createComponentName', () => { const invalidConvertedtoValidNamePair: { [key: string]: string } = { '-2name': 'ocp-2-name', - '0name': 'ocp-0-name', + '.0name': 'ocp-0-name', Name: 'name', '-name': 'name', 'name-': 'name', @@ -153,7 +153,7 @@ describe('ValidationUtils', () => { ).toEqual('wild-west-frontend'); expect( detectGitRepoName('https://github.com/openshift-evangelists/wild-west-frontend.git'), - ).toEqual('wild-west-frontend-git'); + ).toEqual('wild-west-frontend.git'); expect( detectGitRepoName('https://github.com/openshift-evangelists/Wild-West-Frontend123'), ).toEqual('wild-west-frontend-123'); @@ -175,7 +175,7 @@ describe('ValidationUtils', () => { .validate(mockData) .catch((err) => { expect(err.message).toBe( - 'Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ); }); }); diff --git a/frontend/packages/dev-console/src/components/import/deployImage-submit-utils.ts b/frontend/packages/dev-console/src/components/import/deployImage-submit-utils.ts index 0300081f3bcf..eb5938aebaec 100644 --- a/frontend/packages/dev-console/src/components/import/deployImage-submit-utils.ts +++ b/frontend/packages/dev-console/src/components/import/deployImage-submit-utils.ts @@ -32,6 +32,7 @@ import { createRoute, createService, dryRunOpt } from '../../utils/shared-submit import { AppResources } from '../edit-application/edit-application-types'; import { getProbesData } from '../health-checks/create-health-checks-probe-utils'; import { DeployImageFormData, Resources } from './import-types'; +import { createContainerName } from './import-validation-utils'; const WAIT_FOR_IMAGESTREAM_UPDATE_TIMEOUT = 5000; const WAIT_FOR_IMAGESTREAM_GENERATION = 2; @@ -212,7 +213,7 @@ export const createOrUpdateDeployment = ( volumes, containers: [ { - name, + name: createContainerName(name), image: imageRef, ports, volumeMounts, @@ -279,7 +280,7 @@ export const createOrUpdateDeploymentConfig = ( volumes, containers: [ { - name, + name: createContainerName(name), image: _.get(image, ['dockerImageMetadata', 'Config', 'Image']), ports, volumeMounts, diff --git a/frontend/packages/dev-console/src/components/import/import-submit-utils.ts b/frontend/packages/dev-console/src/components/import/import-submit-utils.ts index 190894135e14..ac1b55f9294f 100644 --- a/frontend/packages/dev-console/src/components/import/import-submit-utils.ts +++ b/frontend/packages/dev-console/src/components/import/import-submit-utils.ts @@ -72,6 +72,7 @@ import { ServerlessData, DeploymentData, } from './import-types'; +import { createContainerName } from './import-validation-utils'; export const generateSecret = () => { // http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript @@ -366,7 +367,7 @@ export const createOrUpdateDeployment = ( spec: { containers: [ { - name, + name: createContainerName(name), image: `${name}:latest`, ports, env, @@ -433,7 +434,7 @@ export const createOrUpdateDeploymentConfig = ( spec: { containers: [ { - name, + name: createContainerName(name), image: `${name}:latest`, ports, env, diff --git a/frontend/packages/dev-console/src/components/import/import-validation-utils.ts b/frontend/packages/dev-console/src/components/import/import-validation-utils.ts index 35d88c0b4777..ff7fa43b9ae3 100644 --- a/frontend/packages/dev-console/src/components/import/import-validation-utils.ts +++ b/frontend/packages/dev-console/src/components/import/import-validation-utils.ts @@ -2,7 +2,7 @@ import { TFunction } from 'i18next'; import * as _ from 'lodash'; import * as yup from 'yup'; import { GitProvider } from '@console/git-service/src'; -import { nameValidationSchema, nameRegex } from '@console/shared'; +import { nameValidationSchema, nameRegex, containerNameRegex } from '@console/shared'; import { healthChecksProbesValidationSchema } from '../health-checks/health-checks-probe-validation-utils'; import { projectNameValidationSchema, @@ -75,6 +75,17 @@ export const createComponentName = (nameString: string): string => { : kebabCaseStr; }; +export const createContainerName = (nameString: string): string => { + if (containerNameRegex.test(nameString)) { + return nameString; + } + + const kebabCaseStr = _.kebabCase(nameString); + return nameString.match(/^\d/) || kebabCaseStr.match(/^\d/) + ? `ocp-${kebabCaseStr}` + : kebabCaseStr; +}; + export const detectGitRepoName = (url: string): string | undefined => { if (!gitUrlRegex.test(url)) { return undefined; diff --git a/frontend/packages/helm-plugin/locales/en/helm-plugin.json b/frontend/packages/helm-plugin/locales/en/helm-plugin.json index 8f8755139d07..f98d1ceaed16 100644 --- a/frontend/packages/helm-plugin/locales/en/helm-plugin.json +++ b/frontend/packages/helm-plugin/locales/en/helm-plugin.json @@ -88,7 +88,7 @@ "TLS Client config": "TLS Client config", "Select Secret": "Select Secret", "Edit Helm Chart Repository": "Edit Helm Chart Repository", - "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.": "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.", + "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.": "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.", "The repository name cannot exceed than 100 characters.": "The repository name cannot exceed than 100 characters.", "Required": "Required", "The repository name cannot exceed than 2048 characters.": "The repository name cannot exceed than 2048 characters.", diff --git a/frontend/packages/helm-plugin/src/components/forms/HelmChartRepository/helmchartrepository-validation-utils.ts b/frontend/packages/helm-plugin/src/components/forms/HelmChartRepository/helmchartrepository-validation-utils.ts index c86dc9829909..960a1f54df47 100644 --- a/frontend/packages/helm-plugin/src/components/forms/HelmChartRepository/helmchartrepository-validation-utils.ts +++ b/frontend/packages/helm-plugin/src/components/forms/HelmChartRepository/helmchartrepository-validation-utils.ts @@ -12,7 +12,7 @@ export const createHelmChartRepositoryValidationSchema = (t: TFunction) => .string() .matches(nameRegex, { message: t( - 'helm-plugin~Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'helm-plugin~Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ), excludeEmptyString: true, }) diff --git a/frontend/packages/pipelines-plugin/locales/en/pipelines-plugin.json b/frontend/packages/pipelines-plugin/locales/en/pipelines-plugin.json index 4555b0749821..aa50ae075d43 100644 --- a/frontend/packages/pipelines-plugin/locales/en/pipelines-plugin.json +++ b/frontend/packages/pipelines-plugin/locales/en/pipelines-plugin.json @@ -347,7 +347,7 @@ "Pipeline Repositories": "Pipeline Repositories", "Event type": "Event type", "Last run duration": "Last run duration", - "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.": "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.", + "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.": "Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.", "Invalid Git URL.": "Invalid Git URL.", "Repository details": "Repository details", "Git access token": "Git access token", diff --git a/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/switch-to-form-validation-utils.spec.ts b/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/switch-to-form-validation-utils.spec.ts index 8662261e6456..a27fbaf9f603 100644 --- a/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/switch-to-form-validation-utils.spec.ts +++ b/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/switch-to-form-validation-utils.spec.ts @@ -208,7 +208,7 @@ describe('Tasks validation', () => { .catch( hasError( 'spec.tasks[0].name', - 'Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ), ); }); diff --git a/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/validation-utils.spec.ts b/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/validation-utils.spec.ts index edc496e1475b..02db92b7d66d 100644 --- a/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/validation-utils.spec.ts +++ b/frontend/packages/pipelines-plugin/src/components/pipelines/pipeline-builder/__tests__/validation-utils.spec.ts @@ -64,7 +64,7 @@ describe('Pipeline Build validation schema', () => { .catch( hasError( 'formData.name', - 'Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ), ); }); diff --git a/frontend/packages/pipelines-plugin/src/components/repository/repository-form-utils.ts b/frontend/packages/pipelines-plugin/src/components/repository/repository-form-utils.ts index 81683bb06996..ba178906ea23 100644 --- a/frontend/packages/pipelines-plugin/src/components/repository/repository-form-utils.ts +++ b/frontend/packages/pipelines-plugin/src/components/repository/repository-form-utils.ts @@ -29,7 +29,7 @@ export const repositoryValidationSchema = (t: TFunction) => .string() .matches(nameRegex, { message: t( - 'pipelines-plugin~Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.', + 'pipelines-plugin~Name must consist of lower case alphanumeric characters, hyphens or dots, and must start and end with an alphanumeric character.', ), excludeEmptyString: true, })