Skip to content
Merged
Show file tree
Hide file tree
Changes from 231 commits
Commits
Show all changes
233 commits
Select commit Hold shift + click to select a range
b7399c5
rename existing command to openTerminal
Hweinstock Jul 7, 2023
588594d
add new command for ec2 instance remote-connect
Hweinstock Jul 7, 2023
1c57e45
register new command so that it does not throw error
Hweinstock Jul 7, 2023
814ba96
refactor to make terminal distinction clearer
Hweinstock Jul 7, 2023
b5d2c88
add prompt for new selection
Hweinstock Jul 7, 2023
08ba106
enable connection to ec2, start generalizing CodeCatalyst work
Hweinstock Jul 10, 2023
3caba57
abstract general error msg to its own function
Hweinstock Jul 10, 2023
f2894ba
refactor more code catalyst code
Hweinstock Jul 10, 2023
f0f5086
refactor code to better mirror the code catalyst implementaton
Hweinstock Jul 10, 2023
5be1f8d
add a cancellable loading bar on open
Hweinstock Jul 10, 2023
3c096cd
rename variable to be more explicit
Hweinstock Jul 10, 2023
13b2bc0
refactor to have a with-progress method layer
Hweinstock Jul 10, 2023
8fbbc8d
refactor ssh config into the ssh file
Hweinstock Jul 10, 2023
57dbde6
convert regExp property to abstract
Hweinstock Jul 10, 2023
fb9f1e8
reformat string in proxycommand
Hweinstock Jul 11, 2023
f94fe64
implement basic tests on sshconfig mock object
Hweinstock Jul 11, 2023
fdec798
split up verify ssh host into pieces
Hweinstock Jul 11, 2023
545b8a7
refactor the sshconfig to make more testable, add more tests
Hweinstock Jul 11, 2023
4f8c680
refactor tests to distinguish between command and proxyCommand
Hweinstock Jul 11, 2023
222fcfd
avoid hard-coding in test
Hweinstock Jul 11, 2023
0e5f7a2
avoid other hard-coding in tests
Hweinstock Jul 11, 2023
e87f24d
change simple function to be in lined
Hweinstock Jul 11, 2023
3764b4a
change command wording to be less clunky.
Hweinstock Jul 11, 2023
1c3be08
change command phrasing to mirror ssh extension
Hweinstock Jul 11, 2023
93e23f0
Merge branch 'hkobew/ec2/remoteConnect/newCommand' into hkobew/ec2/re…
Hweinstock Jul 11, 2023
d742eef
Merge branch 'hkobew/ec2/remoteConnect/connect' into hkobew/ec2/remot…
Hweinstock Jul 11, 2023
056e807
remove commented out code
Hweinstock Jul 12, 2023
153bf62
update command file with icon
Hweinstock Jul 13, 2023
bd71166
update context value for parent node
Hweinstock Jul 13, 2023
e027e40
handle case where parent node is passed to command
Hweinstock Jul 13, 2023
9d62154
change outdated prompter text
Hweinstock Jul 13, 2023
f28809b
refactor commands to own file
Hweinstock Jul 13, 2023
3cc9aa6
add start command to package.json files
Hweinstock Jul 13, 2023
732778f
add command to start the instance
Hweinstock Jul 13, 2023
2cbb723
fix typo in which method was being invoked
Hweinstock Jul 13, 2023
26faa78
merge upstream changes
Hweinstock Jul 13, 2023
ea30d86
refactor prompter and commands file
Hweinstock Jul 13, 2023
52a2fde
add tests for new structure of prompter
Hweinstock Jul 13, 2023
8fac525
refactor prompter code to be more testable
Hweinstock Jul 13, 2023
004ac0b
add baseline test to item provider
Hweinstock Jul 13, 2023
f85f0ee
add instance filter and tests for it
Hweinstock Jul 13, 2023
29d6b62
remove duplication of determining if instance is running
Hweinstock Jul 13, 2023
506be9a
backtrack filter idea because it breaks pagination
Hweinstock Jul 13, 2023
2022004
implement start command
Hweinstock Jul 13, 2023
8560da2
move bulk of work to new file
Hweinstock Jul 13, 2023
9022ec2
add command for stopping instance
Hweinstock Jul 13, 2023
fd1703d
add functionality to stop instances
Hweinstock Jul 13, 2023
9e0c16e
refactor start/stop commands into a class
Hweinstock Jul 13, 2023
1f53a3f
add testing for checking instance status
Hweinstock Jul 13, 2023
eb92609
add reboot command
Hweinstock Jul 13, 2023
cec3ede
implement reboot extension
Hweinstock Jul 13, 2023
024eb7b
refactor to remove duplicate code
Hweinstock Jul 13, 2023
38559be
remove unnecessary async
Hweinstock Jul 13, 2023
b217377
expose command on explorer
Hweinstock Jul 13, 2023
19ad794
refactor to eliminate some duplicate implementation
Hweinstock Jul 14, 2023
7794b67
handle undefined node consistently
Hweinstock Jul 14, 2023
adae37b
add method to append status to instance retriever
Hweinstock Jul 14, 2023
d3a4276
refactor how we add fields to the ec2 instances
Hweinstock Jul 14, 2023
0772dd2
add tests for new helper functions in Ec2Client
Hweinstock Jul 14, 2023
b4c03c3
refactor tests to use the same test-data
Hweinstock Jul 14, 2023
b76e22f
add test for filter functionality
Hweinstock Jul 14, 2023
98f03fb
change prompter to filter based on instance status
Hweinstock Jul 14, 2023
6cc4cc5
add icons to QuickPick
Hweinstock Jul 14, 2023
d147b22
disallow rebooting stopped instance
Hweinstock Jul 14, 2023
d72f9c9
add icon entrypoints to start/stop/restart commands
Hweinstock Jul 14, 2023
bd709da
move icon determiner function to seperate file
Hweinstock Jul 14, 2023
bffa367
add icons to show if its running in explorer
Hweinstock Jul 14, 2023
8062ed6
limit commands to cases where they are dont throw error
Hweinstock Jul 14, 2023
f7999b1
limit explorer icons and refresh after
Hweinstock Jul 14, 2023
f2a7786
fix outdated test
Hweinstock Jul 17, 2023
cf05c8e
remove commands from command palette
Hweinstock Jul 17, 2023
f0900d7
refactor such that it only updates ec2 parent node
Hweinstock Jul 17, 2023
10566c1
update outdated test
Hweinstock Jul 17, 2023
2b749a3
add testing to ec2InstanceNode
Hweinstock Jul 17, 2023
bf25145
add another test for the update functionality
Hweinstock Jul 17, 2023
de97b43
update tests to use icons
Hweinstock Jul 17, 2023
1914fe8
implement core logic with basic tests
Hweinstock Jul 17, 2023
ce7beb9
refactor to key by node, rather than string
Hweinstock Jul 17, 2023
a5cf7f3
switch back to using instanceids to add more testing
Hweinstock Jul 17, 2023
177aa07
ensure timer stops with tests
Hweinstock Jul 18, 2023
dd82ff9
refactor tests to avoid polling before tests start
Hweinstock Jul 18, 2023
76eb0fd
refactor such that only instance node is refreshed
Hweinstock Jul 18, 2023
5ad533f
no stopping/starting on pending instances
Hweinstock Jul 18, 2023
6efd4fd
refactor sshConfig changes to their own new file
Hweinstock Jul 18, 2023
4a68497
move the creation of ssh section to parent abstract class
Hweinstock Jul 18, 2023
ba21411
move ensureConnect to shared file
Hweinstock Jul 18, 2023
5ec5496
move ensure valid method to shared file
Hweinstock Jul 18, 2023
6c03515
remove sub-classes
Hweinstock Jul 18, 2023
7e6c56e
switch scriptPrefix to a parameter
Hweinstock Jul 18, 2023
19d3e2c
use variable to name prefix of script
Hweinstock Jul 18, 2023
886a41e
add test for section created by sshConfig
Hweinstock Jul 18, 2023
a4a4626
construct regexp from script name
Hweinstock Jul 18, 2023
8b36799
move logFile location generator to general file
Hweinstock Jul 18, 2023
72ae902
refactor the ec2_connect script
Hweinstock Jul 18, 2023
b08bbdb
refactor script to include token for session
Hweinstock Jul 18, 2023
c4348b4
include session tokens in script env
Hweinstock Jul 18, 2023
02b2a2b
adding suport for documents in start session
Hweinstock Jul 18, 2023
e373be8
remove port number
Hweinstock Jul 18, 2023
0f2c01d
remove log file location where unused
Hweinstock Jul 19, 2023
718c402
clean up state after tests
Hweinstock Jul 19, 2023
a21d6f8
hide start/stop/reboot from command palette
Hweinstock Jul 19, 2023
60566f5
add functionality to generate keys
Hweinstock Jul 19, 2023
e15c0a2
implement sending keys to target instance, with hard coded dest file
Hweinstock Jul 19, 2023
41eade4
implement reading public key from KeyPair
Hweinstock Jul 20, 2023
33fbd79
add comment about hard coded path
Hweinstock Jul 20, 2023
8cb386d
fix some spacing
Hweinstock Jul 20, 2023
84fa815
update config to get it working
Hweinstock Jul 20, 2023
dca607e
cleanup some small things
Hweinstock Jul 20, 2023
f6ac8e3
add some testing
Hweinstock Jul 20, 2023
e15e184
clean up handling of key parameters to ssh config
Hweinstock Jul 21, 2023
6950712
updates tests to utilize sinon stub
Hweinstock Jul 21, 2023
d951675
remove references to code catatlyst in error/log messages
Hweinstock Jul 21, 2023
2a63ae3
pass remote username down from above
Hweinstock Jul 21, 2023
1087678
increase testing coverage for sshConfigSection
Hweinstock Jul 21, 2023
84ea20a
implement method to determine remote user
Hweinstock Jul 21, 2023
eed3a09
implement method for guessing the os
Hweinstock Jul 21, 2023
4b94c83
refactor to use ssm sdk to determine os
Hweinstock Jul 21, 2023
65ad6ac
check for permissions before trying the ssm sdk
Hweinstock Jul 21, 2023
febac95
fix to work on ubuntu
Hweinstock Jul 21, 2023
ee149b7
remove leftover log statement
Hweinstock Jul 21, 2023
d70c415
merge in master
Hweinstock Jul 21, 2023
aa56c93
refactor tests to use stub only where needed
Hweinstock Jul 24, 2023
90b248b
remove double restore in test file
Hweinstock Jul 24, 2023
950ca3c
test commenting out sshConfig tests
Hweinstock Jul 24, 2023
f17580d
add comment to import so that it runs
Hweinstock Jul 24, 2023
ac4e711
comment out other use of sinon stub for testing
Hweinstock Jul 24, 2023
7441de1
comment out test for reading ssh keys
Hweinstock Jul 24, 2023
ef427f2
comment out tests in the model file
Hweinstock Jul 24, 2023
a0cea9d
comment out entire codecatalyst tools file
Hweinstock Jul 24, 2023
740baf8
comment out all tests modified
Hweinstock Jul 24, 2023
c60d540
uncomment test files
Hweinstock Jul 24, 2023
2a08bb7
move ssh tests to their own file
Hweinstock Jul 24, 2023
24a25d0
uncomment tests related to the model
Hweinstock Jul 24, 2023
27179ab
move the rest of the the tests to the sshConfig file
Hweinstock Jul 24, 2023
a8a92ae
add codecatalyst label to relevant tests
Hweinstock Jul 24, 2023
d6896c1
rename file to mirror main class name in file
Hweinstock Jul 24, 2023
e201693
rename test file
Hweinstock Jul 24, 2023
3bbabd1
change path import structure
Hweinstock Jul 24, 2023
8a733e6
implement function to map instance profile to instance role
Hweinstock Jul 26, 2023
8a7e1ae
refactor error handling
Hweinstock Jul 26, 2023
9ac421f
clean up error handling
Hweinstock Jul 26, 2023
819203f
update tests to match the new behavior
Hweinstock Jul 26, 2023
65133a4
be extra explicit that Instance Profile is different from role.
Hweinstock Jul 26, 2023
de04def
throw if no roles associated with instance profile
Hweinstock Jul 26, 2023
9a55520
refactor to avoid duplicate service calls
Hweinstock Jul 26, 2023
b0c1f02
update and refactor tests to use sinon instead of homemade mocks
Hweinstock Jul 26, 2023
59e9f9c
merge in master
Hweinstock Jul 27, 2023
53a678b
Merge branch 'hkobew/ec2/remoteConnect/sshKeysNew' into hkobew/ec2/te…
Hweinstock Jul 27, 2023
0a26c22
merge in necessary pre-req
Hweinstock Jul 27, 2023
fc4af9e
refactor test file to use mocking framework
Hweinstock Jul 27, 2023
2f393c8
add coverage for the getAttachedIamRole method
Hweinstock Jul 27, 2023
6eb3450
reformat and rearrange tests
Hweinstock Jul 27, 2023
f9c5d91
refactor out shared piece
Hweinstock Jul 27, 2023
f72acc7
implement new version using permissions
Hweinstock Jul 27, 2023
19eb5d1
fix logic error
Hweinstock Jul 27, 2023
ca86046
update error message
Hweinstock Jul 27, 2023
57ad523
handle merge conflicts
Hweinstock Aug 5, 2023
dd05a0d
remove duplicate commands
Hweinstock Aug 5, 2023
40abd17
merge in upstream changes
Hweinstock Aug 7, 2023
ae3851c
merge in master
Hweinstock Aug 8, 2023
9cbcb48
remove duplicate commands in package.json
Hweinstock Aug 8, 2023
4d6cd41
remove duplicate terminal command
Hweinstock Aug 8, 2023
d4a2244
merge in master
Hweinstock Aug 10, 2023
ac6d473
make instance readonly on instance node
Hweinstock Aug 10, 2023
6cab577
add comment about not-readonly
Hweinstock Aug 10, 2023
a034dc3
refactor to allow for readonly instance with comment
Hweinstock Aug 10, 2023
2854015
merge in master
Hweinstock Aug 11, 2023
f21201f
merge in master, update imports
Sep 5, 2024
c9d6eff
update vscode.command usage
Hweinstock Sep 5, 2024
49efa8b
add changelog
Hweinstock Sep 5, 2024
0cc83e3
start to generalize polling set
Hweinstock Sep 5, 2024
996362c
minimize code dupe
Hweinstock Sep 5, 2024
1e6cdcf
cleanup
Hweinstock Sep 5, 2024
4e97666
generalize further, extend tests
Hweinstock Sep 5, 2024
9d9fa8d
fix linting problems
Hweinstock Sep 5, 2024
79b8f81
fix linting 2
Hweinstock Sep 6, 2024
681771e
Merge branch 'master' into hkobew/ec2/explorerUpdate
Hweinstock Sep 6, 2024
955308c
clean up inlining
Hweinstock Sep 6, 2024
341bff3
merge in upstream changes
Hweinstock Sep 6, 2024
e2ac9c8
remove merge relic
Hweinstock Sep 6, 2024
1a47575
add removed changes from merge
Hweinstock Sep 6, 2024
65b2ff2
implement w/ timeout
Hweinstock Sep 11, 2024
234a26d
remove outdated test case
Hweinstock Sep 11, 2024
8a16fa7
Merge branch 'hkobew/ec2/useActions' into hkobew/ec2/noDiskKey
Hweinstock Sep 11, 2024
b1f05f5
add deletion tests
Hweinstock Sep 11, 2024
57e887c
add progress bar
Hweinstock Sep 11, 2024
656a58c
attach lifetime to keys
Hweinstock Sep 11, 2024
61eb6bb
add tests for key expiration
Hweinstock Sep 11, 2024
cf70ff6
update key file permissions to match that used in aws ec2 instance co…
Hweinstock Sep 12, 2024
b77dc8d
move test files over
Hweinstock Sep 12, 2024
548f69e
move rest of changes from other branch
Hweinstock Sep 12, 2024
f152943
fix imports
Hweinstock Sep 12, 2024
1af46cd
update changelog
Hweinstock Sep 12, 2024
dda254c
merge in upstream changes
Hweinstock Sep 12, 2024
28798b6
move over changes
Hweinstock Sep 12, 2024
0e9d0e8
Merge branch 'hkobew/ec2/useActions' into hkobew/ec2/useActionsTemp
Hweinstock Sep 12, 2024
cdf23cb
remove system utilities since they are not used anymore
Hweinstock Sep 12, 2024
c3bfbf2
fix bug with priv/pub
Hweinstock Sep 12, 2024
1e7f0e8
add method in ssmClient to describe session status
Hweinstock Sep 13, 2024
987c9cf
force key overwrite
Hweinstock Sep 13, 2024
decca64
Merge branch 'hkobew/ec2/noDiskKey' into hkobew/ec2/cleanUpSSM
Hweinstock Sep 13, 2024
656ddaf
refactor such that connection manager keeps state
Hweinstock Sep 16, 2024
5cfa899
add in deactivation logic
Hweinstock Sep 16, 2024
e37a46f
merge in upstream changes
Hweinstock Sep 16, 2024
eab2f7d
update changelog
Hweinstock Sep 16, 2024
a8051de
remove code related to add inline policies
Hweinstock Sep 16, 2024
3efa868
remove outdated import
Hweinstock Sep 16, 2024
05b107b
Merge branch 'master' into hkobew/ec2/useActions
Hweinstock Sep 17, 2024
2e7c79f
Merge branch 'hkobew/ec2/useActions' into hkobew/ec2/noDiskKey
Hweinstock Sep 17, 2024
45b62e2
Merge branch 'hkobew/ec2/noDiskKey' into hkobew/ec2/cleanUpSSM
Hweinstock Sep 17, 2024
d204f23
refactor helpers out of commands.ts
Hweinstock Sep 17, 2024
887bcf4
add test cases for utility functions
Hweinstock Sep 17, 2024
e8bca90
add test case for connection manager map
Hweinstock Sep 17, 2024
2ac7bfe
add more tests for connection manager
Hweinstock Sep 17, 2024
47b8425
fix tests
Hweinstock Sep 17, 2024
3c3e01c
refactor into seperate class with testing
Hweinstock Sep 17, 2024
8db83d8
merge in upstream changes
Hweinstock Sep 23, 2024
dc315c0
clean up
Hweinstock Sep 23, 2024
6a4a452
make naming more consistent
Hweinstock Sep 23, 2024
585d846
fix changelog
Hweinstock Sep 23, 2024
6e2b3e2
fix test files
Hweinstock Sep 23, 2024
dc31929
refactor to avoid circular dependency
Hweinstock Sep 23, 2024
084c1b4
fix test case
Hweinstock Sep 23, 2024
4dd59ff
move shared data to one place
Hweinstock Sep 23, 2024
8aeb671
fix import
Hweinstock Sep 23, 2024
3d5e718
merge in upstream changes
Hweinstock Oct 15, 2024
50f9a77
refactor changes
Hweinstock Oct 15, 2024
5af92dc
remove old code
Hweinstock Oct 15, 2024
bcbb72d
fix malformed file
Hweinstock Oct 16, 2024
f94f46d
rename classes to avoid vague manager word
Hweinstock Oct 16, 2024
ce29252
merge in master
Hweinstock Oct 23, 2024
cf67383
merge in master
Hweinstock Oct 25, 2024
97723b7
undo package.json change
Hweinstock Oct 25, 2024
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
22 changes: 14 additions & 8 deletions packages/core/src/awsService/ec2/activation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as vscode from 'vscode'
import { ExtContext } from '../../shared/extensions'
import { Commands } from '../../shared/vscode/commands2'
import { telemetry } from '../../shared/telemetry/telemetry'
import { Ec2InstanceNode } from './explorer/ec2InstanceNode'
import { Ec2InstanceNode, tryRefreshNode } from './explorer/ec2InstanceNode'
import { copyTextCommand } from '../../awsexplorer/commands/copyText'
import { Ec2Node } from './explorer/ec2ParentNode'
import {
Expand All @@ -15,13 +15,15 @@ import {
rebootInstance,
startInstance,
stopInstance,
refreshExplorer,
openLogDocument,
linkToLaunchInstance,
openLogDocument,
} from './commands'
import { Ec2ConnecterMap } from './connectionManagerMap'
import { ec2LogsScheme } from '../../shared/constants'
import { Ec2LogDocumentProvider } from './ec2LogDocumentProvider'

const connectionManagers = new Ec2ConnecterMap()

export async function activate(ctx: ExtContext): Promise<void> {
ctx.extensionContext.subscriptions.push(
vscode.workspace.registerTextDocumentContentProvider(ec2LogsScheme, new Ec2LogDocumentProvider())
Expand All @@ -30,7 +32,7 @@ export async function activate(ctx: ExtContext): Promise<void> {
Commands.register('aws.ec2.openTerminal', async (node?: Ec2InstanceNode) => {
await telemetry.ec2_connectToInstance.run(async (span) => {
span.record({ ec2ConnectionType: 'ssm' })
await openTerminal(node)
await openTerminal(connectionManagers, node)
})
}),

Expand All @@ -42,30 +44,30 @@ export async function activate(ctx: ExtContext): Promise<void> {
}),

Commands.register('aws.ec2.openRemoteConnection', async (node?: Ec2Node) => {
await openRemoteConnection(node)
await openRemoteConnection(connectionManagers, node)
}),

Commands.register('aws.ec2.startInstance', async (node?: Ec2Node) => {
await telemetry.ec2_changeState.run(async (span) => {
span.record({ ec2InstanceState: 'start' })
await startInstance(node)
refreshExplorer(node)
await tryRefreshNode(node)
})
}),

Commands.register('aws.ec2.stopInstance', async (node?: Ec2Node) => {
await telemetry.ec2_changeState.run(async (span) => {
span.record({ ec2InstanceState: 'stop' })
await stopInstance(node)
refreshExplorer(node)
await tryRefreshNode(node)
})
}),

Commands.register('aws.ec2.rebootInstance', async (node?: Ec2Node) => {
await telemetry.ec2_changeState.run(async (span) => {
span.record({ ec2InstanceState: 'reboot' })
await rebootInstance(node)
refreshExplorer(node)
await tryRefreshNode(node)
})
}),

Expand All @@ -76,3 +78,7 @@ export async function activate(ctx: ExtContext): Promise<void> {
})
)
}

