Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,160 changes: 1,155 additions & 5 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@
"@aws-sdk/client-ssm": "<3.696.0",
"@aws-sdk/client-sso": "<3.696.0",
"@aws-sdk/client-sso-oidc": "<3.696.0",
"@aws-sdk/client-apprunner": "<3.696.0",
"@aws-sdk/credential-provider-env": "<3.696.0",
"@aws-sdk/credential-provider-process": "<3.696.0",
"@aws-sdk/credential-provider-sso": "<3.696.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { EcrRepositoryNode } from '../../../awsService/ecr/explorer/ecrRepositor
import { EcrTagNode } from '../../../awsService/ecr/explorer/ecrTagNode'

import { CreateAppRunnerServiceWizard } from '../wizards/apprunnerCreateServiceWizard'
import { DefaultAppRunnerClient } from '../../../shared/clients/apprunnerClient'
import { AppRunnerClient } from '../../../shared/clients/apprunner'
import { telemetry } from '../../../shared/telemetry/telemetry'
import { Result } from '../../../shared/telemetry/telemetry'

export async function createFromEcr(
node: EcrTagNode | EcrRepositoryNode,
client = new DefaultAppRunnerClient(node.regionCode)
client = new AppRunnerClient(node.regionCode)
): Promise<void> {
let telemetryResult: Result = 'Failed'

Expand Down
41 changes: 12 additions & 29 deletions packages/core/src/awsService/apprunner/explorer/apprunnerNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import { AWSTreeNodeBase } from '../../../shared/treeview/nodes/awsTreeNodeBase'
import { AppRunnerServiceNode } from './apprunnerServiceNode'
import { PlaceholderNode } from '../../../shared/treeview/nodes/placeholderNode'
import * as nls from 'vscode-nls'
import { AppRunnerClient } from '../../../shared/clients/apprunnerClient'
import { getPaginatedAwsCallIter } from '../../../shared/utilities/collectionUtils'
import { AppRunner } from 'aws-sdk'
import {
AppRunnerClient,
AppRunnerCreateServiceRequest,
AppRunnerServiceSummary,
} from '../../../shared/clients/apprunner'
import { PollingSet } from '../../../shared/utilities/pollingSet'
import { ListServicesRequest } from '@aws-sdk/client-apprunner'

const localize = nls.loadMessageBundle()

export class AppRunnerNode extends AWSTreeNodeBase {
private readonly serviceNodes: Map<AppRunner.ServiceId, AppRunnerServiceNode> = new Map()
private readonly serviceNodes: Map<string, AppRunnerServiceNode> = new Map()
private readonly pollingSet: PollingSet<string> = new PollingSet(20000, this.refresh.bind(this))

public constructor(
Expand All @@ -43,30 +46,10 @@ export class AppRunnerNode extends AWSTreeNodeBase {
})
}

private async getServiceSummaries(request: AppRunner.ListServicesRequest = {}): Promise<AppRunner.Service[]> {
const iterator = getPaginatedAwsCallIter({
awsCall: async (request) => await this.client.listServices(request),
nextTokenNames: {
request: 'NextToken',
response: 'NextToken',
},
request,
})

const services: AppRunner.Service[] = []

while (true) {
const next = await iterator.next()

// eslint-disable-next-line unicorn/no-array-for-each
next.value.ServiceSummaryList.forEach((summary: AppRunner.Service) => services.push(summary))

if (next.done) {
break
}
}

return services
private async getServiceSummaries(request: ListServicesRequest = {}): Promise<AppRunnerServiceSummary[]> {
// TODO: avoid resolving all services at once.
const serviceCollection = this.client.paginateServices(request)
return await serviceCollection.flatten().promise()
}

public async updateChildren(): Promise<void> {
Expand Down Expand Up @@ -107,7 +90,7 @@ export class AppRunnerNode extends AWSTreeNodeBase {
this.pollingSet.delete(id)
}

public async createService(request: AppRunner.CreateServiceRequest): Promise<void> {
public async createService(request: AppRunnerCreateServiceRequest): Promise<void> {
await this.client.createService(request)
this.refresh()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
*/

import AsyncLock from 'async-lock'
import { AppRunnerClient } from '../../../shared/clients/apprunnerClient'
import { AppRunner } from 'aws-sdk'
import { AppRunnerClient, AppRunnerServiceSummary } from '../../../shared/clients/apprunner'
import { AppRunnerNode } from './apprunnerNode'

import { toArrayAsync, toMap } from '../../../shared/utilities/collectionUtils'
Expand All @@ -17,6 +16,7 @@ import * as nls from 'vscode-nls'
import { getLogger } from '../../../shared/logger/logger'
import { getIcon } from '../../../shared/icons'
import { DefaultCloudWatchLogsClient } from '../../../shared/clients/cloudWatchLogsClient'
import { OperationSummary, UpdateServiceRequest } from '@aws-sdk/client-apprunner'
const localize = nls.loadMessageBundle()

const contextBase = 'awsAppRunnerServiceNode'
Expand All @@ -41,8 +41,8 @@ export class AppRunnerServiceNode extends CloudWatchLogsBase implements AWSResou
constructor(
public readonly parent: AppRunnerNode,
private readonly client: AppRunnerClient,
private _info: AppRunner.Service,
private currentOperation: AppRunner.OperationSummary & { Type?: ServiceOperation } = {},
private _info: AppRunnerServiceSummary,
private currentOperation: OperationSummary & { Type?: ServiceOperation } = {},
cloudwatchClient = new DefaultCloudWatchLogsClient(client.regionCode)
) {
super('App Runner Service', parent.regionCode, cloudwatchClient)
Expand All @@ -55,7 +55,7 @@ export class AppRunnerServiceNode extends CloudWatchLogsBase implements AWSResou
this.update(_info)
}

public get info(): Readonly<AppRunner.Service> {
public get info(): Readonly<AppRunnerServiceSummary> {
return this._info
}

Expand All @@ -81,7 +81,7 @@ export class AppRunnerServiceNode extends CloudWatchLogsBase implements AWSResou
this.label = `${this._info.ServiceName} [${displayStatus}]`
}

public update(info: AppRunner.ServiceSummary | AppRunner.Service): void {
public update(info: AppRunnerServiceSummary): void {
// update can be called multiple times during an event loop
// this would rarely cause the node's status to appear as 'Operation in progress'
this.lock
Expand Down Expand Up @@ -135,7 +135,7 @@ export class AppRunnerServiceNode extends CloudWatchLogsBase implements AWSResou
})
}

private updateInfo(info: AppRunner.ServiceSummary | AppRunner.Service): void {
private updateInfo(info: AppRunnerServiceSummary): void {
if (info.Status === 'OPERATION_IN_PROGRESS' && this.currentOperation.Type === undefined) {
// Asynchronous since it is not currently possible for race-conditions to occur with updating operations
void this.updateOperation()
Expand All @@ -161,7 +161,7 @@ export class AppRunnerServiceNode extends CloudWatchLogsBase implements AWSResou
this.setOperation(resp.Service, resp.OperationId, 'DELETE_SERVICE')
}

public async updateService(request: AppRunner.UpdateServiceRequest): Promise<void> {
public async updateService(request: UpdateServiceRequest): Promise<void> {
const resp = await this.client.updateService({ ...request, ServiceArn: this._info.ServiceArn })
this.setOperation(resp.Service, resp.OperationId, 'UPDATE_SERVICE')
}
Expand All @@ -171,13 +171,14 @@ export class AppRunnerServiceNode extends CloudWatchLogsBase implements AWSResou
this.setOperation(this._info, resp.OperationId, 'START_DEPLOYMENT')
}

public setOperation(info: AppRunner.Service, id?: string, type?: ServiceOperation): void {
// eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents
public setOperation(info: AppRunnerServiceSummary, id?: string, type?: ServiceOperation): void {
this.currentOperation.Id = id
this.currentOperation.Type = type
this.update(info)
}

public async describe(): Promise<AppRunner.Service> {
public async describe(): Promise<AppRunnerServiceSummary> {
const resp = await this.client.describeService({ ServiceArn: this.arn })
this.update(resp.Service)
return this._info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { AppRunner } from 'aws-sdk'
import * as nls from 'vscode-nls'
import { createCommonButtons, QuickInputToggleButton } from '../../../shared/ui/buttons'
import * as input from '../../../shared/ui/inputPrompter'
Expand All @@ -17,8 +16,13 @@ import { makeDeploymentButton } from './deploymentButton'
import { createExitPrompter } from '../../../shared/ui/common/exitPrompter'
import { IamClient } from '../../../shared/clients/iam'
import { DefaultEcrClient } from '../../../shared/clients/ecrClient'
import { DefaultAppRunnerClient } from '../../../shared/clients/apprunnerClient'
import {
AppRunnerClient,
AppRunnerCreateServiceRequest,
AppRunnerSourceConfiguration,
} from '../../../shared/clients/apprunner'
import { getAppRunnerCreateServiceDocUrl } from '../../../shared/extensionUtilities'
import { InstanceConfiguration } from '@aws-sdk/client-apprunner'

const localize = nls.loadMessageBundle()

Expand Down Expand Up @@ -54,14 +58,14 @@ const validateName = (name: string) => {
return undefined
}

function createInstanceStep(): Prompter<AppRunner.InstanceConfiguration> {
function createInstanceStep(): Prompter<InstanceConfiguration> {
const enumerations = [
[1, 2],
[1, 3],
[2, 4],
]

const items: picker.DataQuickPickItem<AppRunner.InstanceConfiguration>[] = enumerations.map((e) => ({
const items: picker.DataQuickPickItem<InstanceConfiguration>[] = enumerations.map((e) => ({
label: `${e[0]} vCPUs, ${e[1]} GBs Memory`,
data: { Cpu: `${e[0]} vCPU`, Memory: `${e[1]} GB` },
}))
Expand All @@ -74,10 +78,10 @@ function createInstanceStep(): Prompter<AppRunner.InstanceConfiguration> {

function createSourcePrompter(
autoDeployButton: QuickInputToggleButton
): Prompter<AppRunner.CreateServiceRequest['SourceConfiguration']> {
): Prompter<AppRunnerCreateServiceRequest['SourceConfiguration']> {
const ecrPath = {
label: 'ECR',
data: { ImageRepository: {} } as AppRunner.SourceConfiguration,
data: { ImageRepository: {} } as AppRunnerSourceConfiguration,
detail: localize(
'AWS.apprunner.createService.ecr.detail',
'Create a service from a public or private Elastic Container Registry repository'
Expand All @@ -86,7 +90,7 @@ function createSourcePrompter(

const repositoryPath = {
label: 'Repository',
data: { CodeRepository: {} } as AppRunner.SourceConfiguration,
data: { CodeRepository: {} } as AppRunnerSourceConfiguration,
detail: localize('AWS.apprunner.createService.repository.detail', 'Create a service from a GitHub repository'),
}

Expand All @@ -96,15 +100,15 @@ function createSourcePrompter(
})
}

export class CreateAppRunnerServiceWizard extends Wizard<AppRunner.CreateServiceRequest> {
export class CreateAppRunnerServiceWizard extends Wizard<AppRunnerCreateServiceRequest> {
public constructor(
region: string,
initState: WizardState<AppRunner.CreateServiceRequest> = {},
implicitState: WizardState<AppRunner.CreateServiceRequest> = {},
initState: WizardState<AppRunnerCreateServiceRequest> = {},
implicitState: WizardState<AppRunnerCreateServiceRequest> = {},
clients = {
iam: new IamClient(region),
ecr: new DefaultEcrClient(region),
apprunner: new DefaultAppRunnerClient(region),
apprunner: new AppRunnerClient(region),
}
) {
super({
Expand Down
Loading
Loading