Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…inerapps into mwf/unpleasant-white
  • Loading branch information
MicroFish91 committed Jan 22, 2025
2 parents 48899f1 + b21c44b commit 2542c3a
Show file tree
Hide file tree
Showing 42 changed files with 337 additions and 63 deletions.
1 change: 1 addition & 0 deletions extension.bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export * from './src/commands/deployWorkspaceProject/settings/DeployWorkspacePro
export * from './src/commands/deployWorkspaceProject/settings/dwpSettingUtilsV1';
export * from './src/commands/deployWorkspaceProject/settings/dwpSettingUtilsV2';
export * from './src/commands/IContainerAppContext';
export * from './src/commands/image/imageSource/containerRegistry/acr/createAcr/createAcr';
export * from './src/commands/ingress/editTargetPort/getDefaultPort';
export * from './src/commands/ingress/IngressContext';
export * from './src/commands/ingress/IngressPromptStep';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class ShouldSaveDeploySettingsPromptStep extends AzureWizardPromptStep<De
} else if (context.envPath === '') {
hasNewEnvPath = setting?.envPath !== useRemoteConfigurationKey;
} else {
hasNewEnvPath = context.envPath !== setting?.envPath;
hasNewEnvPath = false;
}

const hasNewResourceGroupSetting: boolean = (!!context.newResourceGroupName && setting?.resourceGroup !== context.newResourceGroupName) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type Container } from "@azure/arm-appcontainers";
import { type Container, type EnvironmentVar } from "@azure/arm-appcontainers";
import { nonNullProp } from "@microsoft/vscode-azext-utils";
import { type Progress } from "vscode";
import { type ContainerAppItem } from "../../../tree/ContainerAppItem";
import { type RevisionsItemModel } from "../../../tree/revisionManagement/RevisionItem";
Expand All @@ -21,10 +22,19 @@ export class EnvironmentVariablesEditDraftStep<T extends EnvironmentVariablesEdi
public async execute(context: T, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
progress.report({ message: localize('editingEnv', 'Editing environment variables (draft)...') });
this.revisionDraftTemplate.containers ??= [];

const container: Container = this.revisionDraftTemplate.containers[context.containersIdx] ?? {};
container.env = context.environmentVariables;

const envMap: Map<string, EnvironmentVar> = new Map();
// Set current environment variables
for (const env of container.env ?? []) {
envMap.set(nonNullProp(env, 'name'), env);
}
// Add new environment variables
for (const env of context.environmentVariables ?? []) {
envMap.set(nonNullProp(env, 'name'), env);
}

container.env = Array.from(envMap.values());
await this.updateRevisionDraftWithTemplate(context);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
* Licensed under the MIT License. See License.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type Registry } from "@azure/arm-containerregistry";
import { LocationListStep, ResourceGroupCreateStep } from "@microsoft/vscode-azext-azureutils";
import { AzureWizard, createSubscriptionContext, nonNullValue, subscriptionExperience, type AzureWizardExecuteStep, type AzureWizardPromptStep, type IActionContext } from "@microsoft/vscode-azext-utils";
import { AzureWizard, createSubscriptionContext, nonNullProp, nonNullValue, subscriptionExperience, type AzureWizardExecuteStep, type AzureWizardPromptStep, type IActionContext } from "@microsoft/vscode-azext-utils";
import { type AzureSubscription } from "@microsoft/vscode-azureresources-api";
import { ext } from "../../../../../../extensionVariables";
import { createActivityContext } from "../../../../../../utils/activityUtils";
Expand All @@ -15,7 +16,7 @@ import { RegistryCreateStep } from "./RegistryCreateStep";
import { RegistryNameStep } from "./RegistryNameStep";
import { SkuListStep } from "./SkuListStep";