export async function deactivate(): Promise<void> {
connectionManagers.forEach(async (manager) => await manager.dispose())
}
23 changes: 6 additions & 17 deletions packages/core/src/awsService/ec2/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,25 @@
*/
import { Ec2InstanceNode } from './explorer/ec2InstanceNode'
import { Ec2Node } from './explorer/ec2ParentNode'
import { Ec2ConnectionManager } from './model'
import { Ec2Prompter, instanceFilter, Ec2Selection } from './prompter'
import { SafeEc2Instance, Ec2Client } from '../../shared/clients/ec2Client'
import { copyToClipboard } from '../../shared/utilities/messages'
import { getLogger } from '../../shared/logger'
import { ec2LogSchema } from './ec2LogDocumentProvider'
import { getAwsConsoleUrl } from '../../shared/awsConsole'
import { showRegionPrompter } from '../../auth/utils'
import { openUrl } from '../../shared/utilities/vsCodeUtils'
import { showFile } from '../../shared/utilities/textDocumentUtilities'
import { Ec2ConnecterMap } from './connectionManagerMap'
import { Ec2Prompter, Ec2Selection, instanceFilter } from './prompter'

export function refreshExplorer(node?: Ec2Node) {
if (node) {
const n = node instanceof Ec2InstanceNode ? node.parent : node
n.refreshNode().catch((e) => {
getLogger().error('refreshNode failed: %s', (e as Error).message)
})
}
}

