@mavogel/cdk-vscode-server 0.0.61 → 0.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +117 -178
- package/API.md +96 -199
- package/CLAUDE.md +214 -57
- package/README.md +39 -1
- package/assets/idle-monitor-enabler/idle-monitor-enabler.lambda/index.js +67 -0
- package/assets/installer/installer.lambda/index.js +67 -30
- package/awslint.json +5 -0
- package/examples/git-repo/main.ts +30 -0
- package/integ-tests/integ.al2023.ts.snapshot/IntegSetupVSCodeOnAl2023DefaultTestDeployAssert74D8F645.assets.json +2 -2
- package/integ-tests/integ.al2023.ts.snapshot/IntegSetupVSCodeOnAl2023DefaultTestDeployAssert74D8F645.template.json +1 -1
- package/integ-tests/integ.al2023.ts.snapshot/IntegTestStackAl2023.assets.json +8 -8
- package/integ-tests/integ.al2023.ts.snapshot/IntegTestStackAl2023.template.json +257 -94
- package/integ-tests/{integ.stop-on-idle.ts.snapshot/asset.33da23274e25bd9f43638c5d83dad26e3931cbe78d462ffd9a9f565e948b4f5f.lambda → integ.al2023.ts.snapshot/asset.2f99f38311da357eaaea1284d67c759759324dec4a1cd11621d9c59eea9e81df.lambda}/index.js +67 -30
- package/integ-tests/{integ.ubuntu.ts.snapshot/asset.0ad50fc42afd768c3d0bfdd4701e43284fb077a25f19eea1e8c51a5ca36ebfe4 → integ.al2023.ts.snapshot/asset.efac30c7091c58fed492058fa6403c14f7e58aab8cf4fd595d838b8d5eeec2b9}/index.js +50 -25
- package/integ-tests/integ.al2023.ts.snapshot/integ.json +1 -1
- package/integ-tests/integ.al2023.ts.snapshot/manifest.json +19 -3
- package/integ-tests/integ.al2023.ts.snapshot/tree.json +1 -1
- package/integ-tests/integ.custom-domain.ts.snapshot/IntegSetupVSCodeOnCustomDomainDefaultTestDeployAssert6982D514.assets.json +2 -2
- package/integ-tests/integ.custom-domain.ts.snapshot/IntegSetupVSCodeOnCustomDomainDefaultTestDeployAssert6982D514.template.json +1 -1
- package/integ-tests/integ.custom-domain.ts.snapshot/IntegTestStackCustomDomain.assets.json +8 -8
- package/integ-tests/integ.custom-domain.ts.snapshot/IntegTestStackCustomDomain.template.json +270 -94
- package/integ-tests/{integ.ubuntu.ts.snapshot/asset.33da23274e25bd9f43638c5d83dad26e3931cbe78d462ffd9a9f565e948b4f5f.lambda → integ.custom-domain.ts.snapshot/asset.2f99f38311da357eaaea1284d67c759759324dec4a1cd11621d9c59eea9e81df.lambda}/index.js +67 -30
- package/integ-tests/{integ.al2023.ts.snapshot/asset.0ad50fc42afd768c3d0bfdd4701e43284fb077a25f19eea1e8c51a5ca36ebfe4 → integ.custom-domain.ts.snapshot/asset.efac30c7091c58fed492058fa6403c14f7e58aab8cf4fd595d838b8d5eeec2b9}/index.js +50 -25
- package/integ-tests/integ.custom-domain.ts.snapshot/integ.json +1 -1
- package/integ-tests/integ.custom-domain.ts.snapshot/manifest.json +19 -3
- package/integ-tests/integ.custom-domain.ts.snapshot/tree.json +1 -1
- package/integ-tests/integ.stop-on-idle.ts +1 -4
- package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegStopOnIdleFunctionalityDefaultTestDeployAssertEECF3FC0.assets.json +2 -2
- package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegStopOnIdleFunctionalityDefaultTestDeployAssertEECF3FC0.template.json +4 -4
- package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegTestStackStopOnIdle.assets.json +23 -9
- package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegTestStackStopOnIdle.template.json +755 -194
- package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.22c8a6c357b704e370bef317ae1b52c59f684aa7640422a3d1dfe813d1f77853.lambda/index.js +67 -0
- package/integ-tests/{integ.custom-domain.ts.snapshot/asset.33da23274e25bd9f43638c5d83dad26e3931cbe78d462ffd9a9f565e948b4f5f.lambda → integ.stop-on-idle.ts.snapshot/asset.2f99f38311da357eaaea1284d67c759759324dec4a1cd11621d9c59eea9e81df.lambda}/index.js +67 -30
- package/integ-tests/integ.stop-on-idle.ts.snapshot/manifest.json +353 -72
- package/integ-tests/integ.stop-on-idle.ts.snapshot/tree.json +1 -1
- package/integ-tests/integ.ubuntu.ts.snapshot/IntegSetupVSCodeOnUbuntuDefaultTestDeployAssertFF8DF2C5.assets.json +2 -2
- package/integ-tests/integ.ubuntu.ts.snapshot/IntegSetupVSCodeOnUbuntuDefaultTestDeployAssertFF8DF2C5.template.json +1 -1
- package/integ-tests/integ.ubuntu.ts.snapshot/IntegTestStackUbuntu22.assets.json +8 -8
- package/integ-tests/integ.ubuntu.ts.snapshot/IntegTestStackUbuntu22.template.json +270 -94
- package/integ-tests/{integ.al2023.ts.snapshot/asset.33da23274e25bd9f43638c5d83dad26e3931cbe78d462ffd9a9f565e948b4f5f.lambda → integ.ubuntu.ts.snapshot/asset.2f99f38311da357eaaea1284d67c759759324dec4a1cd11621d9c59eea9e81df.lambda}/index.js +67 -30
- package/integ-tests/{integ.custom-domain.ts.snapshot/asset.0ad50fc42afd768c3d0bfdd4701e43284fb077a25f19eea1e8c51a5ca36ebfe4 → integ.ubuntu.ts.snapshot/asset.efac30c7091c58fed492058fa6403c14f7e58aab8cf4fd595d838b8d5eeec2b9}/index.js +50 -25
- package/integ-tests/integ.ubuntu.ts.snapshot/integ.json +1 -1
- package/integ-tests/integ.ubuntu.ts.snapshot/manifest.json +19 -3
- package/integ-tests/integ.ubuntu.ts.snapshot/tree.json +1 -1
- package/integ-tests/integ.ubuntu24.ts +69 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/IntegSetupVSCodeOnUbuntuDefaultTestDeployAssertFF8DF2C5.assets.json +33 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/IntegSetupVSCodeOnUbuntuDefaultTestDeployAssertFF8DF2C5.template.json +337 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/IntegTestStackUbuntu24.assets.json +118 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/IntegTestStackUbuntu24.template.json +2725 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d/index.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.2f99f38311da357eaaea1284d67c759759324dec4a1cd11621d9c59eea9e81df.lambda/index.js +180 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.530055f7515b3f0a47900f5df37e729ba40ca977b2d07b952bdefa2b8f883f42.bundle/index.js +30676 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.781ab0ab74634cdaf61539ab208ab777829ef07097ac21f95b9e15a3b1eedc1b.lambda/index.js +57 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200/__entrypoint__.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200/index.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.9d043014be736e8162bcc7ec5590cc6d2ff24fd0d9c73a5c5d595151c5fdad00/index.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/cfn-response.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/consts.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/framework.js +3 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/outbound.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/util.js +1 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/asset.efac30c7091c58fed492058fa6403c14f7e58aab8cf4fd595d838b8d5eeec2b9/index.js +6017 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/integ.json +23 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/manifest.json +1473 -0
- package/integ-tests/integ.ubuntu24.ts.snapshot/tree.json +1 -0
- package/lib/idle-monitor/idle-monitor-function.js +2 -2
- package/lib/idle-monitor/idle-monitor.js +5 -2
- package/lib/idle-monitor-enabler/idle-monitor-enabler-function.d.ts +13 -0
- package/lib/idle-monitor-enabler/idle-monitor-enabler-function.js +22 -0
- package/lib/idle-monitor-enabler/idle-monitor-enabler.d.ts +25 -0
- package/lib/idle-monitor-enabler/idle-monitor-enabler.js +76 -0
- package/lib/idle-monitor-enabler/idle-monitor-enabler.lambda.d.ts +9 -0
- package/lib/idle-monitor-enabler/idle-monitor-enabler.lambda.js +48 -0
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -2
- package/lib/installer/installer-function.js +2 -2
- package/lib/installer/installer.d.ts +100 -0
- package/lib/installer/installer.js +658 -301
- package/lib/installer/installer.lambda.js +64 -30
- package/lib/secret-retriever/secret-retriever-function.js +2 -2
- package/lib/vscode-server.d.ts +40 -0
- package/lib/vscode-server.js +27 -4
- package/package.json +12 -12
- package/.claude/hooks/file_checker.sh +0 -178
- package/.qlty/.gitignore +0 -7
- package/.qlty/configs/.yamllint.yaml +0 -21
- package/.qlty/qlty.toml +0 -115
- package/assets/status-check/status-check.lambda/index.js +0 -123
- package/integ-tests/integ.al2023.ts.snapshot/cdk.out +0 -1
- package/integ-tests/integ.al2023.ts.snapshot/read.13497.1.lock +0 -1
- package/integ-tests/integ.custom-domain.ts.snapshot/read.13497.1.lock +0 -1
- package/integ-tests/integ.ubuntu.ts.snapshot/cdk.out +0 -1
- package/integ-tests/integ.ubuntu.ts.snapshot/read.13497.1.lock +0 -1
- package/lib/status-check/status-check-function.d.ts +0 -13
- package/lib/status-check/status-check-function.js +0 -22
- package/lib/status-check/status-check.d.ts +0 -36
- package/lib/status-check/status-check.js +0 -109
- package/lib/status-check/status-check.lambda.d.ts +0 -2
- package/lib/status-check/status-check.lambda.js +0 -104
package/CLAUDE.md
CHANGED
|
@@ -4,18 +4,25 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Repository Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
A JSII-enabled CDK construct library that deploys VS Code Server on AWS. Published to npm and PyPI. Designed for workshop/development environments with intentionally permissive security for ease of use.
|
|
8
8
|
|
|
9
|
-
**Key
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
**Key Characteristic**: This is **NOT production-ready** by design - it's optimized for quick workshop setup and learning environments.
|
|
10
|
+
|
|
11
|
+
## Projen-Managed Project
|
|
12
|
+
|
|
13
|
+
**Critical**: ALL project configuration is in `.projenrc.ts`. After modifying it, run `npx projen` to regenerate managed files.
|
|
14
|
+
|
|
15
|
+
**Never manually edit**:
|
|
16
|
+
- `package.json`
|
|
17
|
+
- Task definitions
|
|
18
|
+
- GitHub workflows
|
|
19
|
+
- Any file with "~~ Generated by projen" header
|
|
13
20
|
|
|
14
21
|
## Development Commands
|
|
15
22
|
|
|
16
23
|
### Build and Test
|
|
17
24
|
```bash
|
|
18
|
-
#
|
|
25
|
+
# Full build (compiles TS, bundles Lambdas, generates API docs)
|
|
19
26
|
npx projen build
|
|
20
27
|
|
|
21
28
|
# Run unit tests
|
|
@@ -24,10 +31,10 @@ npx projen test
|
|
|
24
31
|
# Run single test file
|
|
25
32
|
npx jest test/vscode-server.test.ts
|
|
26
33
|
|
|
27
|
-
#
|
|
34
|
+
# Watch mode for tests
|
|
28
35
|
npx projen test:watch
|
|
29
36
|
|
|
30
|
-
# Integration tests (deploys to eu-west-1, eu-west-2, eu-north-1)
|
|
37
|
+
# Integration tests (deploys to eu-west-1, eu-west-2, eu-north-1, eu-west-3)
|
|
31
38
|
npm run integ-test
|
|
32
39
|
```
|
|
33
40
|
|
|
@@ -44,82 +51,232 @@ npm run awslint
|
|
|
44
51
|
```bash
|
|
45
52
|
# Bundle specific Lambda
|
|
46
53
|
npx projen bundle:installer/installer.lambda
|
|
54
|
+
npx projen bundle:idle-monitor/idle-monitor.lambda
|
|
55
|
+
npx projen bundle:idle-monitor-enabler/idle-monitor-enabler.lambda
|
|
47
56
|
npx projen bundle:secret-retriever/secret-retriever.lambda
|
|
48
57
|
|
|
49
|
-
# Watch mode for development
|
|
58
|
+
# Watch mode for Lambda development
|
|
50
59
|
npx projen bundle:installer/installer.lambda:watch
|
|
51
60
|
```
|
|
52
61
|
|
|
53
62
|
### Publishing
|
|
54
63
|
```bash
|
|
55
|
-
# Package for all targets (
|
|
64
|
+
# Package for all targets (npm, Python)
|
|
56
65
|
npx projen package-all
|
|
57
66
|
|
|
58
67
|
# Package specific target
|
|
59
68
|
npx projen package:js
|
|
60
69
|
npx projen package:python
|
|
61
|
-
npx projen package:go
|
|
62
70
|
```
|
|
63
71
|
|
|
64
|
-
## Architecture
|
|
72
|
+
## Architecture Overview
|
|
73
|
+
|
|
74
|
+
### Main Construct: `VSCodeServer` (src/vscode-server.ts)
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
Located in `src/vscode-server.ts`, orchestrates:
|
|
76
|
+
Orchestrates the entire infrastructure:
|
|
68
77
|
- VPC with single public subnet
|
|
69
78
|
- EC2 instance (default: m7g.xlarge Graviton3 ARM)
|
|
70
|
-
- CloudFront distribution with custom cache policies
|
|
79
|
+
- CloudFront distribution with custom cache policies
|
|
71
80
|
- Security groups (CloudFront prefix list restriction only)
|
|
72
|
-
- IAM role with CDK permissions
|
|
73
|
-
- Optional Route53 + ACM certificate integration
|
|
81
|
+
- IAM role with broad CDK permissions (workshop-friendly)
|
|
82
|
+
- Optional: Route53 + ACM certificate integration
|
|
83
|
+
- Optional: Auto-stop feature with idle monitoring
|
|
84
|
+
|
|
85
|
+
### Custom Resource Pattern
|
|
74
86
|
|
|
75
|
-
### Custom Resources Pattern
|
|
76
87
|
Uses Lambda-backed custom resources via CDK Provider construct:
|
|
77
|
-
- **Installer** (`src/installer/`): OS-specific VS Code Server installation via SSM documents
|
|
78
|
-
- **SecretRetriever** (`src/secret-retriever/`): Extracts generated password from Secrets Manager
|
|
79
|
-
- **PrefixListRetriever** (`src/prefixlist-retriever/`): Fetches AWS-managed CloudFront prefix lists
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
1. **Installer** (`src/installer/`)
|
|
90
|
+
- Runs SSM documents to install VS Code Server
|
|
91
|
+
- OS-specific installation for Ubuntu 22/24 and Amazon Linux 2023
|
|
92
|
+
- Returns SUCCESS when installation completes
|
|
93
|
+
- Custom resource name: `SSMInstallerCustomResource`
|
|
94
|
+
|
|
95
|
+
2. **SecretRetriever** (`src/secret-retriever/`)
|
|
96
|
+
- Extracts generated password from Secrets Manager
|
|
97
|
+
- Returns password as CloudFormation output
|
|
98
|
+
|
|
99
|
+
3. **PrefixListRetriever** (`src/prefixlist-retriever/`)
|
|
100
|
+
- Fetches AWS-managed CloudFront prefix lists
|
|
101
|
+
- Used to restrict security group ingress
|
|
102
|
+
|
|
103
|
+
4. **IdleMonitorEnabler** (`src/idle-monitor-enabler/`)
|
|
104
|
+
- Enables EventBridge rule ONLY after installation completes
|
|
105
|
+
- Prevents race condition where IdleMonitor stops instance mid-installation
|
|
106
|
+
- Critical dependency chain: `Installer → IdleMonitorEnabler → IdleMonitor active`
|
|
107
|
+
|
|
108
|
+
### Auto-Stop Feature Architecture
|
|
109
|
+
|
|
110
|
+
**Problem Solved**: Race condition where IdleMonitor could stop instance during installation.
|
|
111
|
+
|
|
112
|
+
**Solution Flow**:
|
|
113
|
+
1. EventBridge rule created in **DISABLED** state (`src/idle-monitor/idle-monitor.ts:118`)
|
|
114
|
+
2. Installer runs and completes VS Code Server setup
|
|
115
|
+
3. IdleMonitorEnabler custom resource **enables** the rule after installation succeeds
|
|
116
|
+
4. IdleMonitor now safely monitors CloudFront metrics for idle detection
|
|
117
|
+
|
|
118
|
+
**Key Files**:
|
|
119
|
+
- `src/idle-monitor/idle-monitor.ts` - EventBridge rule + Lambda for monitoring
|
|
120
|
+
- `src/idle-monitor/idle-monitor.lambda.ts` - Checks CloudWatch metrics, stops instance if idle
|
|
121
|
+
- `src/idle-monitor-enabler/idle-monitor-enabler.ts` - Custom resource construct
|
|
122
|
+
- `src/idle-monitor-enabler/idle-monitor-enabler.lambda.ts` - Enables EventBridge rule via AWS SDK
|
|
123
|
+
|
|
124
|
+
**Dependency Wiring** (`src/vscode-server.ts:984`):
|
|
125
|
+
```typescript
|
|
126
|
+
const installerCustomResource = this.node.findChild('SSMInstallerCustomResource');
|
|
127
|
+
enabler.node.addDependency(installerCustomResource);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### AMI Selection (`src/mappings.ts`)
|
|
131
|
+
|
|
132
|
+
Contains SSM parameter paths for:
|
|
83
133
|
- Ubuntu 22/24 (ARM + x86_64)
|
|
84
134
|
- Amazon Linux 2023 (ARM + x86_64)
|
|
85
135
|
|
|
86
136
|
Function `getAmiSSMParameterForLinuxArchitectureAndFlavor()` returns region-specific SSM parameter for latest AMI.
|
|
87
137
|
|
|
88
|
-
### Key Props
|
|
89
|
-
`VSCodeServerProps` in `src/vscode-server.ts:27-155`:
|
|
90
|
-
- **Instance**: `instanceClass`, `instanceSize`, `instanceVolumeSize`
|
|
91
|
-
- **OS**: `instanceOperatingSystem` (LinuxFlavorType enum), `instanceCpuArchitecture` (LinuxArchitectureType enum)
|
|
92
|
-
- **VS Code**: `vscodeUser`, `vscodePassword`, `homeFolder`, `devServerPort`, `devServerBasePath`
|
|
93
|
-
- **Domain**: `domainName`, `hostedZoneId`, `certificateArn`, `autoCreateCertificate`
|
|
94
|
-
- **Extensions**: `additionalInstanceRolePolicies`, `additionalTags`
|
|
138
|
+
### Key Props (`src/vscode-server.ts:27-200`)
|
|
95
139
|
|
|
96
|
-
|
|
140
|
+
**Instance Configuration**:
|
|
141
|
+
- `instanceClass`, `instanceSize`, `instanceVolumeSize`
|
|
142
|
+
- `instanceOperatingSystem` (LinuxFlavorType enum)
|
|
143
|
+
- `instanceCpuArchitecture` (LinuxArchitectureType enum)
|
|
97
144
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
3. Never manually edit `package.json`, task definitions, or GitHub workflows
|
|
145
|
+
**VS Code Configuration**:
|
|
146
|
+
- `vscodeUser`, `vscodePassword`, `homeFolder`
|
|
147
|
+
- `devServerPort`, `devServerBasePath`
|
|
102
148
|
|
|
103
|
-
|
|
149
|
+
**Domain/Certificate**:
|
|
150
|
+
- `domainName`, `hostedZoneId`, `certificateArn`, `autoCreateCertificate`
|
|
151
|
+
|
|
152
|
+
**Auto-Stop**:
|
|
153
|
+
- `enableAutoStop` - Enable automatic instance stop when idle
|
|
154
|
+
- `idleTimeoutMinutes` - Minutes of inactivity before stopping (default: 30)
|
|
155
|
+
- `idleCheckIntervalMinutes` - How often to check (default: 5)
|
|
156
|
+
- `skipStatusChecks` - Skip EC2 status checks before stopping (for testing only)
|
|
157
|
+
|
|
158
|
+
**Extensions**:
|
|
159
|
+
- `additionalInstanceRolePolicies`, `additionalTags`
|
|
160
|
+
|
|
161
|
+
## JSII Constraints
|
|
162
|
+
|
|
163
|
+
**Critical for JSII compatibility**:
|
|
104
164
|
- All public APIs must be JSII-compatible (no TS-specific types)
|
|
105
|
-
- Bundled dependencies (like `node-html-parser`)
|
|
106
|
-
- Lambda functions use esbuild bundling configured via Projen
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
##
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
-
|
|
165
|
+
- Bundled dependencies (like `node-html-parser`) must be in `.projenrc.ts` `bundledDeps`
|
|
166
|
+
- Lambda functions use esbuild bundling configured via Projen (auto-discovered in `src/**/*.lambda.ts`)
|
|
167
|
+
|
|
168
|
+
## CDK-nag Integration
|
|
169
|
+
|
|
170
|
+
Suppressions defined in `src/suppress-nags.ts` and applied throughout construct code.
|
|
171
|
+
|
|
172
|
+
**Why suppressions are needed**: Workshop design intentionally violates production best practices:
|
|
173
|
+
- Broad IAM permissions for ease of use
|
|
174
|
+
- Permissive security groups
|
|
175
|
+
- Public subnet deployment
|
|
176
|
+
- No VPC endpoints
|
|
177
|
+
|
|
178
|
+
Apply suppressions via `NagSuppressions.addResourceSuppressions()`.
|
|
179
|
+
|
|
180
|
+
## Integration Tests
|
|
181
|
+
|
|
182
|
+
Located in `integ-tests/`, using `@aws-cdk/integ-tests-alpha` framework.
|
|
183
|
+
|
|
184
|
+
**Test Files**:
|
|
185
|
+
- `integ.ubuntu.ts` - Basic Ubuntu 22 deployment + login test
|
|
186
|
+
- `integ.al2023.ts` - Amazon Linux 2023 deployment
|
|
187
|
+
- `integ.custom-domain.ts` - Custom domain + ACM certificate
|
|
188
|
+
- `integ.stop-on-idle.ts` - **4-phase auto-stop workflow test**
|
|
189
|
+
|
|
190
|
+
**Stop-on-Idle Test Phases** (`integ-tests/integ.stop-on-idle.ts`):
|
|
191
|
+
1. `verify-auto-stop` - Wait for instance to stop after idle timeout
|
|
192
|
+
2. `disable-idle-monitor` - Disable EventBridge rule to prevent re-stopping
|
|
193
|
+
3. `start-instance` - Start instance and wait for running state
|
|
194
|
+
4. `verify-login` - Check VS Code Server accessibility via CloudFront
|
|
195
|
+
|
|
196
|
+
**Run Integration Tests**:
|
|
197
|
+
```bash
|
|
198
|
+
npm run integ-test # Deploys to 4 regions in parallel
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Important**: Integration tests deploy actual stacks and incur AWS costs.
|
|
202
|
+
|
|
203
|
+
## Lambda Bundling
|
|
204
|
+
|
|
205
|
+
Projen automatically discovers Lambda functions matching `src/**/*.lambda.ts` pattern.
|
|
206
|
+
|
|
207
|
+
**Auto-generated tasks** for each Lambda:
|
|
208
|
+
- `bundle:<path>/name.lambda` - Bundle Lambda code
|
|
209
|
+
- `bundle:<path>/name.lambda:watch` - Watch mode for development
|
|
210
|
+
|
|
211
|
+
**Bundled output**: `assets/<path>/name.lambda/index.js`
|
|
212
|
+
|
|
213
|
+
## Common Workflows
|
|
214
|
+
|
|
215
|
+
### Adding a New Lambda Function
|
|
216
|
+
|
|
217
|
+
1. Create `src/my-feature/my-feature.lambda.ts`
|
|
218
|
+
2. Create `src/my-feature/my-feature-function.ts` (CDK construct wrapper)
|
|
219
|
+
3. Run `npx projen` - auto-discovers and creates bundle task
|
|
220
|
+
4. Import in construct: `import { MyFeatureFunction } from './my-feature/my-feature-function'`
|
|
221
|
+
|
|
222
|
+
### Modifying VSCodeServer Props
|
|
223
|
+
|
|
224
|
+
1. Edit `src/vscode-server.ts` - update `VSCodeServerProps` interface
|
|
225
|
+
2. Run `npx projen build` - regenerates JSII artifacts + API docs
|
|
226
|
+
3. Update README.md with usage examples
|
|
227
|
+
|
|
228
|
+
### Testing Changes
|
|
229
|
+
|
|
230
|
+
1. Unit tests: `npx jest test/vscode-server.test.ts`
|
|
231
|
+
2. Build validation: `npx projen build` (includes awslint checks)
|
|
232
|
+
3. Integration test: `npm run integ-test` (full deployment test)
|
|
233
|
+
|
|
234
|
+
## Race Condition Prevention (Auto-Stop)
|
|
235
|
+
|
|
236
|
+
**Issue**: IdleMonitor EventBridge rule triggers immediately on stack creation, potentially stopping instance during installation (observed: instance stopped 72 seconds after installer started).
|
|
237
|
+
|
|
238
|
+
**Fix**: Three-stage dependency chain ensures safe operation:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
EC2 Instance
|
|
242
|
+
↓
|
|
243
|
+
Installer Custom Resource (waits for VS Code Server installation)
|
|
244
|
+
↓
|
|
245
|
+
IdleMonitorEnabler Custom Resource (enables EventBridge rule)
|
|
246
|
+
↓
|
|
247
|
+
IdleMonitor Active (now safe to monitor)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Implementation Details**:
|
|
251
|
+
- EventBridge rule created with `enabled: false` (`src/idle-monitor/idle-monitor.ts:118`)
|
|
252
|
+
- IdleMonitorEnabler depends on `SSMInstallerCustomResource` via `node.addDependency()`
|
|
253
|
+
- CloudFormation enforces ordering automatically
|
|
254
|
+
|
|
255
|
+
This pattern can be applied to any future features requiring post-installation activation.
|
|
256
|
+
|
|
257
|
+
## Multi-Language Publishing
|
|
258
|
+
|
|
259
|
+
Project publishes to:
|
|
260
|
+
- **npm**: `@mavogel/cdk-vscode-server`
|
|
261
|
+
- **PyPI**: `cdk-vscode-server`
|
|
262
|
+
|
|
263
|
+
JSII compiles TypeScript to:
|
|
264
|
+
- JavaScript (npm)
|
|
265
|
+
- Python (PyPI)
|
|
266
|
+
|
|
267
|
+
**Publishing** (requires credentials):
|
|
268
|
+
```bash
|
|
269
|
+
npx projen release
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Workshop-Specific Considerations
|
|
273
|
+
|
|
274
|
+
**Remember**: This construct is intentionally designed for workshops, NOT production:
|
|
275
|
+
|
|
276
|
+
- IAM roles have broad permissions (all CDK operations)
|
|
277
|
+
- Security groups allow CloudFront only (but permissive within that constraint)
|
|
278
|
+
- No private subnets or VPC endpoints (cost optimization for workshops)
|
|
279
|
+
- Single public subnet (simplicity over high availability)
|
|
280
|
+
- Password-based authentication (ease of use over MFA/SSO)
|
|
281
|
+
|
|
282
|
+
When reviewing changes, prioritize **ease of use** and **quick setup** over security hardening.
|
package/README.md
CHANGED
|
@@ -21,7 +21,9 @@ we implement new features. Therefore make sure you use an exact version in your
|
|
|
21
21
|
- [Features](#features)
|
|
22
22
|
- [Usage](#usage)
|
|
23
23
|
- [Standard](#Standard)
|
|
24
|
+
- [Pre-populate with Git Repository](#pre-populate-with-git-repository)
|
|
24
25
|
- [Custom Domain Configuration](#custom-domain-configuration)
|
|
26
|
+
- [Auto-Stop Configuration](#auto-stop-configuration)
|
|
25
27
|
- [Solution Design](#solution-design)
|
|
26
28
|
- [Inspiration](#inspiration)
|
|
27
29
|
|
|
@@ -31,7 +33,7 @@ we implement new features. Therefore make sure you use an exact version in your
|
|
|
31
33
|
- 📏 **Best Practice Setup**: Set up with [projen](https://projen.io/) and a [single configuration file](./.projenrc.ts) to keep your changes centralized.
|
|
32
34
|
- 🤹♂️ **Pre-installed packages**: Besides the [vscode](https://code.visualstudio.com/) server, other tools and software packages such as `git`, `docker`, `awscli` `nodejs` and `python` are pre-installed on the EC2 instance.
|
|
33
35
|
- 🌐 **Custom Domain Support**: Use your own domain name with automatic ACM certificate creation and Route53 DNS configuration, or bring your existing certificate.
|
|
34
|
-
- 💰 **Auto-Stop**: Automatically stop EC2 instances after inactivity with Elastic IP retention - save up to 75% on costs for development environments
|
|
36
|
+
- 💰 **Auto-Stop**: Automatically stop EC2 instances after inactivity with Elastic IP retention - save up to 75% on costs for development environments.
|
|
35
37
|
- 🏗️ **Extensibility**: Pass in properties to the construct, which start with `additional*`. They allow you to extend the configuration to your needs. There are more to come...
|
|
36
38
|
|
|
37
39
|
## Usage
|
|
@@ -115,6 +117,41 @@ dev.vscodepassword64FBCA12 = foobarbaz
|
|
|
115
117
|
|
|
116
118
|
See the [examples](./examples) folder for more inspiration.
|
|
117
119
|
|
|
120
|
+
### Pre-populate with Git Repository
|
|
121
|
+
|
|
122
|
+
Clone a git repository into the VS Code Server's home folder during instance setup - perfect for workshops or development environments with starter code:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
new VSCodeServer(this, 'vscode', {
|
|
126
|
+
// Clone a git repository into the home folder
|
|
127
|
+
repoUrl: 'https://github.com/aws-samples/my-workshop-repo.git',
|
|
128
|
+
|
|
129
|
+
// Optional: customize the home folder path (default: /Workshop)
|
|
130
|
+
homeFolder: '/MyWorkshop',
|
|
131
|
+
|
|
132
|
+
// Optional: specify VS Code user (default: vscode-user)
|
|
133
|
+
vscodeUser: 'workshop-user',
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**What happens:**
|
|
138
|
+
1. During instance setup, the specified git repository is cloned into the user's home folder
|
|
139
|
+
2. VS Code Server opens with the repository already loaded and ready to use
|
|
140
|
+
3. Participants can start coding immediately without manual git clone steps
|
|
141
|
+
|
|
142
|
+
**Use cases:**
|
|
143
|
+
- Workshop environments with pre-configured starter code
|
|
144
|
+
- Development environments with boilerplate projects
|
|
145
|
+
- Training sessions with example applications
|
|
146
|
+
- Code review sessions with pre-loaded repositories
|
|
147
|
+
|
|
148
|
+
**Repository requirements:**
|
|
149
|
+
- Must be publicly accessible (no authentication required)
|
|
150
|
+
- HTTPS URLs only (SSH git URLs are not supported)
|
|
151
|
+
- Repository will be cloned using `git clone` during instance initialization
|
|
152
|
+
|
|
153
|
+
For complete examples, see [examples/](./examples).
|
|
154
|
+
|
|
118
155
|
### Custom Domain Configuration
|
|
119
156
|
|
|
120
157
|
You can configure your VS Code Server with a custom domain name instead of using the default CloudFront domain. The construct supports three different configuration options:
|
|
@@ -200,6 +237,7 @@ new VSCodeServer(this, 'vscode', {
|
|
|
200
237
|
- Elastic IP for consistent public addressing
|
|
201
238
|
- EventBridge rule triggering idle monitoring at configured intervals
|
|
202
239
|
- IdleMonitor Lambda function checking CloudWatch metrics for request activity
|
|
240
|
+
- IdleMonitorEnabler custom resource ensuring monitoring only starts after installation completes
|
|
203
241
|
- CloudWatch metrics from CloudFront distribution
|
|
204
242
|
|
|
205
243
|
**Integration Testing:**
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/idle-monitor-enabler/idle-monitor-enabler.lambda.ts
|
|
21
|
+
var idle_monitor_enabler_lambda_exports = {};
|
|
22
|
+
__export(idle_monitor_enabler_lambda_exports, {
|
|
23
|
+
handler: () => handler
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(idle_monitor_enabler_lambda_exports);
|
|
26
|
+
var import_client_eventbridge = require("@aws-sdk/client-eventbridge");
|
|
27
|
+
var eventBridge = new import_client_eventbridge.EventBridge();
|
|
28
|
+
var handler = async (event) => {
|
|
29
|
+
console.log("Event: %j", { ...event, ResponseURL: "..." });
|
|
30
|
+
const ruleName = event.ResourceProperties.RuleName;
|
|
31
|
+
if (!ruleName) {
|
|
32
|
+
throw new Error("RuleName is required in ResourceProperties");
|
|
33
|
+
}
|
|
34
|
+
switch (event.RequestType) {
|
|
35
|
+
case "Create":
|
|
36
|
+
case "Update":
|
|
37
|
+
console.log(`Enabling EventBridge rule: ${ruleName}`);
|
|
38
|
+
await eventBridge.send(
|
|
39
|
+
new import_client_eventbridge.EnableRuleCommand({
|
|
40
|
+
Name: ruleName
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
console.log(`Successfully enabled rule: ${ruleName}`);
|
|
44
|
+
return {
|
|
45
|
+
PhysicalResourceId: `idle-monitor-enabler-${ruleName}`
|
|
46
|
+
};
|
|
47
|
+
case "Delete":
|
|
48
|
+
console.log(`Disabling EventBridge rule on deletion: ${ruleName}`);
|
|
49
|
+
try {
|
|
50
|
+
await eventBridge.send(
|
|
51
|
+
new import_client_eventbridge.DisableRuleCommand({
|
|
52
|
+
Name: ruleName
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
console.log(`Successfully disabled rule: ${ruleName}`);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.log(`Error disabling rule (ignoring): ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
return {};
|
|
60
|
+
default:
|
|
61
|
+
throw new Error(`Unsupported RequestType: ${event.RequestType}`);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
65
|
+
0 && (module.exports = {
|
|
66
|
+
handler
|
|
67
|
+
});
|
|
@@ -59,47 +59,89 @@ var handler = async (event, context) => {
|
|
|
59
59
|
parameters[key] = [value];
|
|
60
60
|
}
|
|
61
61
|
console.log("mapped parameters: %j", parameters);
|
|
62
|
-
let attemptNo = 0;
|
|
63
|
-
let timeRemaining = context.getRemainingTimeInMillis();
|
|
64
62
|
console.log(
|
|
65
63
|
`Running SSM Document '${documentName}' on EC2 instance '${instanceId}'. Logging to '${cloudWatchLogGroupName}' with parameters: '${JSON.stringify(parameters)}'`
|
|
66
64
|
);
|
|
65
|
+
let commandId;
|
|
66
|
+
let attemptNo = 0;
|
|
67
67
|
while (true) {
|
|
68
68
|
attemptNo += 1;
|
|
69
|
+
const timeRemaining = context.getRemainingTimeInMillis();
|
|
69
70
|
console.log(
|
|
70
|
-
`
|
|
71
|
+
`Send attempt: ${attemptNo}. Time Remaining: ${timeRemaining / 1e3}s`
|
|
71
72
|
);
|
|
72
73
|
try {
|
|
73
|
-
const response = await ssm.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
74
|
+
const response = await ssm.send(
|
|
75
|
+
new import_client_ssm.SendCommandCommand({
|
|
76
|
+
DocumentName: documentName,
|
|
77
|
+
InstanceIds: [instanceId],
|
|
78
|
+
CloudWatchOutputConfig: {
|
|
79
|
+
CloudWatchLogGroupName: cloudWatchLogGroupName,
|
|
80
|
+
CloudWatchOutputEnabled: true
|
|
81
|
+
},
|
|
82
|
+
Parameters: parameters
|
|
83
|
+
})
|
|
84
|
+
);
|
|
85
|
+
console.log(`sendCommand response: ${JSON.stringify(response)}`);
|
|
83
86
|
const command = response.Command;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
commandId = command.CommandId;
|
|
88
|
+
console.log(`Command sent successfully. CommandId: ${commandId}`);
|
|
89
|
+
break;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.log("Error sending command:", error);
|
|
92
|
+
const isUnauthorized = error.name === "UnauthorizedException" || error.name === "AccessDeniedException" || error.message && error.message.includes("not authorized");
|
|
93
|
+
const isThrottled = error.name === "ThrottlingException" || error.name === "TooManyRequestsException";
|
|
94
|
+
const isRetryable = isUnauthorized || isThrottled;
|
|
95
|
+
const remainingTime = context.getRemainingTimeInMillis();
|
|
96
|
+
if (isRetryable && remainingTime > SLEEP_MS) {
|
|
97
|
+
console.log(
|
|
98
|
+
`Retryable error encountered (${error.name}). Attempt ${attemptNo}. Sleeping: ${SLEEP_MS / 1e3}s before retry`
|
|
99
|
+
);
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, SLEEP_MS));
|
|
101
|
+
} else {
|
|
102
|
+
console.log("Non-retryable error or timeout. Failing...");
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
let pollAttemptNo = 0;
|
|
108
|
+
const responseData = { CommandId: commandId };
|
|
109
|
+
while (true) {
|
|
110
|
+
pollAttemptNo += 1;
|
|
111
|
+
const timeRemaining = context.getRemainingTimeInMillis();
|
|
112
|
+
console.log(
|
|
113
|
+
`Poll attempt: ${pollAttemptNo}. Time Remaining: ${timeRemaining / 1e3}s`
|
|
114
|
+
);
|
|
115
|
+
try {
|
|
116
|
+
const invocationResponse = await ssm.send(
|
|
117
|
+
new import_client_ssm.GetCommandInvocationCommand({
|
|
118
|
+
CommandId: commandId,
|
|
119
|
+
InstanceId: instanceId
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
console.log(
|
|
123
|
+
`getCommandInvocation response: ${JSON.stringify(invocationResponse)}`
|
|
124
|
+
);
|
|
125
|
+
const status = invocationResponse.Status;
|
|
126
|
+
switch (status) {
|
|
87
127
|
case "Pending":
|
|
88
128
|
case "InProgress":
|
|
89
|
-
|
|
129
|
+
case "Delayed":
|
|
90
130
|
if (timeRemaining > SLEEP_MS) {
|
|
91
131
|
console.log(
|
|
92
|
-
`
|
|
132
|
+
`Command ${commandId} status: '${status}'. Sleeping: ${SLEEP_MS / 1e3}s`
|
|
93
133
|
);
|
|
94
134
|
await new Promise((resolve) => setTimeout(resolve, SLEEP_MS));
|
|
95
135
|
break;
|
|
96
136
|
} else {
|
|
97
137
|
throw new Error(
|
|
98
|
-
`SSM Document ${documentName} on EC2 instance ${instanceId} timed out while lambda
|
|
138
|
+
`SSM Document ${documentName} on EC2 instance ${instanceId} timed out while lambda waiting (status: ${status})`
|
|
99
139
|
);
|
|
100
140
|
}
|
|
101
141
|
case "Success":
|
|
102
|
-
console.log(
|
|
142
|
+
console.log(
|
|
143
|
+
`Instance ${instanceId} successfully bootstrapped. Command ${commandId} completed.`
|
|
144
|
+
);
|
|
103
145
|
return { Data: responseData };
|
|
104
146
|
case "TimedOut":
|
|
105
147
|
throw new Error(
|
|
@@ -115,23 +157,18 @@ var handler = async (event, context) => {
|
|
|
115
157
|
);
|
|
116
158
|
default:
|
|
117
159
|
throw new Error(
|
|
118
|
-
`SSM Document ${documentName} on EC2 instance ${instanceId} status ${
|
|
160
|
+
`SSM Document ${documentName} on EC2 instance ${instanceId} unknown status: ${status}`
|
|
119
161
|
);
|
|
120
162
|
}
|
|
121
|
-
return { Data: responseData };
|
|
122
163
|
} catch (error) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const isThrottled = error.name === "ThrottlingException" || error.name === "TooManyRequestsException";
|
|
126
|
-
const isRetryable = isUnauthorized || isThrottled;
|
|
127
|
-
timeRemaining = context.getRemainingTimeInMillis();
|
|
128
|
-
if (isRetryable && timeRemaining > SLEEP_MS) {
|
|
164
|
+
const remainingTime = context.getRemainingTimeInMillis();
|
|
165
|
+
if (error.name === "InvocationDoesNotExist" && remainingTime > SLEEP_MS) {
|
|
129
166
|
console.log(
|
|
130
|
-
`
|
|
167
|
+
`Invocation not yet available. Sleeping: ${SLEEP_MS / 1e3}s`
|
|
131
168
|
);
|
|
132
169
|
await new Promise((resolve) => setTimeout(resolve, SLEEP_MS));
|
|
133
170
|
} else {
|
|
134
|
-
console.log("
|
|
171
|
+
console.log("Error checking command status:", error);
|
|
135
172
|
throw error;
|
|
136
173
|
}
|
|
137
174
|
}
|
package/awslint.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { App, Stack, StackProps } from 'aws-cdk-lib';
|
|
2
|
+
import { Construct } from 'constructs';
|
|
3
|
+
import { VSCodeServer } from '../../src/index'
|
|
4
|
+
|
|
5
|
+
export class MyStack extends Stack {
|
|
6
|
+
constructor(scope: Construct, id: string, props: StackProps = {}) {
|
|
7
|
+
super(scope, id, props);
|
|
8
|
+
|
|
9
|
+
new VSCodeServer(this, 'vscode', {
|
|
10
|
+
// Clone a git repository into the home folder during instance setup
|
|
11
|
+
// Perfect for workshops, training sessions, or development environments
|
|
12
|
+
repoUrl: 'https://github.com/aws-samples/aws-cdk-examples.git',
|
|
13
|
+
|
|
14
|
+
// Optional: customize the home folder path (default: /Workshop)
|
|
15
|
+
homeFolder: '/CdkWorkshop',
|
|
16
|
+
|
|
17
|
+
// Optional: specify VS Code user (default: vscode-user)
|
|
18
|
+
vscodeUser: 'workshop-user',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const env = {
|
|
24
|
+
account: '123456789912',
|
|
25
|
+
region: 'eu-central-1',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const app = new App();
|
|
29
|
+
new MyStack(app, 'vscode-server-git-repo', { env });
|
|
30
|
+
app.synth();
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"
|
|
17
|
+
"73ca3102a170a72edfc485eaa1468c73bbccd6bf566fd94f904e35c82f0fb905": {
|
|
18
18
|
"displayName": "IntegSetupVSCodeOnAl2023DefaultTestDeployAssert74D8F645 Template",
|
|
19
19
|
"source": {
|
|
20
20
|
"path": "IntegSetupVSCodeOnAl2023DefaultTestDeployAssert74D8F645.template.json",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"destinations": {
|
|
24
24
|
"current_account-current_region": {
|
|
25
25
|
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
|
|
26
|
-
"objectKey": "
|
|
26
|
+
"objectKey": "73ca3102a170a72edfc485eaa1468c73bbccd6bf566fd94f904e35c82f0fb905.json",
|
|
27
27
|
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
|
|
28
28
|
}
|
|
29
29
|
}
|