Skip to content

Commit adc4129

Browse files
committed
Merge branch 'hkobew/ec2/testRefactor' into feature/ec2
2 parents 44af406 + 8e33287 commit adc4129

File tree

2 files changed

+130
-31
lines changed

2 files changed

+130
-31
lines changed

src/ec2/model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ export class Ec2ConnectionManager {
184184
this.throwGeneralConnectionError(selection, err as Error)
185185
}
186186
}
187+
187188
public async prepareEc2RemoteEnvWithProgress(selection: Ec2Selection, remoteUser: string): Promise<Ec2RemoteEnv> {
188189
const timeout = new Timeout(60000)
189190
await showMessageWithCancel('AWS: Opening remote connection...', timeout)
@@ -254,7 +255,7 @@ export class Ec2ConnectionManager {
254255
})
255256
}
256257

257-
protected async getRemoteUser(instanceId: string) {
258+
public async getRemoteUser(instanceId: string) {
258259
const osName = await this.ssmClient.getTargetPlatformName(instanceId)
259260
if (osName === 'Amazon Linux') {
260261
return 'ec2-user'

src/test/ec2/model.test.ts

Lines changed: 128 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,124 @@ import * as assert from 'assert'
77
import * as sinon from 'sinon'
88
import { Ec2ConnectionManager } from '../../ec2/model'
99
import { SsmClient } from '../../shared/clients/ssmClient'
10+
import { Ec2Client } from '../../shared/clients/ec2Client'
1011
import { Ec2Selection } from '../../ec2/prompter'
1112
import { ToolkitError } from '../../shared/errors'
1213
import { IAM } from 'aws-sdk'
14+
import { SshKeyPair } from '../../ec2/sshKeyPair'
1315
import { DefaultIamClient } from '../../shared/clients/iamClient'
1416

1517
describe('Ec2ConnectClient', function () {
18+
let client: Ec2ConnectionManager
19+
20+
before(function () {
21+
client = new Ec2ConnectionManager('test-region')
22+
})
23+
24+
describe('getAttachedIamRole', async function () {
25+
it('only returns role if recieves ARN from instance profile', async function () {
26+
let role: IAM.Role | undefined
27+
const getInstanceProfileStub = sinon.stub(Ec2Client.prototype, 'getAttachedIamInstanceProfile')
28+
29+
getInstanceProfileStub.resolves({ Arn: 'thisIsAnArn' })
30+
sinon
31+
.stub(DefaultIamClient.prototype, 'getIAMRoleFromInstanceProfile')
32+
.resolves({ Arn: 'ThisIsARoleArn' } as IAM.Role)
33+
34+
role = await client.getAttachedIamRole('test-instance')
35+
assert.ok(role)
36+
assert.ok(role.Arn)
37+
38+
getInstanceProfileStub.resolves({})
39+
role = await client.getAttachedIamRole('test-instance')
40+
assert.strictEqual(role, undefined)
41+
sinon.restore()
42+
})
43+
})
44+
45+
describe('hasProperPolicies', async function () {
46+
it('correctly determines if proper policies are included', async function () {
47+
async function assertAcceptsPolicies(policies: IAM.Policy[], expectedResult: boolean) {
48+
sinon.stub(DefaultIamClient.prototype, 'listAttachedRolePolicies').resolves(policies)
49+
50+
const result = await client.hasProperPolicies('')
51+
assert.strictEqual(result, expectedResult)
52+
53+
sinon.restore()
54+
}
55+
await assertAcceptsPolicies(
56+
[{ PolicyName: 'name' }, { PolicyName: 'name2' }, { PolicyName: 'name3' }],
57+
false
58+
)
59+
await assertAcceptsPolicies(
60+
[
61+
{ PolicyName: 'AmazonSSMManagedInstanceCore' },
62+
{ PolicyName: 'AmazonSSMManagedEC2InstanceDefaultPolicy' },
63+
],
64+
true
65+
)
66+
await assertAcceptsPolicies([{ PolicyName: 'AmazonSSMManagedEC2InstanceDefaultPolicy' }], false)
67+
await assertAcceptsPolicies([{ PolicyName: 'AmazonSSMManagedEC2InstanceDefaultPolicy' }], false)
68+
})
69+
70+
it('throws error when sdk throws error', async function () {
71+
sinon.stub(DefaultIamClient.prototype, 'listAttachedRolePolicies').throws(new ToolkitError('error'))
72+
73+
try {
74+
await client.hasProperPolicies('')
75+
assert.ok(false)
76+
} catch {
77+
assert.ok(true)
78+
}
79+
80+
sinon.restore()
81+
})
82+
})
83+
84+
describe('isInstanceRunning', async function () {
85+
it('only returns true with the instance is running', async function () {
86+
sinon.stub(Ec2Client.prototype, 'getInstanceStatus').callsFake(async (input: string) => input.split(':')[0])
87+
88+
const actualFirstResult = await client.isInstanceRunning('running:instance')
89+
const actualSecondResult = await client.isInstanceRunning('stopped:instance')
90+
91+
assert.strictEqual(true, actualFirstResult)
92+
assert.strictEqual(false, actualSecondResult)
93+
sinon.restore()
94+
})
95+
})
96+
1697
describe('handleStartSessionError', async function () {
17-
let client: Ec2ConnectionManager
1898
let instanceSelection: Ec2Selection
1999

20100
before(function () {
21-
client = new Ec2ConnectionManager('test-region')
22101
instanceSelection = { instanceId: 'testInstance', region: 'testRegion' }
23102
})
24103

25104
it('throws EC2SSMStatus error if instance is not running', async function () {
26105
sinon.stub(Ec2ConnectionManager.prototype, 'isInstanceRunning').resolves(false)
106+
27107
try {
28108
await client.checkForStartSessionError(instanceSelection)
29109
assert.ok(false)
30110
} catch (err) {
31111
assert.strictEqual((err as ToolkitError).code, 'EC2SSMStatus')
32112
}
113+
33114
sinon.restore()
34115
})
35116

36117
it('throws EC2SSMPermission error if instance is running but has no role', async function () {
37118
sinon.stub(Ec2ConnectionManager.prototype, 'isInstanceRunning').resolves(true)
38119
sinon.stub(Ec2ConnectionManager.prototype, 'getAttachedIamRole').resolves(undefined)
120+
39121
try {
40122
await client.checkForStartSessionError(instanceSelection)
41123
assert.ok(false)
42124
} catch (err) {
43125
assert.strictEqual((err as ToolkitError).code, 'EC2SSMPermission')
44126
}
127+
45128
sinon.restore()
46129
})
47130

@@ -50,12 +133,14 @@ describe('Ec2ConnectClient', function () {
50133
sinon.stub(Ec2ConnectionManager.prototype, 'getAttachedIamRole').resolves({ Arn: 'testRole' } as IAM.Role)
51134
sinon.stub(Ec2ConnectionManager.prototype, 'hasProperPolicies').resolves(true)
52135
sinon.stub(SsmClient.prototype, 'getInstanceAgentPingStatus').resolves('offline')
136+
53137
try {
54138
await client.checkForStartSessionError(instanceSelection)
55139
assert.ok(false)
56140
} catch (err) {
57141
assert.strictEqual((err as ToolkitError).code, 'EC2SSMAgentStatus')
58142
}
143+
59144
sinon.restore()
60145
})
61146

@@ -64,49 +149,62 @@ describe('Ec2ConnectClient', function () {
64149
sinon.stub(Ec2ConnectionManager.prototype, 'getAttachedIamRole').resolves({ Arn: 'testRole' } as IAM.Role)
65150
sinon.stub(Ec2ConnectionManager.prototype, 'hasProperPolicies').resolves(true)
66151
sinon.stub(SsmClient.prototype, 'getInstanceAgentPingStatus').resolves('Online')
152+
67153
assert.doesNotThrow(async () => await client.checkForStartSessionError(instanceSelection))
154+
68155
sinon.restore()
69156
})
70157
})
71158

72-
describe('hasProperPolicies', async function () {
73-
let realClient: Ec2ConnectionManager
159+
describe('sendSshKeysToInstance', async function () {
160+
it('calls the sdk with the proper parameters', async function () {
161+
const sendCommandStub = sinon.stub(SsmClient.prototype, 'sendCommandAndWait')
162+
163+
sinon.stub(SshKeyPair, 'generateSshKeyPair')
164+
sinon.stub(SshKeyPair.prototype, 'getPublicKey').resolves('test-key')
165+
166+
const testSelection = {
167+
instanceId: 'test-id',
168+
region: 'test-region',
169+
}
170+
const mockKeys = await SshKeyPair.getSshKeyPair('')
171+
await client.sendSshKeyToInstance(testSelection, mockKeys, '')
172+
sinon.assert.calledWith(sendCommandStub, testSelection.instanceId, 'AWS-RunShellScript')
173+
sinon.restore()
174+
})
175+
})
176+
177+
describe('getRemoteUser', async function () {
178+
let getTargetPlatformNameStub: sinon.SinonStub<[target: string], Promise<string>>
74179

75180
before(async function () {
76-
realClient = new Ec2ConnectionManager('test-region')
181+
getTargetPlatformNameStub = sinon.stub(SsmClient.prototype, 'getTargetPlatformName')
77182
})
78183

79-
it('correctly determines if proper policies are included', async function () {
80-
async function assertAcceptsPolicies(policies: IAM.Policy[], expectedResult: boolean) {
81-
sinon.stub(DefaultIamClient.prototype, 'listAttachedRolePolicies').resolves(policies)
82-
const result = await realClient.hasProperPolicies('')
83-
assert.strictEqual(result, expectedResult)
84-
sinon.restore()
85-
}
86-
await assertAcceptsPolicies(
87-
[{ PolicyName: 'name' }, { PolicyName: 'name2' }, { PolicyName: 'name3' }],
88-
false
89-
)
90-
await assertAcceptsPolicies(
91-
[
92-
{ PolicyName: 'AmazonSSMManagedInstanceCore' },
93-
{ PolicyName: 'AmazonSSMManagedEC2InstanceDefaultPolicy' },
94-
],
95-
true
96-
)
97-
await assertAcceptsPolicies([{ PolicyName: 'AmazonSSMManagedEC2InstanceDefaultPolicy' }], false)
98-
await assertAcceptsPolicies([{ PolicyName: 'AmazonSSMManagedEC2InstanceDefaultPolicy' }], false)
184+
after(async function () {
185+
sinon.restore()
99186
})
100187

101-
it('throws error when sdk throws error', async function () {
102-
sinon.stub(DefaultIamClient.prototype, 'listAttachedRolePolicies').throws(new ToolkitError('error'))
188+
it('identifies the user for ubuntu as ubuntu', async function () {
189+
getTargetPlatformNameStub.resolves('Ubuntu')
190+
const remoteUser = await client.getRemoteUser('testInstance')
191+
assert.strictEqual(remoteUser, 'ubuntu')
192+
})
193+
194+
it('identifies the user for amazon linux as ec2-user', async function () {
195+
getTargetPlatformNameStub.resolves('Amazon Linux')
196+
const remoteUser = await client.getRemoteUser('testInstance')
197+
assert.strictEqual(remoteUser, 'ec2-user')
198+
})
199+
200+
it('throws error when not given known OS', async function () {
201+
getTargetPlatformNameStub.resolves('ThisIsNotARealOs!')
103202
try {
104-
await realClient.hasProperPolicies('')
203+
await client.getRemoteUser('testInstance')
105204
assert.ok(false)
106-
} catch {
205+
} catch (exception) {
107206
assert.ok(true)
108207
}
109-
sinon.restore()
110208
})
111209
})
112210
})

0 commit comments

Comments
 (0)