export async function openTerminal(node?: Ec2Node) {
export async function openTerminal(connectionManagers: Ec2ConnecterMap, node?: Ec2Node) {
const selection = await getSelection(node)

const connectionManager = new Ec2ConnectionManager(selection.region)
const connectionManager = connectionManagers.getOrInit(selection.region)
await connectionManager.attemptToOpenEc2Terminal(selection)
}

export async function openRemoteConnection(node?: Ec2Node) {
export async function openRemoteConnection(connectionManagers: Ec2ConnecterMap, node?: Ec2Node) {
const selection = await getSelection(node)
const connectionManager = new Ec2ConnectionManager(selection.region)
const connectionManager = connectionManagers.getOrInit(selection.region)
await connectionManager.tryOpenRemoteConnection(selection)
}

Expand Down
26 changes: 26 additions & 0 deletions packages/core/src/awsService/ec2/connectionManagerMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import { getLogger } from '../../shared'
import { Ec2Connecter } from './model'

export class Ec2ConnecterMap extends Map<string, Ec2Connecter> {
private static warnSize: number = 25

public getOrInit(regionCode: string) {
return this.has(regionCode) ? this.get(regionCode)! : this.initiateManager(regionCode)
}

private initiateManager(regionCode: string): Ec2Connecter {
if (this.size >= Ec2ConnecterMap.warnSize) {
getLogger().warn(
`Connection manager exceeded threshold of ${Ec2ConnecterMap.warnSize} with ${this.size} active connections`
)
}
const newConnectionManager = new Ec2Connecter(regionCode)
this.set(regionCode, newConnectionManager)
return newConnectionManager
}
}
14 changes: 13 additions & 1 deletion packages/core/src/awsService/ec2/explorer/ec2InstanceNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import { SafeEc2Instance } from '../../../shared/clients/ec2Client'
import globals from '../../../shared/extensionGlobals'
import { getIconCode } from '../utils'
import { Ec2Selection } from '../prompter'
import { Ec2ParentNode } from './ec2ParentNode'
import { Ec2Node, Ec2ParentNode } from './ec2ParentNode'
import { EC2 } from 'aws-sdk'
import { getLogger } from '../../../shared'

export const Ec2InstanceRunningContext = 'awsEc2RunningNode'
export const Ec2InstanceStoppedContext = 'awsEc2StoppedNode'
Expand Down Expand Up @@ -101,3 +102,14 @@ export class Ec2InstanceNode extends AWSTreeNodeBase implements AWSResourceNode
await vscode.commands.executeCommand('aws.refreshAwsExplorerNode', this)
}
}

