Skip to content

Commit c6e3b5f

Browse files
committed
refactor: migrate type refs
1 parent 22e6b41 commit c6e3b5f

File tree

11 files changed

+74
-53
lines changed

11 files changed

+74
-53
lines changed

packages/core/src/awsService/apprunner/wizards/imageRepositoryWizard.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { AppRunner, IAM } from 'aws-sdk'
6+
import { AppRunner } from 'aws-sdk'
77
import { createCommonButtons, QuickInputButton, QuickInputToggleButton } from '../../../shared/ui/buttons'
88
import { toArrayAsync } from '../../../shared/utilities/collectionUtils'
99
import { EcrClient, EcrRepository } from '../../../shared/clients/ecrClient'
@@ -17,7 +17,7 @@ import * as nls from 'vscode-nls'
1717
import { WizardForm } from '../../../shared/wizards/wizardForm'
1818
import { createVariablesPrompter } from '../../../shared/ui/common/variablesPrompter'
1919
import { makeDeploymentButton } from './deploymentButton'
20-
import { IamClient } from '../../../shared/clients/iam'
20+
import { IamClient, IamRole } from '../../../shared/clients/iam'
2121
import { createRolePrompter } from '../../../shared/ui/common/roles'
2222
import { getLogger } from '../../../shared/logger/logger'
2323
import { getAppRunnerCreateServiceDocUrl, isCloud9 } from '../../../shared/extensionUtilities'
@@ -35,7 +35,7 @@ interface ImagePrompterOptions {
3535
extraButtons?: QuickInputButton<void | WizardControl>
3636
}
3737

