Skip to content

Commit 4d4fc68

Browse files
author
Yuriy Bezsonov
committed
WIP
1 parent 3447465 commit 4d4fc68

4 files changed

Lines changed: 134 additions & 96 deletions

File tree

infra/cdk/src/main/java/sample/com/WorkshopStack.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import software.amazon.awscdk.Aws;
88
import software.constructs.Construct;
99
import sample.com.constructs.*;
10+
import sample.com.constructs.Ide.IdeProps;
1011
import java.util.Map;
1112

1213
public class WorkshopStack extends Stack {
@@ -50,7 +51,10 @@ public WorkshopStack(final Construct scope, final String id, final StackProps pr
5051

5152
// Core infrastructure (always created)
5253
Vpc vpc = new Vpc(this, "Vpc");
53-
Ide ide = new Ide(this, "Ide", vpc.getVpc());
54+
Ide ide = new Ide(this, "Ide", IdeProps.builder()
55+
.vpc(vpc.getVpc())
56+
.gitBranch(gitBranch)
57+
.build());
5458

5559
// Custom roles only for non-base templates
5660
if (!"base".equals(templateType)) {

infra/cdk/src/main/java/sample/com/constructs/CodeBuild.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,12 @@ public CodeBuild(final Construct scope, final String id, final CodeBuildProps pr
133133

134134
// Create start build Lambda function
135135
var startLambda = new Lambda(this, "StartLambda",
136-
"/lambda/codebuild-start.py", props.getProjectName() + "-start", Duration.minutes(2), lambdaRole);
136+
"/lambda/codebuild-start.py", Aws.STACK_NAME + "-codebuild-start", Duration.minutes(2), lambdaRole);
137137
Function startBuildFunction = startLambda.getFunction();
138138

139139
// Create report build Lambda function
140140
var reportLambda = new Lambda(this, "ReportLambda",
141-
"/lambda/codebuild-report.py", props.getProjectName() + "-report", Duration.minutes(2), lambdaRole);
141+
"/lambda/codebuild-report.py", Aws.STACK_NAME + "-codebuild-report", Duration.minutes(2), lambdaRole);
142142
Function reportBuildFunction = reportLambda.getFunction();
143143

144144
// Create EventBridge rule for build completion

infra/cdk/src/main/java/sample/com/constructs/Ide.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public static class IdeProps {
5555
"ms-kubernetes-tools.vscode-kubernetes-tools",
5656
"ms-azuretools.vscode-docker"
5757
);
58+
private String gitBranch = "main";
5859

5960
public static IdeProps.Builder builder() { return new Builder(); }
6061

@@ -69,6 +70,7 @@ public static class Builder {
6970
public Builder additionalSecurityGroups(List<ISecurityGroup> additionalSecurityGroups) { props.additionalSecurityGroups = additionalSecurityGroups; return this; }
7071
public Builder bootstrapTimeoutMinutes(int bootstrapTimeoutMinutes) { props.bootstrapTimeoutMinutes = bootstrapTimeoutMinutes; return this; }
7172
public Builder vscodeExtensions(List<String> vscodeExtensions) { props.vscodeExtensions = vscodeExtensions; return this; }
73+
public Builder gitBranch(String gitBranch) { props.gitBranch = gitBranch; return this; }
7274

7375
public IdeProps build() { return props; }
7476
}
@@ -82,6 +84,7 @@ public static class Builder {
8284
public List<ISecurityGroup> getAdditionalSecurityGroups() { return additionalSecurityGroups; }
8385
public int getBootstrapTimeoutMinutes() { return bootstrapTimeoutMinutes; }
8486
public List<String> getVscodeExtensions() { return vscodeExtensions; }
87+
public String getGitBranch() { return gitBranch; }
8588
}
8689

8790
public Ide(final Construct scope, final String id, final IVpc vpc) {
@@ -153,7 +156,7 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
153156

154157
// Create CloudFront prefix list lookup Lambda function
155158
var prefixListLookup = new Lambda(this, "PrefixListLookup",
156-
"/lambda/cloudfront-prefix-lookup.py", instanceName + "-prefix-list-lambda", Duration.minutes(3), lambdaRole);
159+
"/lambda/cloudfront-prefix-lookup.py", Aws.STACK_NAME + "-cloudfront-prefix-lookup", Duration.minutes(3), lambdaRole);
157160
var prefixListFunction = prefixListLookup.getFunction();
158161

159162
// Add EC2 permissions for prefix list lookup
@@ -241,12 +244,15 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
241244
String bootstrapScript = loadFile("/ec2-userdata.sh")
242245
.replace("${vscodeExtensions}", extensionsString)
243246
.replace("${templateType}", "base")
244-
.replace("${gitBranch}", "new-ws-infra");
247+
.replace("${gitBranch}", props.getGitBranch())
248+
.replace("${stackName}", Aws.STACK_NAME)
249+
.replace("${awsRegion}", Aws.REGION)
250+
.replace("${idePassword}", ideSecretsManagerPassword.secretValueFromJson("password").unsafeUnwrap());
245251
userData.addCommands(bootstrapScript.split("\n"));
246252

247253
// Create instance launcher Lambda with multi-AZ and multi-instance-type failover
248254
var instanceLauncher = new Lambda(this, "InstanceLauncher",
249-
"/lambda/ec2-launcher.py", instanceName + "-launcher", Duration.minutes(5), lambdaRole);
255+
"/lambda/ec2-launcher.py", Aws.STACK_NAME + "-ec2-launcher", Duration.minutes(5), lambdaRole);
250256
var instanceLauncherFunction = instanceLauncher.getFunction();
251257

252258
// Create EC2 instance via Custom Resource with intelligent failover

infra/workshop-template.yaml

Lines changed: 118 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,11 @@ Resources:
456456
responseData = {'Error': tb_err}
457457
finally:
458458
cfnresponse.send(event, context, status, responseData, 'CustomResourcePhysicalID')
459-
FunctionName: ide-prefix-list-lambda
459+
FunctionName:
460+
Fn::Join:
461+
- ""
462+
- - Ref: AWS::StackName
463+
- -cloudfront-prefix-lookup
460464
Handler: index.lambda_handler
461465
Role:
462466
Fn::GetAtt:
@@ -704,7 +708,11 @@ Resources:
704708
responseData = {'Error': tb_err}
705709
706710
cfnresponse.send(event, context, status, responseData, physical_id)
707-
FunctionName: ide-launcher
711+
FunctionName:
712+
Fn::Join:
713+
- ""
714+
- - Ref: AWS::StackName
715+
- -ec2-launcher
708716
Handler: index.lambda_handler
709717
Role:
710718
Fn::GetAtt:
@@ -752,107 +760,119 @@ Resources:
752760
ImageId:
753761
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
754762
UserData:
755-
Fn::Base64: |-
756-
#!/bin/bash
757-
#!/bin/bash
758-
set -e
763+
Fn::Base64:
764+
Fn::Join:
765+
- ""
766+
- - |-
767+
#!/bin/bash
768+
#!/bin/bash
769+
set -e
759770

760-
# Minimal EC2 UserData script - downloads and runs full bootstrap
761-
# This keeps UserData under size limits while allowing unlimited bootstrap size
771+
# Minimal EC2 UserData script - downloads and runs full bootstrap
772+
# This keeps UserData under size limits while allowing unlimited bootstrap size
762773

763-
# Configuration from CDK
764-
GIT_BRANCH="${gitBranch:-main}"
765-
IDE_PASSWORD="${idePassword}"
766-
STACK_NAME="${stackName}"
767-
AWS_REGION="${awsRegion}"
768-
TEMPLATE_TYPE="${templateType:-base}"
769-
VSCODE_EXTENSIONS="${vscodeExtensions:-}"
774+
# Configuration from CDK
775+
GIT_BRANCH="${gitBranch:-main}"
776+
IDE_PASSWORD="{{resolve:secretsmanager:
777+
- Ref: IdeIdePasswordSecretF3482811
778+
- |-
779+
:SecretString:password::}}"
780+
STACK_NAME="
781+
- Ref: AWS::StackName
782+
- |-
783+
"
784+
AWS_REGION="
785+
- Ref: AWS::Region
786+
- |-
787+
"
788+
TEMPLATE_TYPE="${templateType:-base}"
789+
VSCODE_EXTENSIONS="${vscodeExtensions:-}"
770790
771-
# Setup logging
772-
LOG_GROUP_NAME="ide-bootstrap-$(date +%Y%m%d-%H%M%S)"
773-
echo "Bootstrap logs will be written to CloudWatch log group: $LOG_GROUP_NAME"
791+
# Setup logging
792+
LOG_GROUP_NAME="ide-bootstrap-$(date +%Y%m%d-%H%M%S)"
793+
echo "Bootstrap logs will be written to CloudWatch log group: $LOG_GROUP_NAME"
774794
775-
# Install CloudWatch agent for logging
776-
dnf install -y amazon-cloudwatch-agent
795+
# Install CloudWatch agent for logging
796+
dnf install -y amazon-cloudwatch-agent
777797
778-
# Create CloudWatch agent configuration
779-
cat > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json << EOF
780-
{
781-
"logs": {
782-
"logs_collected": {
783-
"files": {
784-
"collect_list": [
785-
{
786-
"file_path": "/var/log/bootstrap.log",
787-
"log_group_name": "$LOG_GROUP_NAME",
788-
"log_stream_name": "{instance_id}",
789-
"retention_in_days": 7
798+
# Create CloudWatch agent configuration
799+
cat > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json << EOF
800+
{
801+
"logs": {
802+
"logs_collected": {
803+
"files": {
804+
"collect_list": [
805+
{
806+
"file_path": "/var/log/bootstrap.log",
807+
"log_group_name": "$LOG_GROUP_NAME",
808+
"log_stream_name": "{instance_id}",
809+
"retention_in_days": 7
810+
}
811+
]
812+
}
790813
}
791-
]
814+
}
792815
}
793-
}
794-
}
795-
}
796-
EOF
816+
EOF
797817
798-
# Start CloudWatch agent
799-
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
800-
-a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s
818+
# Start CloudWatch agent
819+
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
820+
-a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s
801821
802-
# Redirect all output to log file and console
803-
exec > >(tee -a /var/log/bootstrap.log)
804-
exec 2>&1
822+
# Redirect all output to log file and console
823+
exec > >(tee -a /var/log/bootstrap.log)
824+
exec 2>&1
805825
806-
echo "UserData started at $(date) - Logging to $LOG_GROUP_NAME"
826+
echo "UserData started at $(date) - Logging to $LOG_GROUP_NAME"
807827
808-
# Download and run full bootstrap script with retry logic
809-
download_bootstrap() {
810-
local urls=(
811-
"https://raw.githubusercontent.com/aws-samples/java-on-aws/${GIT_BRANCH}/infra/scripts/ide/bootstrap.sh"
812-
"https://github.com/aws-samples/java-on-aws/raw/${GIT_BRANCH}/infra/scripts/ide/bootstrap.sh"
813-
)
814-
local max_attempts=5
815-
local delay=5
828+
# Download and run full bootstrap script with retry logic
829+
download_bootstrap() {
830+
local urls=(
831+
"https://raw.githubusercontent.com/aws-samples/java-on-aws/${GIT_BRANCH}/infra/scripts/ide/bootstrap.sh"
832+
"https://github.com/aws-samples/java-on-aws/raw/${GIT_BRANCH}/infra/scripts/ide/bootstrap.sh"
833+
)
834+
local max_attempts=5
835+
local delay=5
816836
817-
for attempt in $(seq 1 $max_attempts); do
818-
echo "Download attempt $attempt of $max_attempts"
837+
for attempt in $(seq 1 $max_attempts); do
838+
echo "Download attempt $attempt of $max_attempts"
819839
820-
for url in "${urls[@]}"; do
821-
echo "Trying to download bootstrap from: $url"
822-
if curl -fsSL --connect-timeout 30 --max-time 60 "$url" -o /tmp/bootstrap.sh; then
823-
echo "Successfully downloaded bootstrap script on attempt $attempt"
824-
return 0
825-
fi
826-
echo "Failed to download from: $url"
827-
done
840+
for url in "${urls[@]}"; do
841+
echo "Trying to download bootstrap from: $url"
842+
if curl -fsSL --connect-timeout 30 --max-time 60 "$url" -o /tmp/bootstrap.sh; then
843+
echo "Successfully downloaded bootstrap script on attempt $attempt"
844+
return 0
845+
fi
846+
echo "Failed to download from: $url"
847+
done
828848
829-
if [ $attempt -lt $max_attempts ]; then
830-
echo "All URLs failed on attempt $attempt, waiting ${delay}s before retry..."
831-
sleep $delay
832-
fi
833-
done
849+
if [ $attempt -lt $max_attempts ]; then
850+
echo "All URLs failed on attempt $attempt, waiting ${delay}s before retry..."
851+
sleep $delay
852+
fi
853+
done
834854
835-
echo "All download attempts failed after $max_attempts tries"
836-
return 1
837-
}
855+
echo "All download attempts failed after $max_attempts tries"
856+
return 1
857+
}
838858
839-
if download_bootstrap; then
840-
chmod +x /tmp/bootstrap.sh
841-
echo "Executing full bootstrap script..."
842-
export VSCODE_EXTENSIONS="$VSCODE_EXTENSIONS"
843-
if /tmp/bootstrap.sh "$IDE_PASSWORD" "$GIT_BRANCH" "$STACK_NAME" "$AWS_REGION" "$TEMPLATE_TYPE"; then
844-
echo "Bootstrap completed successfully"
845-
/opt/aws/bin/cfn-signal -e 0 --stack "$STACK_NAME" --resource IdeBootstrapWaitCondition --region "$AWS_REGION"
846-
else
847-
echo "FATAL: Bootstrap script failed"
848-
/opt/aws/bin/cfn-signal -e 1 --stack "$STACK_NAME" --resource IdeBootstrapWaitCondition --region "$AWS_REGION"
849-
exit 1
850-
fi
851-
else
852-
echo "FATAL: Could not download bootstrap script from any source"
853-
/opt/aws/bin/cfn-signal -e 1 --stack "$STACK_NAME" --resource IdeBootstrapWaitCondition --region "$AWS_REGION"
854-
exit 1
855-
fi
859+
if download_bootstrap; then
860+
chmod +x /tmp/bootstrap.sh
861+
echo "Executing full bootstrap script..."
862+
export VSCODE_EXTENSIONS="$VSCODE_EXTENSIONS"
863+
if /tmp/bootstrap.sh "$IDE_PASSWORD" "$GIT_BRANCH" "$STACK_NAME" "$AWS_REGION" "$TEMPLATE_TYPE"; then
864+
echo "Bootstrap completed successfully"
865+
/opt/aws/bin/cfn-signal -e 0 --stack "$STACK_NAME" --resource IdeBootstrapWaitCondition --region "$AWS_REGION"
866+
else
867+
echo "FATAL: Bootstrap script failed"
868+
/opt/aws/bin/cfn-signal -e 1 --stack "$STACK_NAME" --resource IdeBootstrapWaitCondition --region "$AWS_REGION"
869+
exit 1
870+
fi
871+
else
872+
echo "FATAL: Could not download bootstrap script from any source"
873+
/opt/aws/bin/cfn-signal -e 1 --stack "$STACK_NAME" --resource IdeBootstrapWaitCondition --region "$AWS_REGION"
874+
exit 1
875+
fi
856876
InstanceTypes: m5.xlarge,m6i.xlarge,t3.xlarge
857877
InstanceName: ide
858878
IamInstanceProfileArn:
@@ -1241,7 +1261,11 @@ Resources:
12411261
responseData = {'Error': tb_err}
12421262
12431263
cfnresponse.send(event, context, status, responseData, physical_id)
1244-
FunctionName: base-setup-start
1264+
FunctionName:
1265+
Fn::Join:
1266+
- ""
1267+
- - Ref: AWS::StackName
1268+
- -codebuild-start
12451269
Handler: index.lambda_handler
12461270
Role:
12471271
Fn::GetAtt:
@@ -1318,7 +1342,11 @@ Resources:
13181342
'error': str(e)
13191343
})
13201344
}
1321-
FunctionName: base-setup-report
1345+
FunctionName:
1346+
Fn::Join:
1347+
- ""
1348+
- - Ref: AWS::StackName
1349+
- -codebuild-report
13221350
Handler: index.lambda_handler
13231351
Role:
13241352
Fn::GetAtt:
@@ -1387,7 +1415,7 @@ Resources:
13871415
Fn::GetAtt:
13881416
- CodeBuildCodeBuildRoleBA9C6D5C
13891417
- Arn
1390-
ContentHash: "1765651009800"
1418+
ContentHash: "1765651951549"
13911419
ProjectName:
13921420
Ref: CodeBuildProjectA0FF5539
13931421
DependsOn:

0 commit comments

Comments
 (0)