export async function tryRefreshNode(node?: Ec2Node) {
if (node) {
const n = node instanceof Ec2InstanceNode ? node.parent : node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be generalized. I think possibly was, on the https://github.com/aws/aws-toolkit-vscode-staging/tree/feature/lambda-get-started branch.

No action needed here, for now.

try {
await n.refreshNode()
} catch (e) {
getLogger().error('refreshNode failed: %s', (e as Error).message)
}
}
}
47 changes: 27 additions & 20 deletions packages/core/src/awsService/ec2/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import * as vscode from 'vscode'
import * as path from 'path'
import { Session } from 'aws-sdk/clients/ssm'
import { IAM, SSM } from 'aws-sdk'
import { EC2, IAM, SSM } from 'aws-sdk'
import { Ec2Selection } from './prompter'
import { getOrInstallCli } from '../../shared/utilities/cliUtils'
import { isCloud9 } from '../../shared/extensionUtilities'
Expand All @@ -26,21 +26,25 @@ import { createBoundProcess } from '../../codecatalyst/model'
import { getLogger } from '../../shared/logger/logger'
import { CancellationError, Timeout } from '../../shared/utilities/timeoutUtils'
import { showMessageWithCancel } from '../../shared/utilities/messages'
import { SshConfig, sshLogFileLocation } from '../../shared/sshConfig'
import { SshConfig } from '../../shared/sshConfig'
import { SshKeyPair } from './sshKeyPair'
import globals from '../../shared/extensionGlobals'
import { Ec2SessionTracker } from './remoteSessionManager'
import { getEc2SsmEnv } from './utils'