38-
function createEcrRole(client: IamClient): Promise<IAM.Role> {
38+
function createEcrRole(client: IamClient): Promise<IamRole> {
3939
const policy = {
4040
Version: '2008-10-17',
4141
Statement: [
@@ -59,7 +59,7 @@ function createEcrRole(client: IamClient): Promise<IAM.Role> {
5959
AssumeRolePolicyDocument: JSON.stringify(policy),
6060
})
6161
.then((resp) => {
62-
const role = resp.Role
62+
const role = resp.Role! as IamRole
6363
return client.attachRolePolicy({ RoleName: role.RoleName, PolicyArn: ecrPolicy }).then(() => role)
6464
})
6565
}
@@ -257,13 +257,14 @@ export class AppRunnerImageRepositoryWizard extends Wizard<AppRunner.SourceConfi
257257
constructor(ecrClient: EcrClient, iamClient: IamClient, autoDeployButton = makeDeploymentButton()) {
258258
super()
259259
const form = this.form
260-
const createAccessRolePrompter = () => {
261-
return createRolePrompter(iamClient, {
260+
const createAccessRolePrompter: () => picker.QuickPickPrompter<string> = () => {
261+
const prompter = createRolePrompter(iamClient, {
262262
title: localize('AWS.apprunner.createService.selectRole.title', 'Select a role to pull from ECR'),
263263
helpUrl: getAppRunnerCreateServiceDocUrl(),
264264
roleFilter: (role) => (role.AssumeRolePolicyDocument ?? '').includes(appRunnerEcrEntity),
265265
createRole: createEcrRole.bind(undefined, iamClient),
266-
}).transform((resp) => resp.Arn)
266+
})
267+
return prompter.transform((resp) => resp.Arn)
267268
}
268269

269270
form.ImageRepository.applyBoundForm(createImageRepositorySubForm(ecrClient, autoDeployButton))

packages/core/src/awsService/ec2/model.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55
import * as vscode from 'vscode'
6-
import { IAM } from 'aws-sdk'
76
import { Ec2Selection } from './prompter'
87
import { getOrInstallCli } from '../../shared/utilities/cliUtils'
98
import { isCloud9 } from '../../shared/extensionUtilities'
@@ -18,7 +17,7 @@ import {
1817
openRemoteTerminal,
1918
promptToAddInlinePolicy,
2019
} from '../../shared/remoteSession'
21-
import { IamClient } from '../../shared/clients/iam'
20+
import { IamClient, IamRole } from '../../shared/clients/iam'
2221
import { ErrorInformation } from '../../shared/errors'
2322
import {
2423
sshAgentSocketVariable,
@@ -95,7 +94,7 @@ export class Ec2Connecter implements vscode.Disposable {
9594
return this.sessionManager.isConnectedTo(instanceId)
9695
}
9796

98-
public async getAttachedIamRole(instanceId: string): Promise<IAM.Role | undefined> {
97+
public async getAttachedIamRole(instanceId: string): Promise<IamRole | undefined> {
9998
const IamInstanceProfile = await this.ec2Client.getAttachedIamInstanceProfile(instanceId)
10099
if (IamInstanceProfile && IamInstanceProfile.Arn) {
101100
const IamRole = await this.iamClient.getIAMRoleFromInstanceProfile(IamInstanceProfile.Arn)

packages/core/src/shared/clients/clientWrapper.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ export abstract class ClientWrapper<C extends AwsClient> implements vscode.Dispo
3232
command: new (o: CommandInput) => Command,
3333
commandOptions: CommandInput
3434
) {
35-
const client = this.getClient()
36-
return await client.send(new command(commandOptions))
35+
return await this.getClient().send(new command(commandOptions))
3736
}
3837

3938
protected makePaginatedRequest<CommandInput extends object, CommandOutput extends object, Output extends object>(

packages/core/src/shared/clients/iam.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
CreateRoleResponse,
1313
EvaluationResult,
1414
GetInstanceProfileCommand,
15+
GetInstanceProfileCommandOutput,
1516
IAMClient,
1617
ListRolesRequest,
1718
paginateListAttachedRolePolicies,
@@ -26,17 +27,24 @@ import { AsyncCollection } from '../utilities/asyncCollection'
2627
import { ToolkitError } from '../errors'
2728
import { ClientWrapper } from './clientWrapper'
2829

30+
export interface IamRole extends Role {
31+
RoleName: string
32+
Arn: string
33+
}
34+
2935
export class IamClient extends ClientWrapper<IAMClient> {
3036
public constructor(public override readonly regionCode: string) {
3137
super(regionCode, IAMClient)
3238
}
3339

34-
public getRoles(request: ListRolesRequest = {}, maxPages: number = 500): AsyncCollection<Role[]> {
35-
return this.makePaginatedRequest(paginateListRoles, request, (p) => p.Roles).limit(maxPages)
40+
public getRoles(request: ListRolesRequest = {}, maxPages: number = 500): AsyncCollection<IamRole[]> {
41+
return this.makePaginatedRequest(paginateListRoles, request, (p) => p.Roles)
42+
.limit(maxPages)
43+
.map((roles) => roles.filter(hasRequiredFields))
3644
}
3745

3846
/** Gets all roles. */
39-
public async resolveRoles(request: ListRolesRequest = {}): Promise<Role[]> {
47+
public async resolveRoles(request: ListRolesRequest = {}): Promise<IamRole[]> {
4048
return this.getRoles(request).flatten().promise()
4149
}
4250

@@ -86,11 +94,15 @@ export class IamClient extends ClientWrapper<IAMClient> {
8694
)
8795
}
8896

89-
public async getIAMRoleFromInstanceProfile(instanceProfileArn: string): Promise<Role> {
90-
const response = await this.makeRequest(GetInstanceProfileCommand, {
97+
public async getIAMRoleFromInstanceProfile(instanceProfileArn: string): Promise<IamRole> {
98+
const response: GetInstanceProfileCommandOutput = await this.makeRequest(GetInstanceProfileCommand, {
9199
InstanceProfileName: this.getFriendlyName(instanceProfileArn),
92100
})
93-
if (response.InstanceProfile.Roles.length === 0) {
101+
if (
102+
!response.InstanceProfile?.Roles ||
103+
response.InstanceProfile.Roles.length === 0 ||
104+
!hasRequiredFields(response.InstanceProfile.Roles[0])
105+
) {
94106
throw new ToolkitError(`Failed to find IAM role associated with Instance profile ${instanceProfileArn}`)
95107
}
96108
return response.InstanceProfile.Roles[0]
@@ -104,3 +116,7 @@ export class IamClient extends ClientWrapper<IAMClient> {
104116
})
105117
}
106118
}
119+
120+
function hasRequiredFields(role: Role): role is IamRole {
121+
return role.RoleName !== undefined && role.Arn !== undefined
122+
}

packages/core/src/shared/remoteSession.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import { pushIf } from './utilities/collectionUtils'
2020
import { ChildProcess } from './utilities/processUtils'
2121
import { findSshPath, getVscodeCliPath } from './utilities/pathFind'
2222
import { IamClient } from './clients/iam'
23-
import { IAM } from 'aws-sdk'
2423
import { getIdeProperties } from './extensionUtilities'
24+
import { EvaluationResult } from '@aws-sdk/client-iam'
2525

2626
const policyAttachDelay = 5000
2727

@@ -243,7 +243,7 @@ function getSsmPolicyDocument() {
243243
}`
244244
}
245245

246-
export async function getDeniedSsmActions(client: IamClient, roleArn: string): Promise<IAM.EvaluationResult[]> {
246+
export async function getDeniedSsmActions(client: IamClient, roleArn: string): Promise<EvaluationResult[]> {
247247
const deniedActions = await client.getDeniedActions({
248248
PolicySourceArn: roleArn,
249249
ActionNames: minimumSsmActions,

packages/core/src/shared/ui/common/roles.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { IAM } from 'aws-sdk'
7-
import { IamClient } from '../../clients/iam'
6+
import { IamClient, IamRole } from '../../clients/iam'
87
import { createCommonButtons, createPlusButton, createRefreshButton } from '../buttons'
98
import { createQuickPick, DataQuickPickItem, QuickPickPrompter } from '../pickerPrompter'
109
import * as nls from 'vscode-nls'
@@ -21,19 +20,19 @@ interface RolePrompterOptions {
2120
readonly title?: string
2221
readonly helpUrl?: string | vscode.Uri
2322
readonly noRoleDetail?: string
24-
readonly roleFilter?: (role: IAM.Role) => boolean
25-
readonly createRole?: () => Promise<IAM.Role>
23+
readonly roleFilter?: (role: IamRole) => boolean
24+
readonly createRole?: () => Promise<IamRole>
2625
}
2726

28-
export function createRolePrompter(client: IamClient, options: RolePrompterOptions = {}): QuickPickPrompter<IAM.Role> {
29-
const placeholderItem: DataQuickPickItem<IAM.Role> = {
27+
export function createRolePrompter(client: IamClient, options: RolePrompterOptions = {}): QuickPickPrompter<IamRole> {
28+
const placeholderItem: DataQuickPickItem<IamRole> = {
3029
label: localize('AWS.rolePrompter.noRoles.title', 'No valid roles found'),
3130
data: WIZARD_BACK,
3231
detail: options.noRoleDetail,
3332
}
3433

3534
const loadItems = () => {
36-
const filterRoles = (roles: IAM.Role[]) => (options.roleFilter ? roles.filter(options.roleFilter) : roles)
35+
const filterRoles = (roles: IamRole[]) => (options.roleFilter ? roles.filter(options.roleFilter) : roles)
3736

3837
return client
3938
.getRoles()
@@ -62,7 +61,7 @@ export function createRolePrompter(client: IamClient, options: RolePrompterOptio
6261
}
6362

6463
function addCreateRoleButton(
65-
prompter: QuickPickPrompter<IAM.Role>,
64+
prompter: QuickPickPrompter<IamRole>,
6665
createRole: RolePrompterOptions['createRole']
6766
): typeof prompter {
6867
if (!createRole) {

packages/core/src/stepFunctions/utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import * as nls from 'vscode-nls'
66
const localize = nls.loadMessageBundle()
77

8-
import { IAM, StepFunctions } from 'aws-sdk'
8+
import { StepFunctions } from 'aws-sdk'
99
import * as vscode from 'vscode'
1010
import { StepFunctionsClient } from '../shared/clients/stepFunctionsClient'
1111
import { fileExists } from '../shared/filesystemUtilities'
@@ -20,6 +20,7 @@ import { HttpResourceFetcher } from '../shared/resourcefetcher/httpResourceFetch
2020
import globals from '../shared/extensionGlobals'
2121
import { fromExtensionManifest } from '../shared/settings'
2222
import { fs } from '../shared/fs/fs'
23+
import { IamRole } from '../shared/clients/iam'
2324

2425
const documentSettings: DocumentLanguageSettings = { comments: 'error', trailingCommas: 'error' }
2526
const languageService = getLanguageService({})
@@ -211,7 +212,7 @@ export async function* listStateMachines(
211212
* Checks if the given IAM Role is assumable by AWS Step Functions.
212213
* @param role The IAM role to check
213214
*/
214-
export function isStepFunctionsRole(role: IAM.Role): boolean {
215+
export function isStepFunctionsRole(role: IamRole): boolean {
215216
const stepFunctionsSevicePrincipal: string = 'states.amazonaws.com'
216217
const assumeRolePolicyDocument: string | undefined = role.AssumeRolePolicyDocument
217218

packages/core/src/test/awsService/ec2/model.test.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import { SsmClient } from '../../../shared/clients/ssm'
1010
import { Ec2Client } from '../../../shared/clients/ec2'
1111
import { Ec2Selection } from '../../../awsService/ec2/prompter'
1212
import { ToolkitError } from '../../../shared/errors'
13-
import { IAM } from 'aws-sdk'
1413
import { SshKeyPair } from '../../../awsService/ec2/sshKeyPair'
15-
import { IamClient } from '../../../shared/clients/iam'
14+
import { IamClient, IamRole } from '../../../shared/clients/iam'
1615
import { assertNoTelemetryMatch, createTestWorkspaceFolder } from '../../testUtil'
1716
import { fs } from '../../../shared'
1817
import path from 'path'
@@ -31,13 +30,11 @@ describe('Ec2ConnectClient', function () {
3130

3231
describe('getAttachedIamRole', async function () {
3332
it('only returns role if receives ARN from instance profile', async function () {
34-
let role: IAM.Role | undefined
33+
let role: IamRole | undefined
3534
const getInstanceProfileStub = sinon.stub(Ec2Client.prototype, 'getAttachedIamInstanceProfile')
3635

3736
getInstanceProfileStub.resolves({ Arn: 'thisIsAnArn' })
38-
sinon
39-
.stub(IamClient.prototype, 'getIAMRoleFromInstanceProfile')
40-
.resolves({ Arn: 'ThisIsARoleArn' } as IAM.Role)
37+
sinon.stub(IamClient.prototype, 'getIAMRoleFromInstanceProfile').resolves(getFakeRole('ThisIsARoleArn'))
4138

4239
role = await client.getAttachedIamRole('test-instance')
4340
assert.ok(role)
@@ -116,7 +113,7 @@ describe('Ec2ConnectClient', function () {
116113

117114
it('throws EC2SSMAgent error if instance is running and has IAM Role, but agent is not running', async function () {
118115
sinon.stub(Ec2Connecter.prototype, 'isInstanceRunning').resolves(true)
119-
sinon.stub(Ec2Connecter.prototype, 'getAttachedIamRole').resolves({ Arn: 'testRole' } as IAM.Role)
116+
sinon.stub(Ec2Connecter.prototype, 'getAttachedIamRole').resolves(getFakeRole('testRole'))
120117
sinon.stub(Ec2Connecter.prototype, 'hasProperPermissions').resolves(true)
121118
sinon.stub(SsmClient.prototype, 'getInstanceAgentPingStatus').resolves('offline')
122119

@@ -141,7 +138,7 @@ describe('Ec2ConnectClient', function () {
141138

142139
it('does not throw an error if all checks pass', async function () {
143140
sinon.stub(Ec2Connecter.prototype, 'isInstanceRunning').resolves(true)
144-
sinon.stub(Ec2Connecter.prototype, 'getAttachedIamRole').resolves({ Arn: 'testRole' } as IAM.Role)
141+
sinon.stub(Ec2Connecter.prototype, 'getAttachedIamRole').resolves(getFakeRole('testRole'))
145142
sinon.stub(Ec2Connecter.prototype, 'hasProperPermissions').resolves(true)
146143
sinon.stub(SsmClient.prototype, 'getInstanceAgentPingStatus').resolves('Online')
147144

@@ -307,3 +304,13 @@ describe('getRemoveLinesCommand', async function () {
307304
assert.throws(() => getRemoveLinesCommand('pat/tern', 'macOS', 'test.txt'))
308305
})
309306
})
307+
308+
function getFakeRole(Arn: string) {
309+
return {
310+
RoleName: 'hasArn',
311+
Arn,
312+
Path: 'thisIsAPath',
313+
RoleId: '1',
314+
CreateDate: new Date(),
315+
}
316+
}

packages/core/src/test/shared/clients/iamClient.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,25 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { IAM } from 'aws-sdk'
76
import assert from 'assert'
87
import * as sinon from 'sinon'
98
import { IamClient } from '../../../shared/clients/iam'
9+
import { SimulatePolicyResponse, SimulatePrincipalPolicyRequest } from '@aws-sdk/client-iam'
1010

1111
describe('iamClient', function () {
1212
describe('getDeniedActions', async function () {
1313
const iamClient: IamClient = new IamClient('us-west-2')
14-
const request: IAM.SimulatePrincipalPolicyRequest = {
14+
const request: SimulatePrincipalPolicyRequest = {
1515
PolicySourceArn: 'taskRoleArn1234',
1616
ActionNames: ['example:permission'],
1717
}
18-
const correctPermissionsResponse = {
18+
const correctPermissionsResponse: SimulatePolicyResponse = {
1919
EvaluationResults: [{ EvalActionName: 'example:permission', EvalDecision: 'allowed' }],
2020
}
21-
const incorrectPermissionsResponse = {
22-
EvaluationResults: [{ EvalActionName: 'example:permission', EvalDecision: 'denied' }],
21+
const incorrectPermissionsResponse: SimulatePolicyResponse = {
22+
EvaluationResults: [{ EvalActionName: 'example:permission', EvalDecision: 'explicitDeny' }],
2323
}
24-
const organizationsDenyPermissionsResponse = {
24+
const organizationsDenyPermissionsResponse: SimulatePolicyResponse = {
2525
EvaluationResults: [
2626
{
2727
EvalActionName: 'example:permission',

packages/core/src/test/shared/ui/prompters/roles.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
import * as vscode from 'vscode'
77
import * as sinon from 'sinon'
88
import assert from 'assert'
9-
import { IAM } from 'aws-sdk'
10-
import { IamClient } from '../../../../shared/clients/iam'
9+
import { IamClient, IamRole } from '../../../../shared/clients/iam'
1110
import { createQuickPickPrompterTester, QuickPickPrompterTester } from '../testUtils'
1211
import { createRolePrompter } from '../../../../shared/ui/common/roles'
1312
import { toCollection } from '../../../../shared/utilities/asyncCollection'
@@ -17,9 +16,9 @@ import { getOpenExternalStub } from '../../../globalSetup.test'
1716
const helpUri = vscode.Uri.parse('https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html')
1817

1918
describe('createRolePrompter', function () {
20-
let roles: IAM.Role[]
21-
let newRole: IAM.Role
22-
let tester: QuickPickPrompterTester<IAM.Role>
19+
let roles: IamRole[]
20+
let newRole: IamRole
21+
let tester: QuickPickPrompterTester<IamRole>
2322

2423
beforeEach(function () {
2524
roles = [

0 commit comments

Comments
 (0)