diff --git a/packages/core/src/dynamicResources/awsResourceManager.ts b/packages/core/src/dynamicResources/awsResourceManager.ts index 76a45996f28..6dbcc64e1ec 100644 --- a/packages/core/src/dynamicResources/awsResourceManager.ts +++ b/packages/core/src/dynamicResources/awsResourceManager.ts @@ -6,7 +6,7 @@ import { writeFileSync } from 'fs' // eslint-disable-line no-restricted-imports import * as path from 'path' import * as vscode from 'vscode' -import { CloudFormationClient } from '../shared/clients/cloudFormationClient' +import { CloudFormationClient } from '../shared/clients/cloudFormation' import { getNonexistentFilename, makeTemporaryToolkitFolder, diff --git a/packages/core/src/dynamicResources/explorer/nodes/resourcesNode.ts b/packages/core/src/dynamicResources/explorer/nodes/resourcesNode.ts index 53e650fcf34..65cc8c09d3b 100644 --- a/packages/core/src/dynamicResources/explorer/nodes/resourcesNode.ts +++ b/packages/core/src/dynamicResources/explorer/nodes/resourcesNode.ts @@ -5,16 +5,16 @@ import * as vscode from 'vscode' import * as nls from 'vscode-nls' -import { CloudFormationClient, DefaultCloudFormationClient } from '../../../shared/clients/cloudFormationClient' +import { CloudFormationClient } from '../../../shared/clients/cloudFormation' import { AWSTreeNodeBase } from '../../../shared/treeview/nodes/awsTreeNodeBase' import { PlaceholderNode } from '../../../shared/treeview/nodes/placeholderNode' import { makeChildrenNodes } from '../../../shared/treeview/utils' import { toArrayAsync, updateInPlace } from '../../../shared/utilities/collectionUtils' import { ResourceTypeNode } from './resourceTypeNode' -import { CloudFormation } from 'aws-sdk' import { CloudControlClient } from '../../../shared/clients/cloudControl' import { memoizedGetResourceTypes, ResourceTypeMetadata } from '../../model/resources' import { ResourcesSettings } from '../../commands/configure' +import { TypeSummary } from '@aws-sdk/client-cloudformation' const localize = nls.loadMessageBundle() @@ -23,7 +23,7 @@ export class ResourcesNode extends AWSTreeNodeBase { public constructor( public readonly region: string, - public readonly cloudFormation: CloudFormationClient = new DefaultCloudFormationClient(region), + public readonly cloudFormation: CloudFormationClient = new CloudFormationClient(region), private readonly cloudControl: CloudControlClient = new CloudControlClient(region), private readonly settings = new ResourcesSettings() ) { @@ -62,7 +62,7 @@ export class ResourcesNode extends AWSTreeNodeBase { const types = await toArrayAsync(this.cloudFormation.listTypes()) types.sort((a, b) => (a.LastUpdated?.getTime() ?? 0) - (b.LastUpdated?.getTime() ?? 0)) - const availableTypes: Map = new Map() + const availableTypes: Map = new Map() for (const type of types) { if (type.TypeName) { availableTypes.set(type.TypeName!, type) diff --git a/packages/core/src/lambda/commands/deleteCloudFormation.ts b/packages/core/src/lambda/commands/deleteCloudFormation.ts index 67c903f35c3..035e7110c86 100644 --- a/packages/core/src/lambda/commands/deleteCloudFormation.ts +++ b/packages/core/src/lambda/commands/deleteCloudFormation.ts @@ -7,7 +7,7 @@ import * as nls from 'vscode-nls' const localize = nls.loadMessageBundle() import * as vscode from 'vscode' -import { DefaultCloudFormationClient } from '../../shared/clients/cloudFormationClient' +import { CloudFormationClient } from '../../shared/clients/cloudFormation' import * as localizedText from '../../shared/localizedText' import { getLogger, Logger } from '../../shared/logger/logger' @@ -45,7 +45,7 @@ export async function deleteCloudFormation(refresh: () => void, node?: CloudForm }) if (userResponse) { - const client = new DefaultCloudFormationClient(node.regionCode) + const client = new CloudFormationClient(node.regionCode) await client.deleteStack(stackName) diff --git a/packages/core/src/lambda/explorer/cloudFormationNodes.ts b/packages/core/src/lambda/explorer/cloudFormationNodes.ts index 13eb1ca53f1..6fd8c4d0e96 100644 --- a/packages/core/src/lambda/explorer/cloudFormationNodes.ts +++ b/packages/core/src/lambda/explorer/cloudFormationNodes.ts @@ -9,7 +9,7 @@ const localize = nls.loadMessageBundle() import { CloudFormation, Lambda } from 'aws-sdk' import * as os from 'os' import * as vscode from 'vscode' -import { DefaultCloudFormationClient } from '../../shared/clients/cloudFormationClient' +import { CloudFormationClient, StackSummary } from '../../shared/clients/cloudFormation' import { DefaultLambdaClient } from '../../shared/clients/lambdaClient' import { AWSResourceNode } from '../../shared/treeview/nodes/awsResourceNode' @@ -28,7 +28,7 @@ export class CloudFormationNode extends AWSTreeNodeBase { public constructor( public override readonly regionCode: string, - private readonly client = new DefaultCloudFormationClient(regionCode) + private readonly client = new CloudFormationClient(regionCode) ) { super('CloudFormation', vscode.TreeItemCollapsibleState.Collapsed) this.stackNodes = new Map() @@ -66,9 +66,9 @@ export class CloudFormationStackNode extends AWSTreeNodeBase implements AWSResou public constructor( public readonly parent: AWSTreeNodeBase, public override readonly regionCode: string, - private stackSummary: CloudFormation.StackSummary, + private stackSummary: StackSummary, private readonly lambdaClient = new DefaultLambdaClient(regionCode), - private readonly cloudformationClient = new DefaultCloudFormationClient(regionCode) + private readonly cloudformationClient = new CloudFormationClient(regionCode) ) { super('', vscode.TreeItemCollapsibleState.Collapsed) @@ -114,7 +114,7 @@ export class CloudFormationStackNode extends AWSTreeNodeBase implements AWSResou }) } - public update(stackSummary: CloudFormation.StackSummary): void { + public update(stackSummary: StackSummary): void { this.stackSummary = stackSummary this.label = `${this.stackName} [${stackSummary.StackStatus}]` this.tooltip = `${this.stackName}${os.EOL}${this.stackId}` diff --git a/packages/core/src/lambda/utils.ts b/packages/core/src/lambda/utils.ts index 5018a221929..79054e02cac 100644 --- a/packages/core/src/lambda/utils.ts +++ b/packages/core/src/lambda/utils.ts @@ -7,9 +7,9 @@ import * as nls from 'vscode-nls' const localize = nls.loadMessageBundle() import xml2js = require('xml2js') -import { CloudFormation, Lambda } from 'aws-sdk' +import { Lambda } from 'aws-sdk' import * as vscode from 'vscode' -import { CloudFormationClient } from '../shared/clients/cloudFormationClient' +import { CloudFormationClient, StackSummary } from '../shared/clients/cloudFormation' import { LambdaClient } from '../shared/clients/lambdaClient' import { getFamily, getNodeMajorVersion, RuntimeFamily } from './models/samLambdaRuntime' import { getLogger } from '../shared/logger/logger' @@ -18,9 +18,7 @@ import { FileResourceFetcher } from '../shared/resourcefetcher/fileResourceFetch import { sampleRequestManifestPath } from './constants' import globals from '../shared/extensionGlobals' -export async function* listCloudFormationStacks( - client: CloudFormationClient -): AsyncIterableIterator { +export async function* listCloudFormationStacks(client: CloudFormationClient): AsyncIterableIterator { // TODO: this 'loading' message needs to go under each regional entry // in the explorer, and be removed when that region's query completes const status = vscode.window.setStatusBarMessage( diff --git a/packages/core/src/shared/clients/cloudFormation.ts b/packages/core/src/shared/clients/cloudFormation.ts new file mode 100644 index 00000000000..f04d2fdeb08 --- /dev/null +++ b/packages/core/src/shared/clients/cloudFormation.ts @@ -0,0 +1,94 @@ +/*! + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as CloudFormation from '@aws-sdk/client-cloudformation' +import { AsyncCollection } from '../utilities/asyncCollection' +import { hasProps, isNonNullable, RequiredProps } from '../utilities/tsUtils' +import { ClientWrapper } from './clientWrapper' + +export interface StackSummary + extends RequiredProps { + DriftInformation: RequiredProps +} + +export type StackResource = RequiredProps + +export interface DescribeStackResourcesOutput extends CloudFormation.DescribeStackResourcesOutput { + StackResources: StackResource[] +} +export class CloudFormationClient extends ClientWrapper { + public constructor(regionCode: string) { + super(regionCode, CloudFormation.CloudFormationClient) + } + + public async deleteStack(name: string): Promise { + return await this.makeRequest(CloudFormation.DeleteStackCommand, { StackName: name }) + } + + public async describeType(typeName: string): Promise { + return await this.makeRequest(CloudFormation.DescribeTypeCommand, { TypeName: typeName }) + } + + public async *listStacks( + statusFilter: CloudFormation.StackStatus[] = ['CREATE_COMPLETE', 'UPDATE_COMPLETE'] + ): AsyncIterableIterator { + const request: CloudFormation.ListStacksInput = { + StackStatusFilter: statusFilter, + } + + do { + const response: CloudFormation.ListStacksOutput = await this.makeRequest( + CloudFormation.ListStacksCommand, + request + ) + + const filteredResponse = response.StackSummaries?.filter(isStackSummary) + if (filteredResponse && filteredResponse.length > 0) { + yield* filteredResponse + } + + request.NextToken = response.NextToken + } while (request.NextToken) + } + + public listAllStacks(request: CloudFormation.ListStacksInput = {}): AsyncCollection { + return this.makePaginatedRequest(CloudFormation.paginateListStacks, request, (page) => page.StackSummaries).map( + (s) => s.filter(isStackSummary) + ) + } + + public async *listTypes(): AsyncIterableIterator { + const request: CloudFormation.ListTypesInput = { + DeprecatedStatus: 'LIVE', + Type: 'RESOURCE', + Visibility: 'PUBLIC', + } + + do { + const response: CloudFormation.ListTypesOutput = await this.makeRequest( + CloudFormation.ListTypesCommand, + request + ) + + if (response.TypeSummaries) { + yield* response.TypeSummaries + } + + request.NextToken = response.NextToken + } while (request.NextToken) + } + + public async describeStackResources(name: string): Promise { + return await this.makeRequest(CloudFormation.DescribeStackResourcesCommand, { StackName: name }) + } +} + +function isStackSummary(s: CloudFormation.StackSummary | undefined): s is StackSummary { + return ( + isNonNullable(s) && + hasProps(s, 'StackName', 'CreationTime', 'StackStatus', 'DriftInformation') && + hasProps(s.DriftInformation, 'StackDriftStatus') + ) +} diff --git a/packages/core/src/shared/clients/cloudFormationClient.ts b/packages/core/src/shared/clients/cloudFormationClient.ts deleted file mode 100644 index 19c7ff5aa48..00000000000 --- a/packages/core/src/shared/clients/cloudFormationClient.ts +++ /dev/null @@ -1,98 +0,0 @@ -/*! - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -import { CloudFormation } from 'aws-sdk' -import globals from '../extensionGlobals' -import { AsyncCollection } from '../utilities/asyncCollection' -import { pageableToCollection } from '../utilities/collectionUtils' -import { ClassToInterfaceType, isNonNullable } from '../utilities/tsUtils' - -export type CloudFormationClient = ClassToInterfaceType -export class DefaultCloudFormationClient { - public constructor(public readonly regionCode: string) {} - - public async deleteStack(name: string): Promise { - const client = await this.createSdkClient() - - await client - .deleteStack({ - StackName: name, - }) - .promise() - } - - public async describeType(typeName: string): Promise { - const client = await this.createSdkClient() - - return await client - .describeType({ - Type: 'RESOURCE', - TypeName: typeName, - }) - .promise() - } - - public async *listStacks( - statusFilter: string[] = ['CREATE_COMPLETE', 'UPDATE_COMPLETE'] - ): AsyncIterableIterator { - const client = await this.createSdkClient() - - const request: CloudFormation.ListStacksInput = { - StackStatusFilter: statusFilter, - } - - do { - const response: CloudFormation.ListStacksOutput = await client.listStacks(request).promise() - - if (response.StackSummaries) { - yield* response.StackSummaries - } - - request.NextToken = response.NextToken - } while (request.NextToken) - } - - public listAllStacks(request: CloudFormation.ListStacksInput = {}): AsyncCollection { - const client = this.createSdkClient() - const requester = async (req: CloudFormation.ListStacksInput) => (await client).listStacks(req).promise() - const collection = pageableToCollection(requester, request, 'NextToken', 'StackSummaries') - - return collection.filter(isNonNullable) - } - - public async *listTypes(): AsyncIterableIterator { - const client = await this.createSdkClient() - - const request: CloudFormation.ListTypesInput = { - DeprecatedStatus: 'LIVE', - Type: 'RESOURCE', - Visibility: 'PUBLIC', - } - - do { - const response: CloudFormation.ListTypesOutput = await client.listTypes(request).promise() - - if (response.TypeSummaries) { - yield* response.TypeSummaries - } - - request.NextToken = response.NextToken - } while (request.NextToken) - } - - public async describeStackResources(name: string): Promise { - const client = await this.createSdkClient() - - return await client - .describeStackResources({ - StackName: name, - }) - .promise() - } - - private async createSdkClient(): Promise { - return await globals.sdkClientBuilder.createAwsService(CloudFormation, undefined, this.regionCode) - } -} diff --git a/packages/core/src/shared/sam/deploy.ts b/packages/core/src/shared/sam/deploy.ts index 4746a6a8660..ea0c3056fae 100644 --- a/packages/core/src/shared/sam/deploy.ts +++ b/packages/core/src/shared/sam/deploy.ts @@ -8,7 +8,7 @@ import { AWSTreeNodeBase } from '../treeview/nodes/awsTreeNodeBase' import { TreeNode, isTreeNode } from '../treeview/resourceTreeDataProvider' import globals from '../../shared/extensionGlobals' import { ToolkitError } from '../../shared/errors' -import { DefaultCloudFormationClient } from '../clients/cloudFormationClient' +import { CloudFormationClient } from '../clients/cloudFormation' import { S3Client } from '../clients/s3' import { samDeployUrl } from '../constants' import { getSpawnEnv } from '../env/resolveEnv' @@ -115,8 +115,7 @@ export class DeployWizard extends CompositeWizard { paramsSource === ParamsSource.Specify || paramsSource === ParamsSource.SpecifyAndSave, }) this.form.stackName.bindPrompter( - ({ region }) => - createStackPrompter(new DefaultCloudFormationClient(region!), deployMementoRootKey, samDeployUrl), + ({ region }) => createStackPrompter(new CloudFormationClient(region!), deployMementoRootKey, samDeployUrl), { showWhen: ({ paramsSource }) => paramsSource === ParamsSource.Specify || paramsSource === ParamsSource.SpecifyAndSave, diff --git a/packages/core/src/shared/sam/sync.ts b/packages/core/src/shared/sam/sync.ts index 99c614ac4d2..60c742e9171 100644 --- a/packages/core/src/shared/sam/sync.ts +++ b/packages/core/src/shared/sam/sync.ts @@ -10,7 +10,7 @@ import * as path from 'path' import * as localizedText from '../localizedText' import { S3Client } from '../clients/s3' import { DataQuickPickItem, createMultiPick, createQuickPick } from '../ui/pickerPrompter' -import { DefaultCloudFormationClient } from '../clients/cloudFormationClient' +import { CloudFormationClient } from '../clients/cloudFormation' import * as CloudFormation from '../cloudformation/cloudformation' import { DefaultEcrClient } from '../clients/ecrClient' import { createRegionPrompter } from '../ui/common/region' @@ -217,8 +217,7 @@ export class SyncWizard extends CompositeWizard { }) this.form.stackName.bindPrompter( - ({ region }) => - createStackPrompter(new DefaultCloudFormationClient(region!), syncMementoRootKey, samSyncUrl), + ({ region }) => createStackPrompter(new CloudFormationClient(region!), syncMementoRootKey, samSyncUrl), { showWhen: ({ paramsSource }) => paramsSource === ParamsSource.Specify || paramsSource === ParamsSource.SpecifyAndSave, diff --git a/packages/core/src/shared/ui/sam/stackPrompter.ts b/packages/core/src/shared/ui/sam/stackPrompter.ts index 12eeec6ca72..be1350489c5 100644 --- a/packages/core/src/shared/ui/sam/stackPrompter.ts +++ b/packages/core/src/shared/ui/sam/stackPrompter.ts @@ -4,7 +4,7 @@ */ import { StackSummary } from 'aws-sdk/clients/cloudformation' import { getAwsConsoleUrl } from '../../awsConsole' -import { DefaultCloudFormationClient } from '../../clients/cloudFormationClient' +import { CloudFormationClient } from '../../clients/cloudFormation' import * as vscode from 'vscode' import { createCommonButtons } from '../buttons' import { createQuickPick } from '../pickerPrompter' @@ -27,11 +27,7 @@ const canShowStack = (s: StackSummary) => * @returns A quick pick prompter configured for stack selection * */ -export function createStackPrompter( - client: DefaultCloudFormationClient, - mementoRootKey: string, - samCommandUrl: vscode.Uri -) { +export function createStackPrompter(client: CloudFormationClient, mementoRootKey: string, samCommandUrl: vscode.Uri) { const recentStack = getRecentResponse(mementoRootKey, client.regionCode, 'stackName') const consoleUrl = getAwsConsoleUrl('cloudformation', client.regionCode) const items = client.listAllStacks().map((stacks) => diff --git a/packages/core/src/test/dynamicResources/awsResourceManager.test.ts b/packages/core/src/test/dynamicResources/awsResourceManager.test.ts index 014a0291b61..b2e52d7dd43 100644 --- a/packages/core/src/test/dynamicResources/awsResourceManager.test.ts +++ b/packages/core/src/test/dynamicResources/awsResourceManager.test.ts @@ -13,16 +13,16 @@ import { ResourceNode } from '../../dynamicResources/explorer/nodes/resourceNode import { ResourceTypeNode } from '../../dynamicResources/explorer/nodes/resourceTypeNode' import { formatResourceModel, AwsResourceManager } from '../../dynamicResources/awsResourceManager' import { CloudControlClient } from '../../shared/clients/cloudControl' -import { CloudFormationClient, DefaultCloudFormationClient } from '../../shared/clients/cloudFormationClient' +import { CloudFormationClient } from '../../shared/clients/cloudFormation' import { makeTemporaryToolkitFolder, readFileAsString } from '../../shared/filesystemUtilities' import { FakeExtensionContext } from '../fakeExtensionContext' import { existsSync } from 'fs' // eslint-disable-line no-restricted-imports import { ResourceTypeMetadata } from '../../dynamicResources/model/resources' import globals from '../../shared/extensionGlobals' import { Stub, stub } from '../utilities/stubber' -import { CloudFormation } from 'aws-sdk' import * as CloudControl from '@aws-sdk/client-cloudcontrol' import { fs } from '../../shared' +import { DescribeTypeOutput } from '@aws-sdk/client-cloudformation' describe('ResourceManager', function () { let sandbox: sinon.SinonSandbox @@ -52,7 +52,7 @@ describe('ResourceManager', function () { cloudControl = stub(CloudControlClient, { regionCode: '', }) - cloudFormation = stub(DefaultCloudFormationClient, { + cloudFormation = stub(CloudFormationClient, { regionCode: '', }) sandbox = sinon.createSandbox() @@ -238,7 +238,7 @@ describe('ResourceManager', function () { }) cloudFormation.describeType.callsFake(async (name: string) => { if (name === fakeTypeName) { - return { Schema: '{}' } as any as CloudFormation.DescribeTypeOutput + return { Schema: '{}' } as any as DescribeTypeOutput } throw new Error() }) diff --git a/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts b/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts index 8898bdf6b5f..46850b9577f 100644 --- a/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts +++ b/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts @@ -7,14 +7,14 @@ import assert from 'assert' import * as vscode from 'vscode' import { ResourcesNode } from '../../../dynamicResources/explorer/nodes/resourcesNode' import { ResourceTypeNode } from '../../../dynamicResources/explorer/nodes/resourceTypeNode' -import { CloudFormationClient } from '../../../shared/clients/cloudFormationClient' +import { CloudFormationClient } from '../../../shared/clients/cloudFormation' import { assertNodeListOnlyHasPlaceholderNode } from '../../utilities/explorerNodeAssertions' import { asyncGenerator } from '../../../shared/utilities/collectionUtils' -import { CloudFormation } from 'aws-sdk' import { CloudControlClient } from '../../../shared/clients/cloudControl' import { Settings } from '../../../shared/settings' import { ResourcesSettings } from '../../../dynamicResources/commands/configure' import sinon from 'sinon' +import { TypeSummary } from '@aws-sdk/client-cloudformation' const unsortedText = ['zebra', 'Antelope', 'aardvark', 'elephant'] const sortedText = ['aardvark', 'Antelope', 'elephant', 'zebra'] @@ -101,8 +101,8 @@ describe('ResourcesNode', function () { function prepareMock(resourceTypes: string[]) { const listStub = sinon.stub().returns( - asyncGenerator( - resourceTypes.map((resourceType) => { + asyncGenerator( + resourceTypes.map((resourceType) => { return { TypeName: resourceType, } diff --git a/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts b/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts index 2eac7d75ecc..8cbeedf25f3 100644 --- a/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts +++ b/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts @@ -4,7 +4,6 @@ */ import assert from 'assert' -import { CloudFormation } from 'aws-sdk' import * as os from 'os' import { CloudFormationNode, @@ -12,7 +11,7 @@ import { contextValueCloudformationLambdaFunction, } from '../../../lambda/explorer/cloudFormationNodes' import { LambdaFunctionNode } from '../../../lambda/explorer/lambdaFunctionNode' -import { DefaultCloudFormationClient } from '../../../shared/clients/cloudFormationClient' +import { CloudFormationClient, StackResource, StackSummary } from '../../../shared/clients/cloudFormation' import { DefaultLambdaClient } from '../../../shared/clients/lambdaClient' import globals from '../../../shared/extensionGlobals' import { TestAWSTreeNode } from '../../shared/treeview/nodes/testAWSTreeNode' @@ -34,7 +33,7 @@ function createLambdaClient(...functionNames: string[]) { } function createCloudFormationClient(...stackNames: string[]) { - const client = stub(DefaultCloudFormationClient, { regionCode }) + const client = stub(CloudFormationClient, { regionCode }) client.describeStackResources.resolves({ StackResources: [] }) client.listStacks.returns( asyncGenerator( @@ -44,6 +43,9 @@ function createCloudFormationClient(...stackNames: string[]) { StackName: name, CreationTime: new globals.clock.Date(), StackStatus: 'CREATE_COMPLETE', + DriftInformation: { + StackDriftStatus: 'UNKNOWN', + }, } }) ) @@ -53,12 +55,15 @@ function createCloudFormationClient(...stackNames: string[]) { } describe('CloudFormationStackNode', function () { - function createStackSummary() { + function createStackSummary(): StackSummary { return { CreationTime: new globals.clock.Date(), StackId: '1', StackName: 'myStack', StackStatus: 'UPDATE_COMPLETE', + DriftInformation: { + StackDriftStatus: 'UNKNOWN', + }, } } @@ -72,11 +77,11 @@ describe('CloudFormationStackNode', function () { return new CloudFormationStackNode(parentNode, regionCode, summary, lambdaClient, cloudFormationClient) } - function generateStackResources(...functionNames: string[]): CloudFormation.StackResource[] { + function generateStackResources(...functionNames: string[]): StackResource[] { return functionNames.map((name) => ({ PhysicalResourceId: name, LogicalResourceId: name, - ResourceStatus: 'CREATED', + ResourceStatus: 'CREATE_COMPLETE', ResourceType: 'Lambda::Function', Timestamp: new globals.clock.Date(), })) diff --git a/packages/core/src/test/shared/sam/deploy.test.ts b/packages/core/src/test/shared/sam/deploy.test.ts index a1566e7cda3..3928f50ceb7 100644 --- a/packages/core/src/test/shared/sam/deploy.test.ts +++ b/packages/core/src/test/shared/sam/deploy.test.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ import * as vscode from 'vscode' -import { CloudFormation, S3 } from 'aws-sdk' +import { S3Bucket } from '../../../shared/clients/s3' import { AppNode } from '../../../awsService/appBuilder/explorer/nodes/appNode' import { assertTelemetry, getWorkspaceFolder, TestFolder } from '../../testUtil' import { DeployParams, DeployWizard, getDeployWizard, runDeploy } from '../../../shared/sam/deploy' @@ -13,19 +13,18 @@ import { samconfigCompleteData, samconfigInvalidData, validTemplateData } from ' import * as SamUtilsModule from '../../../shared/sam/utils' import assert from 'assert' import { getTestWindow } from '../vscode/window' -import { DefaultCloudFormationClient } from '../../../shared/clients/cloudFormationClient' +import { CloudFormationClient } from '../../../shared/clients/cloudFormation' import { intoCollection } from '../../../shared/utilities/collectionUtils' import { clickBackButton, createPromptHandler, PrompterTester } from '../wizards/prompterTester' import { RegionNode } from '../../../awsexplorer/regionNode' import { createTestRegionProvider } from '../regions/testUtil' import { S3Client } from '../../../shared/clients/s3' -import * as CloudFormationClientModule from '../../../shared/clients/cloudFormationClient' +import * as CloudFormationClientModule from '../../../shared/clients/cloudFormation' import * as S3ClientModule from '../../../shared/clients/s3' import * as ProcessUtilsModule from '../../../shared/utilities/processUtils' import * as ProcessTerminalModule from '../../../shared/sam/processTerminal' import * as ResolveEnvModule from '../../../shared/env/resolveEnv' import * as SamConfiModule from '../../../shared/sam/config' -import { RequiredProps } from '../../../shared/utilities/tsUtils' import { UserAgent as __UserAgent } from '@smithy/types' import { SamAppLocation } from '../../../awsService/appBuilder/explorer/samProject' @@ -42,7 +41,7 @@ describe('SAM DeployWizard', async function () { let workspaceFolder: vscode.WorkspaceFolder let templateFile: vscode.Uri - let mockDefaultCFNClient: sinon.SinonStubbedInstance + let mockDefaultCFNClient: sinon.SinonStubbedInstance let mockDefaultS3Client: sinon.SinonStubbedInstance beforeEach(async () => { @@ -52,8 +51,8 @@ describe('SAM DeployWizard', async function () { sandbox = sinon.createSandbox() // Simulate return of deployed stacks - mockDefaultCFNClient = sandbox.createStubInstance(CloudFormationClientModule.DefaultCloudFormationClient) - sandbox.stub(CloudFormationClientModule, 'DefaultCloudFormationClient').returns(mockDefaultCFNClient) + mockDefaultCFNClient = sandbox.createStubInstance(CloudFormationClientModule.CloudFormationClient) + sandbox.stub(CloudFormationClientModule, 'CloudFormationClient').returns(mockDefaultCFNClient) mockDefaultCFNClient.listAllStacks.returns(intoCollection(stackSummaries)) // Simulate return of list bucket @@ -1287,32 +1286,28 @@ describe('SAM Deploy', () => { }) }) -const s3BucketListSummary: Array< - RequiredProps & { - readonly region: string - } -> = [ - { Name: 'stack-1-bucket', region: 'us-west-2' }, - { Name: 'stack-2-bucket', region: 'us-west-2' }, - { Name: 'stack-3-bucket', region: 'us-west-2' }, +const s3BucketListSummary: Array & { readonly region: string }> = [ + { Name: 'stack-1-bucket', region: 'us-west-2', Arn: 'arn-1' }, + { Name: 'stack-2-bucket', region: 'us-west-2', Arn: 'arn-2' }, + { Name: 'stack-3-bucket', region: 'us-west-2', Arn: 'arn-3' }, ] -const stackSummaries: CloudFormation.StackSummary[][] = [ +const stackSummaries: CloudFormationClientModule.StackSummary[][] = [ [ { StackName: 'stack1', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as CloudFormationClientModule.StackSummary, { StackName: 'stack2', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as CloudFormationClientModule.StackSummary, { StackName: 'stack3', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as CloudFormationClientModule.StackSummary, ], ] diff --git a/packages/core/src/test/shared/sam/sync.test.ts b/packages/core/src/test/shared/sam/sync.test.ts index c53fb883736..843b0e0bbcd 100644 --- a/packages/core/src/test/shared/sam/sync.test.ts +++ b/packages/core/src/test/shared/sam/sync.test.ts @@ -11,7 +11,7 @@ import * as SamConfigModule from '../../../shared/sam/config' import * as ResolveEnvModule from '../../../shared/env/resolveEnv' import * as ProcessUtilsModule from '../../../shared/utilities/processUtils' import { CancellationError } from '../../../shared/utilities/timeoutUtils' -import * as CloudFormationClientModule from '../../../shared/clients/cloudFormationClient' +import * as CloudFormationClientModule from '../../../shared/clients/cloudFormation' import { createEnvironmentPrompter, @@ -44,8 +44,7 @@ import { getTestWindow } from '../vscode/window' import { S3Client } from '../../../shared/clients/s3' import { RequiredProps } from '../../../shared/utilities/tsUtils' import S3 from 'aws-sdk/clients/s3' -import { DefaultCloudFormationClient } from '../../../shared/clients/cloudFormationClient' -import CloudFormation from 'aws-sdk/clients/cloudformation' +import { CloudFormationClient } from '../../../shared/clients/cloudFormation' import { intoCollection } from '../../../shared/utilities/collectionUtils' import { SamConfig, Environment, parseConfig } from '../../../shared/sam/config' import { RegionProvider } from '../../../shared/regions/regionProvider' @@ -132,7 +131,7 @@ describe('SAM SyncWizard', async () => { let workspaceFolder: vscode.WorkspaceFolder let templateFile: vscode.Uri - let mockDefaultCFNClient: sinon.SinonStubbedInstance + let mockDefaultCFNClient: sinon.SinonStubbedInstance let mockDefaultS3Client: sinon.SinonStubbedInstance let registry: CloudFormationTemplateRegistry @@ -143,8 +142,8 @@ describe('SAM SyncWizard', async () => { sandbox = sinon.createSandbox() // Simulate return of deployed stacks - mockDefaultCFNClient = sandbox.createStubInstance(CloudFormationClientModule.DefaultCloudFormationClient) - sandbox.stub(CloudFormationClientModule, 'DefaultCloudFormationClient').returns(mockDefaultCFNClient) + mockDefaultCFNClient = sandbox.createStubInstance(CloudFormationClientModule.CloudFormationClient) + sandbox.stub(CloudFormationClientModule, 'CloudFormationClient').returns(mockDefaultCFNClient) mockDefaultCFNClient.listAllStacks.returns(intoCollection(stackSummaries)) // Simulate return of list bucket @@ -1075,7 +1074,7 @@ describe('SAM runSync', () => { let spyWriteSamconfigGlobal: sinon.SinonSpy let spyRunInterminal: sinon.SinonSpy - let mockDefaultCFNClient: sinon.SinonStubbedInstance + let mockDefaultCFNClient: sinon.SinonStubbedInstance let mockDefaultS3Client: sinon.SinonStubbedInstance let registry: CloudFormationTemplateRegistry @@ -1093,8 +1092,8 @@ describe('SAM runSync', () => { await registry.addItem(templateFile) // Simulate return of deployed stacks - mockDefaultCFNClient = sandbox.createStubInstance(CloudFormationClientModule.DefaultCloudFormationClient) - sandbox.stub(CloudFormationClientModule, 'DefaultCloudFormationClient').returns(mockDefaultCFNClient) + mockDefaultCFNClient = sandbox.createStubInstance(CloudFormationClientModule.CloudFormationClient) + sandbox.stub(CloudFormationClientModule, 'CloudFormationClient').returns(mockDefaultCFNClient) mockDefaultCFNClient.listAllStacks.returns(intoCollection(stackSummaries)) // Simulate return of list bucket @@ -2184,22 +2183,22 @@ const s3BucketListSummary: Array< { Name: 'stack-3-bucket', region: 'us-west-2' }, ] -const stackSummaries: CloudFormation.StackSummary[][] = [ +const stackSummaries: CloudFormationClientModule.StackSummary[][] = [ [ { StackName: 'stack1', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as CloudFormationClientModule.StackSummary, { StackName: 'stack2', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as CloudFormationClientModule.StackSummary, { StackName: 'stack3', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as CloudFormationClientModule.StackSummary, ], ] diff --git a/packages/core/src/test/shared/ui/sam/stackPrompter.test.ts b/packages/core/src/test/shared/ui/sam/stackPrompter.test.ts index 37237030d7e..206d26db9e1 100644 --- a/packages/core/src/test/shared/ui/sam/stackPrompter.test.ts +++ b/packages/core/src/test/shared/ui/sam/stackPrompter.test.ts @@ -4,13 +4,12 @@ */ import assert from 'assert' -import CloudFormation from 'aws-sdk/clients/cloudformation' import sinon from 'sinon' import * as vscode from 'vscode' import * as AwsConsoleModule from '../../../../shared/awsConsole' import * as SamUtilsModule from '../../../../shared/sam/utils' import * as ButtonsModule from '../../../../shared/ui/buttons' -import { DefaultCloudFormationClient } from '../../../../shared/clients/cloudFormationClient' +import { CloudFormationClient, StackSummary } from '../../../../shared/clients/cloudFormation' import { samSyncUrl } from '../../../../shared/constants' import { createStackPrompter } from '../../../../shared/ui/sam/stackPrompter' import { intoCollection } from '../../../../shared/utilities/collectionUtils' @@ -18,7 +17,7 @@ import { sleep } from '../../../../shared/utilities/timeoutUtils' describe('createStackPrompter', () => { let sandbox: sinon.SinonSandbox - const cfnClient = new DefaultCloudFormationClient('us-east-1') + const cfnClient = new CloudFormationClient('us-east-1') const mementoRootKey = 'samcli.sync.params' beforeEach(() => { @@ -31,23 +30,23 @@ describe('createStackPrompter', () => { it('should create a prompter with existing stacks', async () => { // Arrange - const stackSummaries: CloudFormation.StackSummary[][] = [ + const stackSummaries: StackSummary[][] = [ [ { StackName: 'stack1', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as StackSummary, { StackName: 'stack2', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as StackSummary, { StackName: 'stack3', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), - } as CloudFormation.StackSummary, + } as StackSummary, ], ] const expectedItems = [