-
Notifications
You must be signed in to change notification settings - Fork 17
Add deployImage as part of API export, add additional activity children, and allow more flexible deployment targets
#817
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
87841ca
1088867
3e85ad6
e0a7003
c35bd08
ef87f0f
631be79
b537741
146661f
e4ede57
7906366
7c8d543
b8a81fb
a5db872
c9292be
1feaddd
a139430
f2cd6a7
300a5da
2d05935
209d1ac
e2c87c6
7a8787c
eff6574
5b22cc9
bd3e538
57661f6
d2eddbb
4ec09bb
85eba7d
85d8d1c
ac5b4dc
31db97f
6f7cb74
75df8de
6a98700
08428a0
7849f25
5faccfc
21cf2c0
a5ddc53
6a433d9
316ea8c
d3c884c
85c4efa
2310f79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /*--------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.txt in the project root for license information. | ||
| *--------------------------------------------------------------------------------------------*/ | ||
|
|
||
| import { callWithMaskHandling, callWithTelemetryAndErrorHandling, createSubscriptionContext, type ExecuteActivityContext, type IActionContext, type ISubscriptionActionContext } from "@microsoft/vscode-azext-utils"; | ||
| import { ImageSource, acrDomain } from "../../constants"; | ||
| import { type DeployImageApiTelemetryProps as TelemetryProps } from "../../telemetry/commandTelemetryProps"; | ||
| import { type SetTelemetryProps } from "../../telemetry/SetTelemetryProps"; | ||
| import { getDomainFromRegistryName, getRegistryFromAcrName } from "../../utils/imageNameUtils"; | ||
| import { pickContainer } from "../../utils/pickItem/pickContainer"; | ||
| import { deployImage } from "../deployImage/deployImage"; | ||
| import { type ContainerRegistryImageSourceContext } from "../image/imageSource/containerRegistry/ContainerRegistryImageSourceContext"; | ||
| import { type ImageSourceBaseContext } from "../image/imageSource/ImageSourceContext"; | ||
| import { type DeployImageToAcaOptionsContract } from "./vscode-azurecontainerapps.api"; | ||
|
|
||
| export type DeployImageApiContext = ImageSourceBaseContext & ExecuteActivityContext & SetTelemetryProps<TelemetryProps>; | ||
|
|
||
| export async function deployImageApi(deployImageOptions: DeployImageToAcaOptionsContract): Promise<void> { | ||
| return await callWithTelemetryAndErrorHandling('containerApps.api.deployImage', async (context: IActionContext & Partial<ContainerRegistryImageSourceContext>) => { | ||
| const node = await pickContainer(context); | ||
| const { subscription } = node; | ||
|
|
||
| Object.assign(context, { ...createSubscriptionContext(subscription), imageSource: ImageSource.ContainerRegistry }, deployImageOptions); | ||
|
|
||
| context.registryDomain = getDomainFromRegistryName(deployImageOptions.registryName); | ||
| if (context.registryDomain === acrDomain) { | ||
| context.registry = await getRegistryFromAcrName(<ISubscriptionActionContext>context, deployImageOptions.registryName); | ||
| } | ||
|
|
||
| // Mask sensitive data | ||
| if (deployImageOptions.secret) { | ||
| context.valuesToMask.push(deployImageOptions.secret); | ||
| } | ||
| if (deployImageOptions.username) { | ||
| context.valuesToMask.push(deployImageOptions.username); | ||
| } | ||
| context.valuesToMask.push(deployImageOptions.image); | ||
|
|
||
| if (deployImageOptions.secret) { | ||
| context.telemetry.properties.hasRegistrySecrets = 'true'; | ||
| return callWithMaskHandling<void>(() => deployImage(context, node), deployImageOptions.secret); | ||
| } else { | ||
| context.telemetry.properties.hasRegistrySecrets = 'false'; | ||
| return deployImage(context, node); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * A compatibility wrapper for the legacy entrypoint utilizing `deployImageApi` | ||
| */ | ||
| export async function deployImageApiCompat(_: IActionContext & Partial<ContainerRegistryImageSourceContext>, deployImageOptions: DeployImageToAcaOptionsContract): Promise<void> { | ||
| return await deployImageApi(deployImageOptions); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,15 @@ export interface AzureContainerAppsExtensionApi { | |
| deployWorkspaceProject(options: DeployWorkspaceProjectOptionsContract): Promise<DeployWorkspaceProjectResults>; | ||
| } | ||
|
|
||
| // The interface of the command options passed to the Azure Container Apps extension's deployImageToAca command | ||
| // This interface is shared with the Docker extension (https://github.com/microsoft/vscode-docker) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Carryover of existing interface, but moved into the api type definition |
||
| export interface DeployImageToAcaOptionsContract { | ||
| image: string; | ||
| registryName: string; | ||
| username?: string; | ||
| secret?: string; | ||
| } | ||
|
|
||
| export interface DeployWorkspaceProjectOptionsContract { | ||
| // Existing resources | ||
| subscriptionId?: string; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /*--------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.md in the project root for license information. | ||
| *--------------------------------------------------------------------------------------------*/ | ||
|
|
||
| import { type Template } from "@azure/arm-appcontainers"; | ||
| import { type DeployImageApiContext } from "../api/deployImageApi"; | ||
|
|
||
| export interface DeployImageContext extends DeployImageApiContext { | ||
| containersIdx: number; | ||
| template: Template; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| /*--------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.md in the project root for license information. | ||
| *--------------------------------------------------------------------------------------------*/ | ||
|
|
||
| import { type ResourceGroup } from "@azure/arm-resources"; | ||
| import { LocationListStep, ResourceGroupListStep } from "@microsoft/vscode-azext-azureutils"; | ||
| import { activityInfoIcon, activitySuccessContext, AzureWizard, createSubscriptionContext, createUniversallyUniqueContextValue, GenericTreeItem, nonNullValue, nonNullValueAndProp, type IActionContext, type ISubscriptionContext } from "@microsoft/vscode-azext-utils"; | ||
| import { ext } from "../../extensionVariables"; | ||
| import { type ContainerItem } from "../../tree/containers/ContainerItem"; | ||
| import { createActivityContext } from "../../utils/activityUtils"; | ||
| import { isAzdExtensionInstalled } from "../../utils/azdUtils"; | ||
| import { getManagedEnvironmentFromContainerApp } from "../../utils/getResourceUtils"; | ||
| import { getVerifyProvidersStep } from "../../utils/getVerifyProvidersStep"; | ||
| import { localize } from "../../utils/localize"; | ||
| import { getParentResource } from "../../utils/revisionDraftUtils"; | ||
| import { ContainerAppOverwriteConfirmStep } from "../ContainerAppOverwriteConfirmStep"; | ||
| import { showContainerAppNotification } from "../createContainerApp/showContainerAppNotification"; | ||
| import { ContainerAppUpdateStep } from "../image/imageSource/ContainerAppUpdateStep"; | ||
| import { ImageSourceListStep } from "../image/imageSource/ImageSourceListStep"; | ||
| import { type ContainerRegistryImageSourceContext } from "../image/imageSource/containerRegistry/ContainerRegistryImageSourceContext"; | ||
| import { type DeployImageContext } from "./DeployImageContext"; | ||
|
|
||
| export async function deployImage(context: IActionContext & Partial<ContainerRegistryImageSourceContext>, node: ContainerItem): Promise<void> { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New changes:
|
||
| const { subscription, containerApp } = node; | ||
| const subscriptionContext: ISubscriptionContext = createSubscriptionContext(subscription); | ||
|
|
||
| const wizardContext: DeployImageContext = { | ||
| ...context, | ||
| ...subscriptionContext, | ||
| ...await createActivityContext(true), | ||
| subscription, | ||
| managedEnvironment: await getManagedEnvironmentFromContainerApp({ ...context, ...subscriptionContext }, containerApp), | ||
| containerApp, | ||
| containersIdx: node.containersIdx, | ||
| template: nonNullValueAndProp(getParentResource(containerApp, node.revision), 'template'), | ||
| }; | ||
|
|
||
| if (isAzdExtensionInstalled()) { | ||
| wizardContext.telemetry.properties.isAzdExtensionInstalled = 'true'; | ||
| } | ||
|
|
||
| const resourceGroups: ResourceGroup[] = await ResourceGroupListStep.getResourceGroups(wizardContext); | ||
| wizardContext.resourceGroup = nonNullValue( | ||
| resourceGroups.find(rg => rg.name === containerApp.resourceGroup), | ||
| localize('containerAppResourceGroup', 'Expected to find the container app\'s resource group.'), | ||
| ); | ||
|
|
||
| // Log resource group | ||
| wizardContext.activityChildren?.push( | ||
| new GenericTreeItem(undefined, { | ||
| contextValue: createUniversallyUniqueContextValue(['useExistingResourceGroupInfoItem', activitySuccessContext]), | ||
| label: localize('useResourceGroup', 'Using resource group "{0}"', wizardContext.resourceGroup.name), | ||
| iconPath: activityInfoIcon | ||
| }) | ||
| ); | ||
| ext.outputChannel.appendLog(localize('usingResourceGroup', 'Using resource group "{0}".', wizardContext.resourceGroup.name)); | ||
|
|
||
| // Log container app | ||
| wizardContext.activityChildren?.push( | ||
| new GenericTreeItem(undefined, { | ||
| contextValue: createUniversallyUniqueContextValue(['useExistingContainerAppInfoItem', activitySuccessContext]), | ||
| label: localize('useContainerApp', 'Using container app "{0}"', wizardContext.containerApp?.name), | ||
| iconPath: activityInfoIcon | ||
| }) | ||
| ); | ||
| ext.outputChannel.appendLog(localize('usingContainerApp', 'Using container app "{0}".', wizardContext.containerApp?.name)); | ||
|
|
||
| await LocationListStep.setLocation(wizardContext, containerApp.location); | ||
|
|
||
| const parentResourceName: string = getParentResource(containerApp, node.revision).name ?? containerApp.name; | ||
| const wizard: AzureWizard<DeployImageContext> = new AzureWizard(wizardContext, { | ||
| title: localize('deployImageTitle', 'Deploy image to "{0}"', parentResourceName), | ||
| promptSteps: [ | ||
| new ImageSourceListStep(), | ||
| new ContainerAppOverwriteConfirmStep(), | ||
| ], | ||
| executeSteps: [ | ||
| getVerifyProvidersStep<DeployImageContext>(), | ||
| new ContainerAppUpdateStep(), | ||
| ], | ||
| showLoadingPrompt: true | ||
| }); | ||
|
|
||
| await wizard.prompt(); | ||
| await wizard.execute(); | ||
|
|
||
| if (!wizardContext.suppressNotification) { | ||
| void showContainerAppNotification(containerApp, true /** isUpdate */); | ||
| } | ||
| } | ||
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is all carryover code except with a new
callWithTelemetryAndErrorHandlingwrapper