public async execute()

in src/commands/registries/azure/DockerAssignAcrPullRoleStep.ts [21:81]


    public async execute(context: IAppServiceWizardContext, progress: Progress<{ message?: string; increment?: number }>): Promise<void> {
        const message: string = localize('vscode-docker.commands.registries.azure.deployImage.assigningPullRole', 'Granting permission for App Service to pull image from ACR...');
        ext.outputChannel.appendLine(message);
        progress.report({ message: message });

        const armAuth = await import('@azure/arm-authorization');
        const armContainerRegistry = await import('@azure/arm-containerregistry');
        const armAppService = await import('@azure/arm-appservice');
        const authClient = createAzureClient(context, armAuth.AuthorizationManagementClient);
        const crmClient = createAzureClient(context, armContainerRegistry.ContainerRegistryManagementClient);
        const appSvcClient = createAzureClient(context, armAppService.WebSiteManagementClient);

        // If we're in `execute`, then `shouldExecute` passed and `this.tagTreeItem.parent.parent` is guaranteed to be an AzureRegistryTreeItem
        const registryTreeItem: AzureRegistryTreeItem = this.tagTreeItem.parent.parent as AzureRegistryTreeItem;

        // 1. Get the registry resource. We will need the ID.
        const registry = await crmClient.registries.get(registryTreeItem.resourceGroup, registryTreeItem.registryName);

        if (!(registry?.id)) {
            throw new Error(
                localize('vscode-docker.commands.registries.deployImage.noRegistryId', 'Unable to get details from Container Registry {0}', registryTreeItem.baseUrl)
            );
        }

        // 2. Get the role definition for the AcrPull role. We will need the definition ID. This role is built-in and should always exist.
        const acrPullRoleDefinition = (await authClient.roleDefinitions.list(registry.id, { filter: `roleName eq 'AcrPull'` }))[0];

        if (!(acrPullRoleDefinition?.id)) {
            throw new Error(
                localize('vscode-docker.commands.registries.deployImage.noRoleDefinition', 'Unable to get AcrPull role definition on subscription {0}', context.subscriptionId)
            );
        }

        // 3. Get the info for the now-created web site. We will need the principal ID.
        const siteInfo = await appSvcClient.webApps.get(context.site.resourceGroup, context.site.name);

        if (!(siteInfo?.identity?.principalId)) {
            throw new Error(
                localize('vscode-docker.commands.registries.deployImage.noPrincipalid', 'Unable to get identity principal ID for web site {0}', context.site.name)
            );
        }

        // 4. On the registry, assign the AcrPull role to the principal representing the website
        await authClient.roleAssignments.create(registry.id, (await import('uuid')).v4(), {
            principalId: siteInfo.identity.principalId,
            roleDefinitionId: acrPullRoleDefinition.id,
            principalType: 'ServicePrincipal',
        });

        // 5. Set the web app to use the desired ACR image, which was not done in DockerSiteCreateStep. Get the config and then update it.
        const config = await appSvcClient.webApps.getConfiguration(context.site.resourceGroup, context.site.name);

        if (!config) {
            throw new Error(
                localize('vscode-docker.commands.registries.deployImage.updateConfig', 'Unable to get configuration for web site {0}', context.site.name)
            );
        }

        config.linuxFxVersion = `DOCKER|${this.tagTreeItem.fullTag}`;
        await appSvcClient.webApps.updateConfiguration(context.site.resourceGroup, context.site.name, config);
    }