export async function createAcr(context: IActionContext, node?: { subscription: AzureSubscription }): Promise<void> {
export async function createAcr(context: IActionContext, node?: { subscription: AzureSubscription }): Promise<Registry> {
const subscription = node?.subscription ?? await subscriptionExperience(context, ext.rgApiV2.resources.azureResourceTreeDataProvider);

const wizardContext: CreateAcrContext = {
Expand Down Expand Up @@ -52,4 +53,5 @@ export async function createAcr(context: IActionContext, node?: { subscription:
wizardContext.activityTitle = localize('createAcr', 'Create Azure Container Registry "{0}"', wizardContext.newRegistryName);

await wizard.execute();
return nonNullProp(wizardContext, 'registry');
}
4 changes: 2 additions & 2 deletions test/global.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import * as assert from 'assert';
import * as vscode from 'vscode';
import { ext, registerOnActionStartHandler, registerUIExtensionVariables } from '../extension.bundle';

const longRunningLocalTestsEnabled: boolean = !/^(false|0)?$/i.test(process.env.AzCode_EnableLongRunningTestsLocal || '');
const longRunningRemoteTestsEnabled: boolean = !/^(false|0)?$/i.test(process.env.AzCode_UseAzureFederatedCredentials || '');
export const longRunningLocalTestsEnabled: boolean = !/^(false|0)?$/i.test(process.env.AzCode_EnableLongRunningTestsLocal || '');
export const longRunningRemoteTestsEnabled: boolean = !/^(false|0)?$/i.test(process.env.AzCode_UseAzureFederatedCredentials || '');

export const longRunningTestsEnabled: boolean = longRunningLocalTestsEnabled || longRunningRemoteTestsEnabled;

Expand Down
4 changes: 2 additions & 2 deletions test/nightly/deployWorkspaceProject/buildParallelScenarios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { workspace, type Uri, type WorkspaceFolder } from "vscode";
import { AzExtFsExtra, deployWorkspaceProject, dwpSettingUtilsV2, ext, parseError, settingUtils, type DeploymentConfigurationSettings, type DeployWorkspaceProjectResults, type IParsedError } from "../../../extension.bundle";
import { assertStringPropsMatch, getWorkspaceFolderUri } from "../../testUtils";
import { resourceGroupsToDelete } from "../global.nightly.test";
import { dwpTestScenarios, type DeployWorkspaceProjectTestScenario } from "./dwpTestScenarios";
import { getDwpTestScenarios, type DeployWorkspaceProjectTestScenario } from "./dwpTestScenarios";

export interface DwpParallelTestScenario {
title: string;
Expand All @@ -19,7 +19,7 @@ export interface DwpParallelTestScenario {
}

export function buildParallelTestScenarios(): DwpParallelTestScenario[] {
return dwpTestScenarios.map(scenario => {
return getDwpTestScenarios().map(scenario => {
return {
title: scenario.label,
callback: buildParallelScenarioCallback(scenario),
Expand Down
34 changes: 27 additions & 7 deletions test/nightly/deployWorkspaceProject/deployWorkspaceProject.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/

import { type ManagedEnvironment } from "@azure/arm-appcontainers";
import { type Registry } from "@azure/arm-containerregistry";
import { runWithTestActionContext } from "@microsoft/vscode-azext-dev";
import { nonNullProp, randomUtils } from "@microsoft/vscode-azext-utils";
import * as assert from "assert";
import { createManagedEnvironment } from "../../../extension.bundle";
import { createAcr, createManagedEnvironment } from "../../../extension.bundle";
import { longRunningTestsEnabled } from '../../global.test';
import { resourceGroupsToDelete } from "../global.nightly.test";
import { buildParallelTestScenarios, type DwpParallelTestScenario } from './buildParallelScenarios';
Expand All @@ -23,10 +24,10 @@ suite('deployWorkspaceProject', async function (this: Mocha.Suite) {
this.skip();
}

// Create a managed environment first so that we can guarantee one is always built before workspace deployment tests start.
// This is crucial for test consistency because the managed environment prompt will skip if no managed environment
// resources are available yet. Creating at least one environment first ensures consistent reproduceability.
setupTask = setupManagedEnvironment();
// Create a container registry & managed environment first so that we can guarantee one is always built before workspace deployment tests start.
// This is crucial for test consistency because some resource prompts will skip if no existing resources exist to choose from
// Creating at least one of each resource first ensures consistent reproduceability.
setupTask = setupResources();

for (const s of testScenarios) {
s.scenario = s.callback(setupTask);
Expand All @@ -40,10 +41,11 @@ suite('deployWorkspaceProject', async function (this: Mocha.Suite) {
}
});

async function setupManagedEnvironment(): Promise<void> {
async function setupResources(): Promise<void> {
let envResourceTask: Promise<void> | undefined;
let managedEnvironment: ManagedEnvironment | undefined;
try {
await runWithTestActionContext('createManagedEnvironment', async context => {
envResourceTask = runWithTestActionContext('createManagedEnvironment', async context => {
const resourceName: string = 'dwp' + randomUtils.getRandomHexString(6);
await context.ui.runWithInputs([resourceName, 'East US'], async () => {
managedEnvironment = await createManagedEnvironment(context);
Expand All @@ -53,6 +55,24 @@ async function setupManagedEnvironment(): Promise<void> {
console.error(e);
}

let acrResourceTask: Promise<void> | undefined;
let registry: Registry | undefined;
try {
acrResourceTask = runWithTestActionContext('createContainerRegistry', async context => {
const resourceName: string = 'dwp' + randomUtils.getRandomHexString(6);
await context.ui.runWithInputs([resourceName, 'Basic', 'East US'], async () => {
registry = await createAcr(context);
});
});
} catch (e) {
console.error(e);
}

await Promise.allSettled([envResourceTask, acrResourceTask]);

assert.ok(managedEnvironment, 'Failed to create managed environment - skipping "deployWorkspaceProject" tests.');
resourceGroupsToDelete.add(nonNullProp(managedEnvironment, 'name'));

assert.ok(registry, 'Failed to create container registry - skipping "deployWorkspaceProject" tests.');
resourceGroupsToDelete.add(nonNullProp(registry, 'name'));
}
43 changes: 30 additions & 13 deletions test/nightly/deployWorkspaceProject/dwpTestScenarios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,42 @@
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { longRunningLocalTestsEnabled } from "../../global.test";
import { generateAlbumApiJavaScriptTestCases } from "./testCases/albumApiJavaScriptTestCases";
import { type DeployWorkspaceProjectTestCase } from "./testCases/DeployWorkspaceProjectTestCase";
import { generateMonoRepoBasicTestCases } from "./testCases/monoRepoBasicTestCases";
import { generateMonoRepoAdminCredentialsTestCases } from "./testCases/monoRepoTestCases/adminCredentialsTestCases";
import { generateMonoRepoIdentityTestCases } from "./testCases/monoRepoTestCases/identityTestCases";

export interface DeployWorkspaceProjectTestScenario {
label: string;
folderName: string;
testCases: DeployWorkspaceProjectTestCase[];
}

export const dwpTestScenarios: DeployWorkspaceProjectTestScenario[] = [
{
label: 'albumapi-js',
folderName: 'albumapi-js',
testCases: generateAlbumApiJavaScriptTestCases()
},
{
label: 'monorepo',
folderName: 'monorepo-basic',
testCases: generateMonoRepoBasicTestCases()
},
];
export function getDwpTestScenarios(): DeployWorkspaceProjectTestScenario[] {
const dwpTestScenarios: DeployWorkspaceProjectTestScenario[] = [
{
label: 'albumapi-js',
folderName: 'albumapi-js',
testCases: generateAlbumApiJavaScriptTestCases(),
},
{
label: 'monorepo-admincreds',
folderName: 'monorepo-admincreds',
testCases: generateMonoRepoAdminCredentialsTestCases(),
},
];

if (longRunningLocalTestsEnabled) {
// Insufficient auth privilege to test managed identity / role assignment in our manual testing subscription.
// Therefore, limit these tests to only run locally in personal subscriptions where user has full permission to assign roles.
// Todo: Investigate if it makes sense to elevate remote privileges such that these tests can also be automated to run remotely.
dwpTestScenarios.push({
label: 'monorepo-identity',
folderName: 'monorepo-identity',
testCases: generateMonoRepoIdentityTestCases(),
});
}

return dwpTestScenarios;
}
16 changes: 15 additions & 1 deletion test/nightly/deployWorkspaceProject/dwpTestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { subscriptionContext } from "../global.nightly.test";
import { type PostTestAssertion } from "./testCases/DeployWorkspaceProjectTestCase";

export namespace dwpTestUtils {
export function generateExpectedResults(sharedResourceName: string, acrResourceName: string, appResourceName: string): StringOrRegExpProps<DeployWorkspaceProjectResults> {
export function generateExpectedResultsWithCredentials(sharedResourceName: string, acrResourceName: string, appResourceName: string): StringOrRegExpProps<DeployWorkspaceProjectResults> {
return {
containerAppId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.App\/containerApps\/${appResourceName}`, 'i'),
imageName: new RegExp(appResourceName, 'i'),
Expand All @@ -27,6 +27,20 @@ export namespace dwpTestUtils {
};
}

export function generateExpectedResultsWithoutCredentials(sharedResourceName: string, acrResourceName: string, appResourceName: string): StringOrRegExpProps<DeployWorkspaceProjectResults> {
return {
containerAppId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.App\/containerApps\/${appResourceName}`, 'i'),
imageName: new RegExp(appResourceName, 'i'),
logAnalyticsWorkspaceId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.OperationalInsights\/workspaces\/${sharedResourceName}`, 'i'),
managedEnvironmentId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.App\/managedEnvironments\/${sharedResourceName}`, 'i'),
registryId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.ContainerRegistry\/registries\/${acrResourceName}.{6}`, 'i'),
registryLoginServer: new RegExp(`${acrResourceName}.{6}\.azurecr\.io`, 'i'),
registryPassword: undefined,
registryUsername: undefined,
resourceGroupId: new RegExp(`\/resourceGroups\/${sharedResourceName}`, 'i')
};
}

export function generatePostTestAssertion(expectedContainerAppSettings: { targetPort: number | undefined, env: EnvironmentVar[] | undefined }): PostTestAssertion {
return async function postTestAssertion(context: IActionContext, resources: DeployWorkspaceProjectResults, errMsg?: string): Promise<void> {
const parsedId = parseAzureResourceId(nonNullProp(resources, 'containerAppId'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ export function generateAlbumApiJavaScriptTestCases(): DeployWorkspaceProjectTes
label: 'Should fail to deploy app (bad Dockerfile)',
inputs: [
new RegExp(folderName, 'i'),
new RegExp('test_fail.Dockerfile', 'i'),
path.join('src', 'test_fail.Dockerfile'),
new RegExp('Create new container apps environment', 'i'),
new RegExp('Create new container registry', 'i'),
'Continue',
sharedResourceName.slice(0, -1), // Isolate by using a different resource group name since we expect this case to fail
appResourceName,
Expand All @@ -41,8 +42,9 @@ export function generateAlbumApiJavaScriptTestCases(): DeployWorkspaceProjectTes
label: 'Deploy App',
inputs: [
new RegExp(folderName, 'i'),
'Dockerfile',
path.join('src', 'Dockerfile'),
new RegExp('Create new container apps environment', 'i'),
new RegExp('Create new container registry', 'i'),
'Continue',
sharedResourceName,
appResourceName,
Expand All @@ -52,7 +54,7 @@ export function generateAlbumApiJavaScriptTestCases(): DeployWorkspaceProjectTes
'East US',
'Save'
],
expectedResults: dwpTestUtils.generateExpectedResults(sharedResourceName, acrResourceName, appResourceName),
expectedResults: dwpTestUtils.generateExpectedResultsWithCredentials(sharedResourceName, acrResourceName, appResourceName),
expectedVSCodeSettings: {
deploymentConfigurations: [
generateExpectedDeploymentConfiguration(sharedResourceName, acrResourceName, appResourceName)
Expand All @@ -68,7 +70,7 @@ export function generateAlbumApiJavaScriptTestCases(): DeployWorkspaceProjectTes
appResourceName,
'Continue'
],
expectedResults: dwpTestUtils.generateExpectedResults(sharedResourceName, acrResourceName, appResourceName),
expectedResults: dwpTestUtils.generateExpectedResultsWithCredentials(sharedResourceName, acrResourceName, appResourceName),
expectedVSCodeSettings: {
deploymentConfigurations: [
generateExpectedDeploymentConfiguration(sharedResourceName, acrResourceName, appResourceName)
Expand Down
Loading

0 comments on commit 2542c3a

Please sign in to comment.