Skip to content

Commit 4b8ac71

Browse files
authored
Update DefaultResourcesNameStep (#634)
1 parent 0fd000a commit 4b8ac71

File tree

6 files changed

+45
-344
lines changed

6 files changed

+45
-344
lines changed

extension.bundle.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
export * from '@microsoft/vscode-azext-utils';
1818
// Export activate/deactivate for main.js
1919
export * from './src/commands/deployWorkspaceProject/DeployWorkspaceProjectContext';
20-
export * from './src/commands/deployWorkspaceProject/internal/DefaultResourcesNameStep';
2120
export * from './src/commands/ingress/IngressContext';
2221
export * from './src/commands/ingress/IngressPromptStep';
2322
export * from './src/commands/ingress/editTargetPort/getDefaultPort';

src/commands/createManagedEnvironment/ManagedEnvironmentNameStep.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class ManagedEnvironmentNameStep extends AzureWizardPromptStep<IManagedEn
1414
const prompt: string = localize('containerAppNamePrompt', 'Enter a container apps environment name.');
1515
context.newManagedEnvironmentName = (await context.ui.showInputBox({
1616
prompt,
17-
validateInput: this.validateInput,
17+
validateInput: ManagedEnvironmentNameStep.validateInput,
1818
asyncValidationTask: (name: string) => this.validateNameAvailable(context, name)
1919
})).trim();
2020

@@ -25,7 +25,7 @@ export class ManagedEnvironmentNameStep extends AzureWizardPromptStep<IManagedEn
2525
return !context.managedEnvironment && !context.newManagedEnvironmentName;
2626
}
2727

