Skip to content

Commit f1c4700

Browse files
committed
Impl
1 parent b3bb7ad commit f1c4700

File tree

18 files changed

+207
-22
lines changed

18 files changed

+207
-22
lines changed

package.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@
7575
"title": "%containerApps.editContainerApp%",
7676
"category": "Azure Container Apps"
7777
},
78+
{
79+
"command": "containerApps.updateImage",
80+
"title": "%containerApps.updateImage%",
81+
"category": "Azure Container Apps"
82+
},
7883
{
7984
"command": "containerApps.deployImageApi",
8085
"title": "%containerApps.deployImageApi%",
@@ -328,6 +333,11 @@
328333
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /containerAppItem/i",
329334
"group": "5@1"
330335
},
336+
{
337+
"command": "containerApps.updateImage",
338+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /containerAppItem(.*)revisionMode:single/i",
339+
"group": "6@1"
340+
},
331341
{
332342
"command": "containerApps.startStreamingLogs",
333343
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /containerAppItem/i",
@@ -368,6 +378,11 @@
368378
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /revisionItem(.*)revisionState:active/i",
369379
"group": "2@4"
370380
},
381+
{
382+
"command": "containerApps.updateImage",
383+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /revisionDraft:false(.*)revisionItem/i",
384+
"group": "3@1"
385+
},
371386
{
372387
"command": "containerApps.deployRevisionDraft",
373388
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /revisionDraftItem(.*)unsavedChanges:true/i",
@@ -389,10 +404,15 @@
389404
"group": "1@2"
390405
},
391406
{
392-
"command": "containerApps.editRevisionDraft",
407+
"command": "containerApps.updateImage",
393408
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /revisionDraftItem/i",
394409
"group": "2@1"
395410
},
411+
{
412+
"command": "containerApps.editRevisionDraft",
413+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /revisionDraftItem/i",
414+
"group": "3@1"
415+
},
396416
{
397417
"command": "containerApps.editScaleRange",
398418
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /scaleItem/i",

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"containerApps.browse": "Browse",
88
"containerApps.createContainerApp": "Create Container App...",
99
"containerApps.editContainerApp": "Edit Container App (Advanced)...",
10+
"containerApps.updateImage": "Update Container Image...",
1011
"containerApps.deployImageApi": "Deploy Image to Container App (API)...",
1112
"containerApps.deployWorkspaceProject": "Deploy Project from Workspace...",
1213
"containerApps.deleteContainerApp": "Delete Container App...",

src/commands/createContainerApp/ContainerAppCreateStep.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { getContainerNameForImage } from "../image/imageSource/containerRegistry
1717
import type { ICreateContainerAppContext } from "./ICreateContainerAppContext";
1818

1919
export class ContainerAppCreateStep extends ExecuteActivityOutputStepBase<ICreateContainerAppContext> {
20-
public priority: number = 750;
20+
public priority: number = 620;
2121

2222
protected async executeCore(context: ICreateContainerAppContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
2323
const appClient: ContainerAppsAPIClient = await createContainerAppsAPIClient(context);

src/commands/image/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22

33
- `deployImageApi` - A command shared with the `vscode-docker` extension. It uses our old `deployImage` command flow which immediately tries to deploy the image to a container app without creating a draft. This command cannot be used to bundle template changes.
44

5-
<!-- Todo: Add this back in when update image command is added in follow-up PR -->
6-
<!-- - `updateContainerImage` - An ACA exclusive command that updates the container app or revision's container image through updates to a revision draft. The draft must be deployed for the changes to take effect and can be used to bundle together `Template` changes. -->
5+
- `updateImage` - An ACA exclusive command that updates the container app or revision's container image via revision draft. The draft must be deployed for the changes to take effect and can be used to bundle together `Template` changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { Revision } from "@azure/arm-appcontainers";
7+
import { nonNullProp, randomUtils } from "@microsoft/vscode-azext-utils";
8+
import { Progress } from "vscode";
9+
import { ext } from "../../../extensionVariables";
10+
import { ContainerAppItem, ContainerAppModel } from "../../../tree/ContainerAppItem";
11+
import { RevisionsItemModel } from "../../../tree/revisionManagement/RevisionItem";
12+
import { localize } from "../../../utils/localize";
13+
import { getParentResourceFromItem } from "../../../utils/revisionDraftUtils";
14+
import { RevisionDraftUpdateBaseStep } from "../../revisionDraft/RevisionDraftUpdateBaseStep";
15+
import { getContainerNameForImage } from "../imageSource/containerRegistry/getContainerNameForImage";
16+
import { UpdateImageContext } from "./updateImage";
17+
18+
export class UpdateImageStep<T extends UpdateImageContext> extends RevisionDraftUpdateBaseStep<T> {
19+
public priority: number = 490;
20+
21+
constructor(baseItem: ContainerAppItem | RevisionsItemModel) {
22+
super(baseItem);
23+
}
24+
25+
public async execute(context: UpdateImageContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
26+
progress.report({ message: localize('updatingImage', 'Updating image (draft)...') });
27+
28+
this.revisionDraftTemplate.containers = [];
29+
this.revisionDraftTemplate.containers.push({
30+
env: context.environmentVariables,
31+
image: context.image,
32+
// We need the revision draft to always show up as having unsaved changes, we can ensure this by adding a unique ID at end of the container name
33+
name: getContainerNameForImage(nonNullProp(context, 'image')) + `-${randomUtils.getRandomHexString(5)}`,
34+
});
35+
36+
this.updateRevisionDraftWithTemplate();
37+
38+
const parentResource: ContainerAppModel | Revision = getParentResourceFromItem(this.baseItem);
39+
ext.outputChannel.appendLog(localize('updatedImage', 'Updated container app "{0}" with image "{1}" (draft).', parentResource.name, context.image));
40+
}
41+
42+
public shouldExecute(context: UpdateImageContext): boolean {
43+
return !!context.containerApp && !!context.image;
44+
}
45+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { AzureWizardExecuteStep, nonNullProp } from "@microsoft/vscode-azext-utils";
7+
import type { Progress } from "vscode";
8+
import { ext } from "../../../extensionVariables";
9+
import { ContainerAppModel, getContainerEnvelopeWithSecrets } from "../../../tree/ContainerAppItem";
10+
import { localize } from "../../../utils/localize";
11+
import { updateContainerApp } from "../../../utils/updateContainerApp/updateContainerApp";
12+
import { UpdateImageContext } from "./updateImage";
13+
14+
export class UpdateRegistryAndSecretsStep extends AzureWizardExecuteStep<UpdateImageContext> {
15+
public priority: number = 480;
16+
17+
public async execute(context: UpdateImageContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
18+
progress.report({ message: localize('configuringSecrets', 'Configuring registry secrets...') });
19+
20+
const containerApp: ContainerAppModel = nonNullProp(context, 'containerApp');
21+
const containerAppEnvelope = await getContainerEnvelopeWithSecrets(context, context.subscription, containerApp);
22+
23+
containerAppEnvelope.configuration.secrets = context.secrets;
24+
containerAppEnvelope.configuration.registries = context.registries;
25+
26+
await updateContainerApp(context, context.subscription, containerAppEnvelope);
27+
28+
ext.outputChannel.appendLog(localize('updatedSecrets', 'Updated container app "{0}" with new registry secrets.', containerApp.name));
29+
}
30+
31+
public shouldExecute(context: UpdateImageContext): boolean {
32+
return !!context.registries && !!context.secrets;
33+
}
34+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.md in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { KnownActiveRevisionsMode, Revision } from "@azure/arm-appcontainers";
7+
import { VerifyProvidersStep } from "@microsoft/vscode-azext-azureutils";
8+
import { AzureWizard, AzureWizardExecuteStep, AzureWizardPromptStep, ExecuteActivityContext, IActionContext, createSubscriptionContext } from "@microsoft/vscode-azext-utils";
9+
import { webProvider } from "../../../constants";
10+
import { ext } from "../../../extensionVariables";
11+
import { ContainerAppItem, ContainerAppModel } from "../../../tree/ContainerAppItem";
12+
import { RevisionDraftItem } from "../../../tree/revisionManagement/RevisionDraftItem";
13+
import { RevisionItem } from "../../../tree/revisionManagement/RevisionItem";
14+
import { createActivityContext } from "../../../utils/activity/activityUtils";
15+
import { localize } from "../../../utils/localize";
16+
import { pickContainerApp } from "../../../utils/pickItem/pickContainerApp";
17+
import { pickRevision, pickRevisionDraft } from "../../../utils/pickItem/pickRevision";
18+
import { getParentResourceFromItem } from "../../../utils/revisionDraftUtils";
19+
import type { ImageSourceBaseContext } from "../imageSource/ImageSourceBaseContext";
20+
import { ImageSourceListStep } from "../imageSource/ImageSourceListStep";
21+
import { UpdateImageStep } from "./UpdateImageStep";
22+
import { UpdateRegistryAndSecretsStep } from "./UpdateRegistryAndSecretsStep";
23+
24+
export type UpdateImageContext = ImageSourceBaseContext & ExecuteActivityContext;
25+
26+
export async function updateImage(context: IActionContext, node?: ContainerAppItem | RevisionItem): Promise<void> {
27+
let item: ContainerAppItem | RevisionItem | RevisionDraftItem | undefined = node;
28+
if (!item) {
29+
const containerAppItem: ContainerAppItem = await pickContainerApp(context);
30+
31+
if (containerAppItem.containerApp.revisionsMode === KnownActiveRevisionsMode.Single) {
32+
item = containerAppItem;
33+
} else {
34+
if (ext.revisionDraftFileSystem.doesContainerAppsItemHaveRevisionDraft(containerAppItem)) {
35+
item = await pickRevisionDraft(context, containerAppItem);
36+
} else {
37+
item = await pickRevision(context, containerAppItem);
38+
}
39+
}
40+
}
41+
42+
const { subscription, containerApp } = item;
43+
44+
const wizardContext: UpdateImageContext = {
45+
...context,
46+
...createSubscriptionContext(subscription),
47+
...await createActivityContext(),
48+
subscription,
49+
containerApp
50+
};
51+
52+
const promptSteps: AzureWizardPromptStep<UpdateImageContext>[] = [
53+
new ImageSourceListStep(),
54+
];
55+
56+
const executeSteps: AzureWizardExecuteStep<UpdateImageContext>[] = [
57+
new VerifyProvidersStep([webProvider]),
58+
new UpdateRegistryAndSecretsStep(),
59+
new UpdateImageStep(item)
60+
];
61+
62+
const parentResource: ContainerAppModel | Revision = getParentResourceFromItem(item);
63+
64+
const wizard: AzureWizard<UpdateImageContext> = new AzureWizard(wizardContext, {
65+
title: localize('updateImage', 'Update container image for "{0}" (draft)', parentResource.name),
66+
promptSteps,
67+
executeSteps,
68+
showLoadingPrompt: true
69+
});
70+
71+
await wizard.prompt();
72+
await wizard.execute();
73+
}

src/commands/ingress/disableIngress/DisableIngressStep.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { IngressUpdateStepBase } from "../IngressUpdateStepBase";
1111
import { isIngressEnabled } from "../isIngressEnabled";
1212

1313
export class DisableIngressStep extends IngressUpdateStepBase<IngressContext> {
14-
public priority: number = 650;
14+
public priority: number = 750;
1515

1616
public async execute(context: IngressContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
1717
const containerApp = nonNullProp(context, 'containerApp');

src/commands/ingress/enableIngress/EnableIngressStep.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { updateContainerApp } from "../../../utils/updateContainerApp/updateCont
1414
import type { IngressContext } from "../IngressContext";
1515

1616
export class EnableIngressStep extends ExecuteActivityOutputStepBase<IngressContext> {
17-
public priority: number = 650;
17+
public priority: number = 750;
1818

1919
protected async executeCore(context: IngressContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
2020
progress.report({ message: localize('enablingIngress', 'Enabling ingress...') });

src/commands/ingress/toggleIngressVisibility/ToggleIngressVisibilityStep.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { IngressContext } from "../IngressContext";
1111
import { IngressUpdateStepBase } from "../IngressUpdateStepBase";
1212

1313
export class ToggleIngressVisibilityStep extends IngressUpdateStepBase<IngressContext> {
14-
public priority: number = 650;
14+
public priority: number = 750;
1515

1616
public async execute(context: IngressContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
1717
const containerApp = nonNullProp(context, 'containerApp');

0 commit comments

Comments
 (0)