Skip to content

Commit 54ef6df

Browse files
Merge master into feature/q-dev-execution
2 parents 3ffb52d + 5f816f1 commit 54ef6df

File tree

8 files changed

+171
-10
lines changed

8 files changed

+171
-10
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ export class SshKeyPair {
4545

4646
public static async generateSshKeyPair(keyPath: string): Promise<void> {
4747
const keyGenerated = await SshKeyPair.tryKeyTypes(keyPath, ['ed25519', 'rsa'])
48-
await SshKeyPair.assertGenerated(keyPath, keyGenerated)
4948
// Should already be the case, but just in case we assert permissions.
5049
// skip on Windows since it only allows write permission to be changed.
5150
if (!globals.isWeb && os.platform() !== 'win32') {
5251
await fs.chmod(keyPath, 0o600)
52+
await SshKeyPair.assertGenerated(keyPath, keyGenerated)
5353
}
5454
}
5555
/**

packages/core/src/codewhisperer/commands/basicCommands.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ import { ToolkitError, getTelemetryReason, getTelemetryReasonDesc } from '../../
4141
import { isRemoteWorkspace } from '../../shared/vscode/env'
4242
import { isBuilderIdConnection } from '../../auth/connection'
4343
import globals from '../../shared/extensionGlobals'
44-
import { getVscodeCliPath, tryRun } from '../../shared/utilities/pathFind'
44+
import { getVscodeCliPath } from '../../shared/utilities/pathFind'
4545
import { setContext } from '../../shared/vscode/setContext'
46+
import { tryRun } from '../../shared/utilities/pathFind'
4647

4748
const MessageTimeOut = 5_000
4849

packages/core/src/shared/remoteSession.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface MissingTool {
3030
readonly reason?: string
3131
}
3232

33-
const minimumSsmActions = [
33+
export const minimumSsmActions = [
3434
'ssmmessages:CreateControlChannel',
3535
'ssmmessages:CreateDataChannel',
3636
'ssmmessages:OpenControlChannel',

packages/core/src/shared/utilities/pathFind.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ export async function findTypescriptCompiler(): Promise<string | undefined> {
115115
* Gets the configured `ssh` path, or falls back to "ssh" (not absolute),
116116
* or tries common locations, or returns undefined.
117117
*/
118-
export async function findSshPath(): Promise<string | undefined> {
119-
if (sshPath !== undefined) {
118+
export async function findSshPath(useCache: boolean = true): Promise<string | undefined> {
119+
if (useCache && sshPath !== undefined) {
120120
return sshPath
121121
}
122122

@@ -133,7 +133,7 @@ export async function findSshPath(): Promise<string | undefined> {
133133
continue
134134
}
135135
if (await tryRun(p, ['-G', 'x'], 'noresult' /* "ssh -G" prints quasi-sensitive info. */)) {
136-
sshPath = p
136+
sshPath = useCache ? p : sshPath
137137
return p
138138
}
139139
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import assert from 'assert'
6+
import { minimumSsmActions, promptToAddInlinePolicy } from '../../shared/remoteSession'
7+
import { IamClient } from '../../shared/clients/iamClient'
8+
import { getTestWindow } from './vscode/window'
9+
import { cancel } from '../../shared'
10+
11+
describe('minimumSsmActions', function () {
12+
it('should contain minimal actions needed for ssm connection', function () {
13+
assert.deepStrictEqual(minimumSsmActions, [
14+
'ssmmessages:CreateControlChannel',
15+
'ssmmessages:CreateDataChannel',
16+
'ssmmessages:OpenControlChannel',
17+
'ssmmessages:OpenDataChannel',
18+
'ssm:DescribeAssociation',
19+
'ssm:ListAssociations',
20+
'ssm:UpdateInstanceInformation',
21+
])
22+
})
23+
24+
it('prompts the user for confirmation before adding policies and allow cancels', async function () {
25+
getTestWindow().onDidShowMessage((message) => {
26+
assert.ok(message.message.includes('add'), 'should prompt to add policies')
27+
getTestWindow().getFirstMessage().selectItem(cancel)
28+
})
29+
const added = await promptToAddInlinePolicy({} as IamClient, 'roleArnTest')
30+
assert.ok(!added, 'should not add policies by default')
31+
})
32+
})

packages/core/src/test/shared/utilities/pathFind.test.ts

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@ import assert from 'assert'
77
import * as vscode from 'vscode'
88
import * as os from 'os'
99
import * as path from 'path'
10-
1110
import * as testutil from '../../testUtil'
12-
import { findTypescriptCompiler, getVscodeCliPath } from '../../../shared/utilities/pathFind'
1311
import { fs } from '../../../shared'
12+
import { findSshPath, findTypescriptCompiler, getVscodeCliPath, tryRun } from '../../../shared/utilities/pathFind'
13+
import { isCI, isWin } from '../../../shared/vscode/env'
1414

1515
describe('pathFind', function () {
1616
it('findTypescriptCompiler()', async function () {
17-
const iswin = process.platform === 'win32'
1817
const workspace = vscode.workspace.workspaceFolders![0]
19-
const tscNodemodules = path.join(workspace.uri.fsPath, `foo/bar/node_modules/.bin/tsc${iswin ? '.cmd' : ''}`)
18+
const tscNodemodules = path.join(workspace.uri.fsPath, `foo/bar/node_modules/.bin/tsc${isWin() ? '.cmd' : ''}`)
2019
await fs.delete(tscNodemodules, { force: true })
2120

2221
// The test workspace normally doesn't have node_modules so this will
@@ -42,4 +41,90 @@ describe('pathFind', function () {
4241
const regex = /bin[\\\/](code|code-insiders)$/
4342
assert.ok(regex.test(vscPath), `expected regex ${regex} to match: "${vscPath}"`)
4443
})
44+
45+
describe('findSshPath', function () {
46+
let previousPath: string | undefined
47+
48+
beforeEach(function () {
49+
previousPath = process.env.PATH
50+
})
51+
52+
afterEach(function () {
53+
process.env.PATH = previousPath
54+
})
55+
56+
it('first tries ssh in $PATH (Non-Windows)', async function () {
57+
// skip on windows because ssh in path will never work with .exe extension.
58+
if (isWin()) {
59+
return
60+
}
61+
const workspace = await testutil.createTestWorkspaceFolder()
62+
const fakeSshPath = path.join(workspace.uri.fsPath, `ssh`)
63+
64+
process.env.PATH = workspace.uri.fsPath
65+
const firstResult = await findSshPath(false)
66+
67+
await testutil.createExecutableFile(fakeSshPath, '')
68+
69+
const secondResult = await findSshPath(false)
70+
71+
assert.notStrictEqual(firstResult, secondResult)
72+
assert.strictEqual(secondResult, 'ssh')
73+
})
74+
75+
it('only returns valid executable ssh path (Non-Windows)', async function () {
76+
if (isWin()) {
77+
return
78+
}
79+
// On non-windows, we can overwrite path and create our own executable to find.
80+
const workspace = await testutil.createTestWorkspaceFolder()
81+
const fakeSshPath = path.join(workspace.uri.fsPath, `ssh`)
82+
83+
process.env.PATH = workspace.uri.fsPath
84+
85+
await testutil.createExecutableFile(fakeSshPath, '')
86+
87+
const ssh = await findSshPath(false)
88+
assert.ok(ssh)
89+
const result = await tryRun(ssh, [], 'yes')
90+
assert.ok(result)
91+
})
92+
93+
it('caches result from previous runs (Non-Windows)', async function () {
94+
if (isWin()) {
95+
return
96+
}
97+
// On non-windows, we can overwrite path and create our own executable to find.
98+
const workspace = await testutil.createTestWorkspaceFolder()
99+
// We move the ssh to a temp directory temporarily to test if cache works.
100+
const fakeSshPath = path.join(workspace.uri.fsPath, `ssh`)
101+
102+
process.env.PATH = workspace.uri.fsPath
103+
104+
await testutil.createExecutableFile(fakeSshPath, '')
105+
106+
const ssh1 = (await findSshPath(true))!
107+
108+
await fs.delete(fakeSshPath)
109+
110+
const ssh2 = await findSshPath(true)
111+
112+
assert.strictEqual(ssh1, ssh2)
113+
})
114+
115+
it('finds valid executable path (Windows CI)', async function () {
116+
// Don't want to be messing with System32 on peoples local machines.
117+
if (!isWin() || !isCI()) {
118+
return
119+
}
120+
const expectedPathInCI = 'C:/Windows/System32/OpenSSH/ssh.exe'
121+
122+
if (!(await fs.exists(expectedPathInCI))) {
123+
await testutil.createExecutableFile(expectedPathInCI, '')
124+
}
125+
const ssh = (await findSshPath(true))!
126+
const result = await tryRun(ssh, ['-G', 'x'], 'noresult')
127+
assert.ok(result)
128+
})
129+
})
45130
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import assert from 'assert'
6+
import { createExecutableFile, createTestWorkspaceFolder, copyEnv } from '../../testUtil'
7+
import path from 'path'
8+
import { fs } from '../../../shared'
9+
import { isWin } from '../../../shared/vscode/env'
10+
import { tryRun } from '../../../shared/utilities/pathFind'
11+
12+
describe('copyEnv', function () {
13+
it('modifies the node environment variables (Non-Windows)', function () {
14+
// PATH returns undefined on Windows.
15+
if (isWin()) {
16+
this.skip()
17+
}
18+
19+
const originalPath = copyEnv().PATH
20+
const fakePath = 'fakePath'
21+
process.env.PATH = fakePath
22+
assert.strictEqual(copyEnv().PATH, fakePath)
23+
24+
process.env.PATH = originalPath
25+
assert.strictEqual(copyEnv().PATH, originalPath)
26+
})
27+
})
28+
29+
describe('createExecutableFile', function () {
30+
it('creates a file that can be executed', async function () {
31+
const tempDir = await createTestWorkspaceFolder()
32+
const filePath = path.join(tempDir.uri.fsPath, `exec${isWin() ? '.cmd' : ''}`)
33+
await createExecutableFile(filePath, '')
34+
35+
const result = await tryRun(filePath, [], 'yes')
36+
assert.ok(result)
37+
await fs.delete(tempDir.uri, { force: true, recursive: true })
38+
})
39+
})

packages/core/src/test/testUtil.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,7 @@ export function tryRegister(command: DeclaredCommand<() => Promise<any>>) {
630630
export function getFetchStubWithResponse(response: Partial<Response>) {
631631
return stub(request, 'fetch').returns({ response: new Promise((res, _) => res(response)) } as any)
632632
}
633+
634+
export function copyEnv(): NodeJS.ProcessEnv {
635+
return { ...process.env }
636+
}

0 commit comments

Comments
 (0)