28-
private validateInput(name: string | undefined): string | undefined {
28+
public static validateInput(name: string | undefined): string | undefined {
2929
name = name ? name.trim() : '';
3030

3131
const { minLength, maxLength } = { minLength: 4, maxLength: 20 };

src/commands/deployWorkspaceProject/internal/DefaultResourcesNameStep.ts

Lines changed: 41 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,83 +4,72 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { ResourceGroupListStep } from "@microsoft/vscode-azext-azureutils";
7-
import { AzureWizardPromptStep, nonNullValueAndProp } from "@microsoft/vscode-azext-utils";
7+
import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils";
88
import { ProgressLocation, window } from "vscode";
99
import { ext } from "../../../extensionVariables";
1010
import { localize } from "../../../utils/localize";
11-
import { validateUtils } from "../../../utils/validateUtils";
1211
import { ContainerAppNameStep } from "../../createContainerApp/ContainerAppNameStep";
1312
import { ManagedEnvironmentNameStep } from "../../createManagedEnvironment/ManagedEnvironmentNameStep";
1413
import { ImageNameStep } from "../../image/imageSource/buildImageInAzure/ImageNameStep";
1514
import { RegistryNameStep } from "../../image/imageSource/containerRegistry/acr/createAcr/RegistryNameStep";
16-
import { type DeployWorkspaceProjectContext } from "../DeployWorkspaceProjectContext";
15+
import { type DeployWorkspaceProjectInternalContext } from "./deployWorkspaceProjectInternal";
1716

18-
export class DefaultResourcesNameStep extends AzureWizardPromptStep<DeployWorkspaceProjectContext> {
19-
public async prompt(context: DeployWorkspaceProjectContext): Promise<void> {
20-
ext.outputChannel.appendLog(localize('resourceNameUnavailable',
21-
'Info: Some container app resources matching the workspace name "{0}" were invalid or unavailable.',
22-
cleanWorkspaceName(nonNullValueAndProp(context.rootFolder, 'name')))
23-
);
24-
25-
const resourceBaseName: string = (await context.ui.showInputBox({
17+
export class DefaultResourcesNameStep extends AzureWizardPromptStep<DeployWorkspaceProjectInternalContext> {
18+
public async prompt(context: DeployWorkspaceProjectInternalContext): Promise<void> {
19+
const resourceName: string = (await context.ui.showInputBox({
2620
prompt: localize('resourceBaseNamePrompt', 'Enter a name for the new container app resource(s).'),
27-
validateInput: this.validateInput,
21+
validateInput: (name: string) => this.validateInput(context, name),
2822
asyncValidationTask: (name: string) => this.validateNameAvailability(context, name)
2923
})).trim();
3024

31-
ext.outputChannel.appendLog(localize('usingResourceName', 'User provided the new resource name "{0}" as the default for resource creation.', resourceBaseName))
32-
33-
!context.resourceGroup && (context.newResourceGroupName = resourceBaseName);
34-
!context.managedEnvironment && (context.newManagedEnvironmentName = resourceBaseName);
35-
!context.containerApp && (context.newContainerAppName = resourceBaseName);
36-
context.imageName = ImageNameStep.getTimestampedImageName(context.containerApp?.name || resourceBaseName);
37-
}
38-
39-
public async configureBeforePrompt(context: DeployWorkspaceProjectContext): Promise<void> {
40-
const workspaceName: string = cleanWorkspaceName(nonNullValueAndProp(context.rootFolder, 'name'));
41-
if (this.validateInput(workspaceName) !== undefined) {
42-
context.telemetry.properties.promptDefaultNameReason = 'invalid';
43-
return;
44-
}
45-
46-
if (!await this.isWorkspaceNameAvailable(context, workspaceName)) {
47-
context.telemetry.properties.promptDefaultNameReason = 'unavailable';
48-
return;
49-
}
50-
51-
if (!context.resourceGroup || !context.managedEnvironment || !context.registry || !context.containerApp) {
52-
ext.outputChannel.appendLog(localize('usingWorkspaceName', 'Using workspace name "{0}" as the default for remaining resource creation.', workspaceName));
53-
}
25+
ext.outputChannel.appendLog(localize('usingResourceName', 'User provided the new resource name "{0}" as the default for resource creation.', resourceName))
5426

55-
!context.resourceGroup && (context.newResourceGroupName = workspaceName);
56-
!context.managedEnvironment && (context.newManagedEnvironmentName = workspaceName);
57-
!context.registry && (context.newRegistryName = await RegistryNameStep.tryGenerateRelatedName(context, workspaceName));
58-
!context.containerApp && (context.newContainerAppName = workspaceName);
59-
context.imageName = ImageNameStep.getTimestampedImageName(context.containerApp?.name || workspaceName);
27+
!context.resourceGroup && (context.newResourceGroupName = resourceName);
28+
!context.managedEnvironment && (context.newManagedEnvironmentName = resourceName);
29+
!context.containerApp && (context.newContainerAppName = resourceName);
30+
context.imageName = ImageNameStep.getTimestampedImageName(context.containerApp?.name || resourceName);
6031
}
6132

62-
public shouldPrompt(context: DeployWorkspaceProjectContext): boolean {
33+
public shouldPrompt(context: DeployWorkspaceProjectInternalContext): boolean {
6334
return (!context.resourceGroup && !context.newResourceGroupName) ||
6435
(!context.managedEnvironment && !context.newManagedEnvironmentName) ||
65-
(!context.registry && !context.newRegistryName) ||
66-
(!context.containerApp && !context.newContainerAppName);
36+
(!context.containerApp && !context.newContainerAppName) ||
37+
!context.registry;
6738
}
6839

69-
private validateInput(name: string = ''): string | undefined {
40+
private validateInput(context: DeployWorkspaceProjectInternalContext, name: string = ''): string | undefined {
7041
name = name.trim();
7142

72-
// No symbols are allowed for ACR - we will strip out any offending characters from the base name, but still need to ensure this version has an appropriate length
73-
const nameWithoutSymbols: string = name.replace(/[^a-z0-9]+/g, '');
74-
if (!validateUtils.isValidLength(nameWithoutSymbols, 5, 20)) {
75-
return localize('invalidLength', 'The alphanumeric portion of the name must be least 5 characters but no more than 20 characters.');
43+
// ** Sorted from _most_ to _least_ strict naming rules, with priority being most strict character length since that usually gets checked first **
44+
// ** This sorting should help to minimize the possibility of conflicting validate input error messages which could be confusing for users **
45+
46+
if (!context.managedEnvironment && !context.newManagedEnvironmentName) {
47+
const result = ManagedEnvironmentNameStep.validateInput(name);
48+
if (result) {
49+
return result;
50+
}
51+
}
52+
53+
if (!context.containerApp && !context.newContainerAppName) {
54+
const result = ContainerAppNameStep.validateInput(name);
55+
if (result) {
56+
return result;
57+
}
58+
}
59+
60+
if (!context.registry) { // Skip checking newRegistryName since it gets set every time validateNameAvailability is run
61+
// No symbols are allowed for ACR names
62+
const nameWithoutSymbols: string = name.replace(/[^a-z0-9]+/g, '');
63+
const result = RegistryNameStep.validateInput(nameWithoutSymbols);
64+
if (result) {
65+
return result;
66+
}
7667
}
7768

78-
// Container app names currently have the strictest name formatting logic at the time of writing this
79-
// Todo: https://github.com/microsoft/vscode-azurecontainerapps/issues/603
80-
return ContainerAppNameStep.validateInput(name);
69+
return undefined;
8170
}
8271

83-
protected async validateNameAvailability(context: DeployWorkspaceProjectContext, name: string): Promise<string | undefined> {
72+
protected async validateNameAvailability(context: DeployWorkspaceProjectInternalContext, name: string): Promise<string | undefined> {
8473
return await window.withProgress({
8574
location: ProgressLocation.Notification,
8675
cancellable: false,
@@ -92,7 +81,6 @@ export class DefaultResourcesNameStep extends AzureWizardPromptStep<DeployWorksp
9281
// Skip check, one already exists so don't need to worry about naming
9382
} else {
9483
context.newRegistryName = await RegistryNameStep.tryGenerateRelatedName(context, name);
95-
9684
if (!context.newRegistryName) {
9785
return localize('timeoutError', 'Timed out waiting for registry name to be generated. Please try another name.');
9886
}
@@ -124,40 +112,4 @@ export class DefaultResourcesNameStep extends AzureWizardPromptStep<DeployWorksp
124112
return undefined;
125113
});
126114
}
127-
128-
protected async isWorkspaceNameAvailable(context: DeployWorkspaceProjectContext, workspaceName: string): Promise<boolean> {
129-
const isAvailable: Record<string, boolean> = {};
130-
131-
if (context.resourceGroup || await ResourceGroupListStep.isNameAvailable(context, workspaceName)) {
132-
isAvailable['resourceGroup'] = true;
133-
}
134-
135-
if (context.managedEnvironment || await ManagedEnvironmentNameStep.isNameAvailable(context, context.resourceGroup?.name ?? workspaceName, workspaceName)) {
136-
isAvailable['managedEnvironment'] = true;
137-
}
138-
139-
if (context.containerApp || await ContainerAppNameStep.isNameAvailable(context, context.resourceGroup?.name ?? workspaceName, workspaceName)) {
140-
isAvailable['containerApp'] = true;
141-
}
142-
143-
return isAvailable['resourceGroup'] && isAvailable['managedEnvironment'] && isAvailable['containerApp'];
144-
}
145-
}
146-
147-
export function cleanWorkspaceName(workspaceName: string): string {
148-
// Only alphanumeric characters or hyphens
149-
let cleanedWorkspaceName: string = workspaceName.toLowerCase().replace(/[^a-z0-9-]+/g, '');
150-
151-
// Remove any consecutive hyphens
152-
cleanedWorkspaceName = cleanedWorkspaceName.replace(/-+/g, '-');
153-
154-
// Remove any leading or ending hyphens
155-
if (cleanedWorkspaceName.startsWith('-')) {
156-
cleanedWorkspaceName = cleanedWorkspaceName.slice(1);
157-
}
158-
if (cleanedWorkspaceName.endsWith('-')) {
159-
cleanedWorkspaceName = cleanedWorkspaceName.slice(0, -1);
160-
}
161-
162-
return cleanedWorkspaceName;
163115
}

src/commands/image/imageSource/containerRegistry/acr/createAcr/RegistryNameStep.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class RegistryNameStep extends AzureWizardPromptStep<CreateAcrContext> {
1414
public async prompt(context: CreateAcrContext): Promise<void> {
1515
context.newRegistryName = await context.ui.showInputBox({
1616
prompt: localize('registryName', 'Enter a name for the new registry'),
17-
validateInput: this.validateInput,
17+
validateInput: RegistryNameStep.validateInput,
1818
asyncValidationTask: (value: string): Promise<string | undefined> => this.validateNameAvalability(context, value)
1919
});
2020
}
@@ -23,7 +23,7 @@ export class RegistryNameStep extends AzureWizardPromptStep<CreateAcrContext> {
2323
return !context.newRegistryName;
2424
}
2525

26-
private validateInput(name: string | undefined): string | undefined {
26+
public static validateInput(name: string | undefined): string | undefined {
2727
name = name ? name.trim() : '';
2828

2929
const { minLength, maxLength } = { minLength: 5, maxLength: 50 };

0 commit comments

Comments
 (0)