diff --git a/packages/core/package.nls.json b/packages/core/package.nls.json index 2f92a23b5ac..f1a83c0c3e4 100644 --- a/packages/core/package.nls.json +++ b/packages/core/package.nls.json @@ -20,7 +20,7 @@ "AWS.configuration.description.suppressPrompts": "Prompts which ask for confirmation. Checking an item suppresses the prompt.", "AWS.configuration.enableCodeLenses": "Enable SAM hints in source code and template.yaml files", "AWS.configuration.description.resources.enabledResources": "AWS resources to display in the 'Resources' portion of the explorer.", - "AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `samSyncCode` - Adds an additional code-only option when synchronizing SAM applications. Code-only synchronizations are faster but can cause drift in the CloudFormation stack. Does nothing when using the legacy SAM deploy feature.\n * `iamPolicyChecks` - Enables IAM Policy Checks feature, allowing users to validate IAM policies against IAM policy grammar, AWS best practices, and specified security standards.", + "AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `ec2RemoteConnect` - Allows interfacing with EC2 instances with options to start, stop, and establish remote connections. Remote connections are done over SSM and can be through a terminal or a remote VSCode window.", "AWS.stepFunctions.asl.format.enable.desc": "Enables the default formatter used with Amazon States Language files", "AWS.stepFunctions.asl.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).", "AWS.configuration.description.awssam.debug.api": "API Gateway configuration", diff --git a/packages/core/src/awsexplorer/regionNode.ts b/packages/core/src/awsexplorer/regionNode.ts index 98fb14c369c..5e6e0b06d52 100644 --- a/packages/core/src/awsexplorer/regionNode.ts +++ b/packages/core/src/awsexplorer/regionNode.ts @@ -29,9 +29,9 @@ import { DefaultSchemaClient } from '../shared/clients/schemaClient' import { getEcsRootNode } from '../awsService/ecs/model' import { compareTreeItems, TreeShim } from '../shared/treeview/utils' import { Ec2ParentNode } from '../awsService/ec2/explorer/ec2ParentNode' -import { DevSettings } from '../shared/settings' import { Ec2Client } from '../shared/clients/ec2Client' import { isCloud9 } from '../shared/extensionUtilities' +import { Experiments } from '../shared/settings' interface ServiceNode { allRegions?: boolean @@ -65,7 +65,7 @@ const serviceCandidates: ServiceNode[] = [ }, { serviceId: 'ec2', - when: () => DevSettings.instance.isDevMode(), + when: () => Experiments.instance.isExperimentEnabled('ec2RemoteConnect'), createFn: (regionCode: string, partitionId: string) => new Ec2ParentNode(regionCode, partitionId, new Ec2Client(regionCode)), }, diff --git a/packages/core/src/shared/settings-toolkit.gen.ts b/packages/core/src/shared/settings-toolkit.gen.ts index ea291352701..66b7ac75ee9 100644 --- a/packages/core/src/shared/settings-toolkit.gen.ts +++ b/packages/core/src/shared/settings-toolkit.gen.ts @@ -41,7 +41,8 @@ export const toolkitSettings = { "ssoCacheError": {} }, "aws.experiments": { - "jsonResourceModification": {} + "jsonResourceModification": {}, + "ec2RemoteConnect": {} }, "aws.resources.enabledResources": {}, "aws.lambda.recentlyUploaded": {}, diff --git a/packages/core/src/shared/settings.ts b/packages/core/src/shared/settings.ts index 190ed442017..a34ba2f8d2d 100644 --- a/packages/core/src/shared/settings.ts +++ b/packages/core/src/shared/settings.ts @@ -726,12 +726,12 @@ export class Experiments extends Settings.define( 'aws.experiments', toRecord(keys(experiments), () => Boolean) ) { - public async isExperimentEnabled(name: ExperimentName): Promise { + public isExperimentEnabled(name: ExperimentName): boolean { try { return this._getOrThrow(name, false) } catch (error) { this._log(`experiment check for ${name} failed: %s`, error) - await this.reset() + this.reset().catch((e) => getLogger().error(`failed to reset experiment settings: %O`, e)) return false } diff --git a/packages/core/src/test/shared/settings.test.ts b/packages/core/src/test/shared/settings.test.ts index 95e30eecfd6..08a31ff42f2 100644 --- a/packages/core/src/test/shared/settings.test.ts +++ b/packages/core/src/test/shared/settings.test.ts @@ -521,17 +521,17 @@ describe('Experiments', function () { // The `Experiments` class is basically an immutable form of `PromptSettings` it('returns false when the setting is missing', async function () { - assert.strictEqual(await sut.isExperimentEnabled('jsonResourceModification'), false) + assert.strictEqual(sut.isExperimentEnabled('jsonResourceModification'), false) }) it('returns false for invalid types', async function () { await sut.update('jsonResourceModification', 'definitely a boolean' as unknown as boolean) - assert.strictEqual(await sut.isExperimentEnabled('jsonResourceModification'), false) + assert.strictEqual(sut.isExperimentEnabled('jsonResourceModification'), false) }) it('returns true when the flag is set', async function () { await sut.update('jsonResourceModification', true) - assert.strictEqual(await sut.isExperimentEnabled('jsonResourceModification'), true) + assert.strictEqual(sut.isExperimentEnabled('jsonResourceModification'), true) }) it('fires events from nested settings', async function () { diff --git a/packages/toolkit/.changes/next-release/Feature-6cca02fc-98d3-4fe0-b2d7-dac2ef86cee6.json b/packages/toolkit/.changes/next-release/Feature-6cca02fc-98d3-4fe0-b2d7-dac2ef86cee6.json new file mode 100644 index 00000000000..f8af3be5854 --- /dev/null +++ b/packages/toolkit/.changes/next-release/Feature-6cca02fc-98d3-4fe0-b2d7-dac2ef86cee6.json @@ -0,0 +1,4 @@ +{ + "type": "Feature", + "description": "Enable the EC2 experiment (setting id: `aws.experiments`) in VSCode settings to try the new EC2 features of AWS Toolkit! Remote Connect and Open Terminal to EC2 instances, list EC2 instances and view their status in AWS Explorer. " +} diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 311f3d02d36..2949bc31e82 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -240,12 +240,17 @@ "type": "object", "markdownDescription": "%AWS.configuration.description.experiments%", "default": { - "jsonResourceModification": false + "jsonResourceModification": false, + "ec2RemoteConnect": false }, "properties": { "jsonResourceModification": { "type": "boolean", "default": false + }, + "ec2RemoteConnect": { + "type": "boolean", + "default": false } }, "additionalProperties": false @@ -1203,27 +1208,27 @@ }, { "command": "aws.ec2.openRemoteConnection", - "when": "aws.isDevMode" + "when": "config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.openTerminal", - "when": "aws.isDevMode" + "when": "config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.linkToLaunch", - "when": "aws.isDevMode" + "when": "config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.startInstance", - "when": "aws.isDevMode" + "when": "config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.stopInstance", - "when": "aws.isDevMode" + "when": "config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.rebootInstance", - "when": "aws.isDevMode" + "when": "config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.dev.openMenu", @@ -1448,62 +1453,67 @@ { "command": "aws.ec2.openTerminal", "group": "0@1", - "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/" + "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/ && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.openTerminal", "group": "inline@1", - "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/" + "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/ && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.linkToLaunch", "group": "0@1", - "when": "viewItem =~ /^(awsEc2ParentNode)$/" + "when": "viewItem =~ /^(awsEc2ParentNode)$/ && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.linkToLaunch", "group": "inline@1", - "when": "viewItem =~ /^(awsEc2ParentNode)$/" + "when": "viewItem =~ /^(awsEc2ParentNode)$/ && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.openRemoteConnection", "group": "0@1", - "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/" + "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/ && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.openRemoteConnection", "group": "inline@1", - "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/" + "when": "viewItem =~ /^(awsEc2(Parent|Running)Node)$/ && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.startInstance", "group": "0@1", - "when": "viewItem == awsEc2StoppedNode" + "when": "viewItem == awsEc2StoppedNode && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.startInstance", "group": "inline@1", - "when": "viewItem == awsEc2StoppedNode" + "when": "viewItem == awsEc2StoppedNode && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.stopInstance", "group": "0@1", - "when": "viewItem == awsEc2RunningNode" + "when": "viewItem == awsEc2RunningNode && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.stopInstance", "group": "inline@1", - "when": "viewItem == awsEc2RunningNode" + "when": "viewItem == awsEc2RunningNode && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.rebootInstance", "group": "0@1", - "when": "viewItem == awsEc2RunningNode" + "when": "viewItem == awsEc2RunningNode && config.aws.experiments.ec2RemoteConnect" }, { "command": "aws.ec2.rebootInstance", "group": "inline@1", - "when": "viewItem == awsEc2RunningNode" + "when": "viewItem == awsEc2RunningNode && config.aws.experiments.ec2RemoteConnect" + }, + { + "command": "aws.ec2.copyInstanceId", + "when": "view == aws.explorer && viewItem =~ /^(awsEc2(Running|Stopped|Pending)Node)$/ && config.aws.experiments.ec2RemoteConnect", + "group": "2@0" }, { "command": "aws.ecr.createRepository", @@ -1605,11 +1615,6 @@ "when": "!config.aws.samcli.legacyDeploy && view == aws.explorer && viewItem =~ /^(awsLambdaNode|awsRegionNode|awsCloudFormationRootNode)$/", "group": "1@2" }, - { - "command": "aws.ec2.copyInstanceId", - "when": "view == aws.explorer && viewItem =~ /^(awsEc2(Running|Stopped|Pending)Node)$/", - "group": "2@0" - }, { "command": "aws.ecr.copyTagUri", "when": "view == aws.explorer && viewItem == awsEcrTagNode",