Skip to content

Commit cb55391

Browse files
author
Yuriy Bezsonov
committed
refactor(infra): simplify construct configuration and update monitoring setup
1 parent 200e025 commit cb55391

10 files changed

Lines changed: 167 additions & 141 deletions

File tree

apps/unicorn-store-spring-java25/pom.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,6 @@
8686
<groupId>io.micrometer</groupId>
8787
<artifactId>micrometer-registry-prometheus</artifactId>
8888
</dependency>
89-
<dependency>
90-
<groupId>org.aspectj</groupId>
91-
<artifactId>aspectjweaver</artifactId>
92-
</dependency>
9389

9490
<!-- Serialization -->
9591
<dependency>

apps/unicorn-store-spring-java25/src/main/java/com/unicorn/store/config/MonitoringConfig.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,6 @@ ObservedAspect observedAspect(ObservationRegistry registry) {
3939
return new ObservedAspect(registry);
4040
}
4141

42-
// Filters actuator endpoints from observations to reduce metric/trace noise
43-
@Bean
44-
ObservationPredicate noActuatorTraces() {
45-
return (name, context) -> !(context instanceof ServerRequestObservationContext ctx &&
46-
ctx.getCarrier().getRequestURI().startsWith("/actuator"));
47-
}
48-
4942
@PostConstruct
5043
public void configureMeterRegistry() {
5144
String clusterType = System.getenv("ECS_CONTAINER_METADATA_URI_V4") != null ? "ecs" : "eks";

infra/README.md

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ All scripts implement consistent error handling:
135135
### Resource Naming
136136

137137
All AWS resources use a configurable prefix (default: `workshop`) following the pattern `{prefix}-{component}-{function}`:
138-
- Lambda functions: `workshop-ide-launcher`, `workshop-codebuild-start`
139-
- CodeBuild: `workshop-setup`
138+
- Lambda functions: `workshop-ide-launcher`
140139
- Database: `workshop-db-cluster`, `workshop-db-writer`
141140
- EKS: `workshop-eks`
142141
- Secrets: `workshop-db-secret`, `workshop-db-password-secret`
@@ -145,6 +144,47 @@ Exceptions for app-specific compatibility:
145144
- Unicorn construct uses `unicorn*` naming
146145
- AiJvmAnalyzer uses `ai-jvm-analyzer-*` naming
147146

147+
### Multi-Instance Construct Support
148+
149+
The infrastructure supports multiple instances of certain constructs with unique, predictable naming:
150+
151+
#### Multi-Instance Capable Constructs
152+
- **CodeBuild**: Uses `projectName` parameter for all resource naming
153+
- CodeBuild project: `{projectName}`
154+
- Lambda functions: `{projectName}-start`, `{projectName}-report`
155+
- EventBridge rules: Filtered by project name
156+
- **EcsExpressService**: Uses `appName` parameter for all resource naming
157+
- ECS cluster: `{appName}`
158+
- ECS service: `{appName}`
159+
- CloudWatch log group: `/aws/ecs/{appName}`
160+
- **Lambda**: Uses `functionName` parameter for function naming
161+
- Lambda function: `{functionName}`
162+
163+
#### Singleton Constructs
164+
These constructs are designed as singletons and should only be instantiated once per stack:
165+
- **Vpc**: Creates shared VPC infrastructure
166+
- **Database**: Creates shared Aurora PostgreSQL cluster
167+
- **Eks**: Creates shared EKS cluster
168+
- **Unicorn**: Creates shared EventBus and IAM roles with hardcoded names
169+
- **Ide**: Creates single IDE instance
170+
- **WorkshopBucket**: Creates shared S3 bucket
171+
- **EcrRegistry**: Sets account-wide ECR settings
172+
173+
#### Current Multi-Instance Usage
174+
```java
175+
// Two CodeBuild instances with unique project names
176+
new CodeBuild(this, "CodeBuild",
177+
CodeBuildProps.builder().projectName("workshop-setup").build());
178+
new CodeBuild(this, "PlaceholderImageBuild",
179+
CodeBuildProps.builder().projectName("workshop-placeholder-images").build());
180+
181+
// Two ECS services with unique app names
182+
new EcsExpressService(this, "SpringAiAgent",
183+
EcsExpressServiceProps.builder().appName("unicorn-spring-ai-agent").build());
184+
new EcsExpressService(this, "McpServer",
185+
EcsExpressServiceProps.builder().appName("unicorn-store-spring").build());
186+
```
187+
148188
### Development Tools
149189

150190
The IDE includes comprehensive development tooling:

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ public WorkshopStack(final Construct scope, final String id, final StackProps pr
7474
// CodeBuild for workshop setup (service-linked role creation)
7575
new CodeBuild(this, "CodeBuild",
7676
CodeBuild.CodeBuildProps.builder()
77-
.prefix(prefix)
7877
.projectName(prefix + "-setup")
7978
.vpc(vpc.getVpc())
8079
.environmentVariables(Map.of(
@@ -160,9 +159,11 @@ public WorkshopStack(final Construct scope, final String id, final StackProps pr
160159
161160
# Create placeholder Dockerfile
162161
cat > /tmp/Dockerfile << 'EOF'
163-
FROM public.ecr.aws/nginx/nginx:stable-alpine
164-
RUN echo 'server { listen 8080; location /actuator/health { return 200 "OK"; } location / { return 200 "Placeholder"; } }' > /etc/nginx/conf.d/default.conf
162+
FROM public.ecr.aws/docker/library/nginx:stable
163+
RUN echo '<html><body><h1>Hello World!</h1><p>Build timestamp: '$(date)'</p></body></html>' > /usr/share/nginx/html/index.html
164+
RUN sed -i 's/listen\\s*80;/listen 8080;/' /etc/nginx/conf.d/default.conf
165165
EXPOSE 8080
166+
CMD ["nginx", "-g", "daemon off;"]
166167
EOF
167168
168169
# Build and push placeholder to both repos (create-on-push creates repos)
@@ -175,7 +176,6 @@ public WorkshopStack(final Construct scope, final String id, final StackProps pr
175176

176177
CodeBuild placeholderImageBuild = new CodeBuild(this, "PlaceholderImageBuild",
177178
CodeBuild.CodeBuildProps.builder()
178-
.prefix(prefix)
179179
.projectName(prefix + "-placeholder-images")
180180
.vpc(vpc.getVpc())
181181
.privilegedMode(true)

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ public class CodeBuild extends Construct {
2424
private final Role lambdaRole;
2525

2626
public static class CodeBuildProps {
27-
private String prefix = "workshop";
2827
private String projectName = "workshop-setup";
2928
private IBuildImage buildImage = LinuxBuildImage.AMAZON_LINUX_2_5;
3029
private ComputeType computeType = ComputeType.MEDIUM;
@@ -39,7 +38,6 @@ public static class CodeBuildProps {
3938
public static class Builder {
4039
private CodeBuildProps props = new CodeBuildProps();
4140

42-
public Builder prefix(String prefix) { props.prefix = prefix; return this; }
4341
public Builder projectName(String projectName) { props.projectName = projectName; return this; }
4442
public Builder buildImage(IBuildImage buildImage) { props.buildImage = buildImage; return this; }
4543
public Builder computeType(ComputeType computeType) { props.computeType = computeType; return this; }
@@ -53,7 +51,6 @@ public static class Builder {
5351
}
5452

5553
// Getters
56-
public String getPrefix() { return prefix; }
5754
public String getProjectName() { return projectName; }
5855
public IBuildImage getBuildImage() { return buildImage; }
5956
public ComputeType getComputeType() { return computeType; }
@@ -75,8 +72,6 @@ public CodeBuild(final Construct scope, final String id, final IVpc vpc, final M
7572
public CodeBuild(final Construct scope, final String id, final CodeBuildProps props) {
7673
super(scope, id);
7774

78-
String prefix = props.getPrefix();
79-
8075
// Create CodeBuild service role
8176
this.codeBuildRole = Role.Builder.create(this, "Role")
8277
.assumedBy(ServicePrincipal.Builder.create("codebuild.amazonaws.com").build())
@@ -135,12 +130,12 @@ public CodeBuild(final Construct scope, final String id, final CodeBuildProps pr
135130

136131
// Create start build Lambda function
137132
var startLambda = new Lambda(this, "StartLambda",
138-
"/lambda/codebuild-start.py", prefix + "-codebuild-start", Duration.minutes(2), lambdaRole);
133+
"/lambda/codebuild-start.py", props.getProjectName() + "-start", Duration.minutes(2), lambdaRole);
139134
Function startBuildFunction = startLambda.getFunction();
140135

141136
// Create report build Lambda function
142137
var reportLambda = new Lambda(this, "ReportLambda",
143-
"/lambda/codebuild-report.py", prefix + "-codebuild-report", Duration.minutes(2), lambdaRole);
138+
"/lambda/codebuild-report.py", props.getProjectName() + "-report", Duration.minutes(2), lambdaRole);
144139
Function reportBuildFunction = reportLambda.getFunction();
145140

146141
// Create EventBridge rule for build completion

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public EcsExpressService(final Construct scope, final String id, final EcsExpres
8989
.build())
9090
.cpu("1024")
9191
.memory("2048")
92-
.healthCheckPath("/actuator/health")
92+
.healthCheckPath("/")
9393
.networkConfiguration(CfnExpressGatewayService.ExpressGatewayServiceNetworkConfigurationProperty.builder()
9494
.subnets(publicSubnetIds)
9595
.securityGroups(List.of(dbSecurityGroupId))

infra/cfn/base-stack.yaml

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -676,29 +676,6 @@ Resources:
676676
Fn::GetAtt:
677677
- IdeInstanceLauncherFunction803C5A2A
678678
- Arn
679-
SecurityGroupIds:
680-
Fn::Join:
681-
- ""
682-
- - Fn::GetAtt:
683-
- IdeSecurityGroup73B02454
684-
- GroupId
685-
- ","
686-
- Fn::GetAtt:
687-
- IdeInternalSecurityGroupB0A5D76B
688-
- GroupId
689-
SubnetIds:
690-
Fn::Join:
691-
- ""
692-
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
693-
- ","
694-
- Ref: VpcPublicSubnet2SubnetA811849C
695-
VolumeSize: "50"
696-
IamInstanceProfileArn:
697-
Fn::GetAtt:
698-
- IdeInstanceProfile61B92038
699-
- Arn
700-
InstanceName: ide
701-
InstanceTypes: m6a.xlarge,m7a.xlarge
702679
UserData:
703680
Fn::Base64:
704681
Fn::Join:
@@ -835,6 +812,29 @@ Resources:
835812
"
836813
exit 1
837814
fi
815+
InstanceTypes: m6a.xlarge,m7a.xlarge
816+
InstanceName: ide
817+
IamInstanceProfileArn:
818+
Fn::GetAtt:
819+
- IdeInstanceProfile61B92038
820+
- Arn
821+
VolumeSize: "50"
822+
SubnetIds:
823+
Fn::Join:
824+
- ""
825+
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
826+
- ","
827+
- Ref: VpcPublicSubnet2SubnetA811849C
828+
SecurityGroupIds:
829+
Fn::Join:
830+
- ""
831+
- - Fn::GetAtt:
832+
- IdeSecurityGroup73B02454
833+
- GroupId
834+
- ","
835+
- Fn::GetAtt:
836+
- IdeInternalSecurityGroupB0A5D76B
837+
- GroupId
838838
ImageId:
839839
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
840840
UpdateReplacePolicy: Delete

infra/cfn/java-on-amazon-eks-stack.yaml

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -794,18 +794,19 @@ Resources:
794794
Fn::GetAtt:
795795
- IdeInstanceLauncherFunction803C5A2A
796796
- Arn
797-
SecurityGroupIds:
797+
SubnetIds:
798798
Fn::Join:
799799
- ""
800-
- - Fn::GetAtt:
801-
- IdeSecurityGroup73B02454
802-
- GroupId
800+
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
803801
- ","
804-
- Fn::GetAtt:
805-
- IdeInternalSecurityGroupB0A5D76B
806-
- GroupId
807-
ImageId:
808-
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
802+
- Ref: VpcPublicSubnet2SubnetA811849C
803+
VolumeSize: "50"
804+
IamInstanceProfileArn:
805+
Fn::GetAtt:
806+
- IdeInstanceProfile61B92038
807+
- Arn
808+
InstanceName: ide
809+
InstanceTypes: m6a.xlarge,m7a.xlarge
809810
UserData:
810811
Fn::Base64:
811812
Fn::Join:
@@ -942,19 +943,18 @@ Resources:
942943
"
943944
exit 1
944945
fi
945-
InstanceTypes: m6a.xlarge,m7a.xlarge
946-
InstanceName: ide
947-
IamInstanceProfileArn:
948-
Fn::GetAtt:
949-
- IdeInstanceProfile61B92038
950-
- Arn
951-
VolumeSize: "50"
952-
SubnetIds:
946+
ImageId:
947+
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
948+
SecurityGroupIds:
953949
Fn::Join:
954950
- ""
955-
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
951+
- - Fn::GetAtt:
952+
- IdeSecurityGroup73B02454
953+
- GroupId
956954
- ","
957-
- Ref: VpcPublicSubnet2SubnetA811849C
955+
- Fn::GetAtt:
956+
- IdeInternalSecurityGroupB0A5D76B
957+
- GroupId
958958
UpdateReplacePolicy: Delete
959959
DeletionPolicy: Delete
960960
IdeEipAssociationDFF81215:
@@ -1333,12 +1333,12 @@ Resources:
13331333
Environment:
13341334
ComputeType: BUILD_GENERAL1_MEDIUM
13351335
EnvironmentVariables:
1336-
- Name: GIT_BRANCH
1337-
Type: PLAINTEXT
1338-
Value: new-ws-infra
13391336
- Name: TEMPLATE_TYPE
13401337
Type: PLAINTEXT
13411338
Value: java-on-amazon-eks
1339+
- Name: GIT_BRANCH
1340+
Type: PLAINTEXT
1341+
Value: new-ws-infra
13421342
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
13431343
ImagePullCredentialsType: CODEBUILD
13441344
PrivilegedMode: false
@@ -1460,7 +1460,7 @@ Resources:
14601460
responseData = {'Error': tb_err}
14611461
14621462
cfnresponse.send(event, context, status, responseData, physical_id)
1463-
FunctionName: workshop-codebuild-start
1463+
FunctionName: workshop-setup-start
14641464
Handler: index.lambda_handler
14651465
Role:
14661466
Fn::GetAtt:
@@ -1526,7 +1526,7 @@ Resources:
15261526
'error': str(e)
15271527
})
15281528
}
1529-
FunctionName: workshop-codebuild-report
1529+
FunctionName: workshop-setup-report
15301530
Handler: index.lambda_handler
15311531
Role:
15321532
Fn::GetAtt:
@@ -1543,12 +1543,12 @@ Resources:
15431543
Description: workshop-setup build complete
15441544
EventPattern:
15451545
detail:
1546+
project-name:
1547+
- Ref: CodeBuildProjectA0FF5539
15461548
build-status:
15471549
- SUCCEEDED
15481550
- FAILED
15491551
- STOPPED
1550-
project-name:
1551-
- Ref: CodeBuildProjectA0FF5539
15521552
detail-type:
15531553
- CodeBuild Build State Change
15541554
source:
@@ -1580,13 +1580,13 @@ Resources:
15801580
Fn::GetAtt:
15811581
- CodeBuildStartLambdaFunction8349284F
15821582
- Arn
1583+
ProjectName:
1584+
Ref: CodeBuildProjectA0FF5539
1585+
ContentHash: "1767604218045"
15831586
CodeBuildIamRoleArn:
15841587
Fn::GetAtt:
15851588
- CodeBuildRoleE9A44575
15861589
- Arn
1587-
ContentHash: "1767557212506"
1588-
ProjectName:
1589-
Ref: CodeBuildProjectA0FF5539
15901590
DependsOn:
15911591
- CodeBuildCompleteRuleAllowEventRuleWorkshopStackCodeBuildReportLambdaFunctionD77C60919E0B0C89
15921592
- CodeBuildCompleteRuleEE9277E8
@@ -1944,7 +1944,7 @@ Resources:
19441944
- Ref: AWS::AccountId
19451945
- "-"
19461946
- Ref: AWS::Region
1947-
- "-20260104210652"
1947+
- "-20260105101018"
19481948
PublicAccessBlockConfiguration:
19491949
BlockPublicAcls: true
19501950
BlockPublicPolicy: true
@@ -2703,12 +2703,12 @@ Resources:
27032703
}
27042704
Environment:
27052705
Variables:
2706-
SECRET_NAME: workshop-ide-password
2707-
EKS_CLUSTER_NAME:
2708-
Ref: EksClusterB2BDED5B
2706+
S3_THREAD_DUMPS_PREFIX: thread-dumps/
27092707
S3_BUCKET_NAME:
27102708
Ref: WorkshopBucketFD5BC43F
2711-
S3_THREAD_DUMPS_PREFIX: thread-dumps/
2709+
EKS_CLUSTER_NAME:
2710+
Ref: EksClusterB2BDED5B
2711+
SECRET_NAME: workshop-ide-password
27122712
FunctionName: workshop-thread-dump-lambda
27132713
Handler: index.lambda_handler
27142714
MemorySize: 512

0 commit comments

Comments
 (0)