export type Ec2ConnectErrorCode = 'EC2SSMStatus' | 'EC2SSMPermission' | 'EC2SSMConnect' | 'EC2SSMAgentStatus'

interface Ec2RemoteEnv extends VscodeRemoteConnection {
export interface Ec2RemoteEnv extends VscodeRemoteConnection {
selection: Ec2Selection
keyPair: SshKeyPair
ssmSession: SSM.StartSessionResponse
}

export class Ec2ConnectionManager {
export class Ec2Connecter implements vscode.Disposable {
protected ssmClient: SsmClient
protected ec2Client: Ec2Client
protected iamClient: DefaultIamClient
protected sessionManager: Ec2SessionTracker

private policyDocumentationUri = vscode.Uri.parse(
'https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-getting-started-instance-profile.html'
Expand All @@ -54,6 +58,7 @@ export class Ec2ConnectionManager {
this.ssmClient = this.createSsmSdkClient()
this.ec2Client = this.createEc2SdkClient()
this.iamClient = this.createIamSdkClient()
this.sessionManager = new Ec2SessionTracker(regionCode, this.ssmClient)
}

protected createSsmSdkClient(): SsmClient {
Expand All @@ -68,6 +73,18 @@ export class Ec2ConnectionManager {
return new DefaultIamClient(this.regionCode)
}

public async addActiveSession(sessionId: SSM.SessionId, instanceId: EC2.InstanceId): Promise<void> {
await this.sessionManager.addSession(instanceId, sessionId)
}

public async dispose(): Promise<void> {
await this.sessionManager.dispose()
}

public isConnectedTo(instanceId: string): boolean {
return this.sessionManager.isConnectedTo(instanceId)
}

public async getAttachedIamRole(instanceId: string): Promise<IAM.Role | undefined> {
const IamInstanceProfile = await this.ec2Client.getAttachedIamInstanceProfile(instanceId)
if (IamInstanceProfile && IamInstanceProfile.Arn) {
Expand Down Expand Up @@ -185,6 +202,7 @@ export class Ec2ConnectionManager {
this.throwGeneralConnectionError(selection, err as Error)
}
}

public async prepareEc2RemoteEnvWithProgress(selection: Ec2Selection, remoteUser: string): Promise<Ec2RemoteEnv> {
const timeout = new Timeout(60000)
await showMessageWithCancel('AWS: Opening remote connection...', timeout)
Expand All @@ -206,8 +224,10 @@ export class Ec2ConnectionManager {

throw err
}
const session = await this.ssmClient.startSession(selection.instanceId, 'AWS-StartSSHSession')
const vars = getEc2SsmEnv(selection, ssm, session)
const ssmSession = await this.ssmClient.startSession(selection.instanceId, 'AWS-StartSSHSession')
await this.addActiveSession(selection.instanceId, ssmSession.SessionId!)

const vars = getEc2SsmEnv(selection, ssm, ssmSession)
const envProvider = async () => {
return { [sshAgentSocketVariable]: await startSshAgent(), ...vars }
}
Expand All @@ -225,6 +245,7 @@ export class Ec2ConnectionManager {
SessionProcess,
selection,
keyPair,
ssmSession,
}
}

Expand Down Expand Up @@ -270,17 +291,3 @@ export class Ec2ConnectionManager {
throw new ToolkitError(`Unrecognized OS name ${osName} on instance ${instanceId}`, { code: 'UnknownEc2OS' })
}
}

function getEc2SsmEnv(selection: Ec2Selection, ssmPath: string, session: SSM.StartSessionResponse): NodeJS.ProcessEnv {
return Object.assign(
{
AWS_REGION: selection.region,
AWS_SSM_CLI: ssmPath,
LOG_FILE_LOCATION: sshLogFileLocation('ec2', selection.instanceId),
STREAM_URL: session.StreamUrl,
SESSION_ID: session.SessionId,
TOKEN: session.TokenValue,
},
process.env
)
}
8 changes: 8 additions & 0 deletions packages/core/src/awsService/ec2/prompter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { isValidResponse } from '../../shared/wizards/wizard'
import { CancellationError } from '../../shared/utilities/timeoutUtils'
import { AsyncCollection } from '../../shared/utilities/asyncCollection'
import { getIconCode } from './utils'
import { Ec2Node } from './explorer/ec2ParentNode'
import { Ec2InstanceNode } from './explorer/ec2InstanceNode'

export type instanceFilter = (instance: SafeEc2Instance) => boolean
export interface Ec2Selection {
Expand Down Expand Up @@ -72,3 +74,9 @@ export class Ec2Prompter {
)
}
}

export async function getSelection(node?: Ec2Node, filter?: instanceFilter): Promise<Ec2Selection> {
const prompter = new Ec2Prompter(filter)
const selection = node && node instanceof Ec2InstanceNode ? node.toSelection() : await prompter.promptUser()
return selection
}
40 changes: 40 additions & 0 deletions packages/core/src/awsService/ec2/remoteSessionManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import { EC2, SSM } from 'aws-sdk'
import { SsmClient } from '../../shared/clients/ssmClient'
import { Disposable } from 'vscode'

export class Ec2SessionTracker extends Map<EC2.InstanceId, SSM.SessionId> implements Disposable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we'll generalize this later, e.g. for ECS sessions and possibly others in the future.

public constructor(
readonly regionCode: string,
protected ssmClient: SsmClient
) {
super()
}

public async addSession(instanceId: EC2.InstanceId, sessionId: SSM.SessionId): Promise<void> {
if (this.isConnectedTo(instanceId)) {
const existingSessionId = this.get(instanceId)!
await this.ssmClient.terminateSessionFromId(existingSessionId)
this.set(instanceId, sessionId)
} else {
this.set(instanceId, sessionId)
}
}

private async disconnectEnv(instanceId: EC2.InstanceId): Promise<void> {
await this.ssmClient.terminateSessionFromId(this.get(instanceId)!)
this.delete(instanceId)
}

public async dispose(): Promise<void> {
this.forEach(async (_sessionId, instanceId) => await this.disconnectEnv(instanceId))
}

public isConnectedTo(instanceId: EC2.InstanceId): boolean {
return this.has(instanceId)
}
}
26 changes: 26 additions & 0 deletions packages/core/src/awsService/ec2/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { SSM } from 'aws-sdk'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the "v2" sdk. may want to double-check if we already have the v3 SDK for ssm-related stuff (just by searching the codebase). that will avoid needing to migrate this later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, @aws-sdk/client-ssm is not a dependency yet which I think is what we want based on (https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-ssm/Interface/StartSessionResponse/)

import { SafeEc2Instance } from '../../shared/clients/ec2Client'
import { copyToClipboard } from '../../shared/utilities/messages'
import { Ec2Selection } from './prompter'
import { sshLogFileLocation } from '../../shared/sshConfig'

export function getIconCode(instance: SafeEc2Instance) {
if (instance.LastSeenStatus === 'running') {
Expand All @@ -16,3 +20,25 @@ export function getIconCode(instance: SafeEc2Instance) {

return 'loading~spin'
}

export async function copyInstanceId(instanceId: string): Promise<void> {
await copyToClipboard(instanceId, 'Id')
}

export function getEc2SsmEnv(
selection: Ec2Selection,
ssmPath: string,
session: SSM.StartSessionResponse
): NodeJS.ProcessEnv {
return Object.assign(
{
AWS_REGION: selection.region,
AWS_SSM_CLI: ssmPath,
LOG_FILE_LOCATION: sshLogFileLocation('ec2', selection.instanceId),
STREAM_URL: session.StreamUrl,
SESSION_ID: session.SessionId,
TOKEN: session.TokenValue,
},
process.env
)
}
Loading
Loading