Skip to content

Commit a7d8c2a

Browse files
author
Yuriy Bezsonov
committed
WIP
1 parent 5583222 commit a7d8c2a

File tree

10 files changed

+84
-96
lines changed

10 files changed

+84
-96
lines changed

.kiro/specs/infra/deployment-guide.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ aws cloudformation deploy \
1313
--template-file cfn/java-on-aws-stack.yaml \
1414
--stack-name workshop-stack \
1515
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
16-
--s3-bucket workshop-cfn-templates-192330716364
16+
--s3-bucket workshop-cfn-templates-973079160866
1717
```
1818

19-
## Architecture Fix Applied
20-
**Fixed bootstrap failure rollback issue**: Removed WaitCondition dependencies from critical outputs to match original working architecture. Stack will still fail if bootstrap fails, but will rollback cleanly without orphaned resources.
19+
## Architecture Fixes Applied
20+
1. **Fixed bootstrap failure rollback issue**: Removed WaitCondition dependencies from critical outputs to match original working architecture. Stack will still fail if bootstrap fails, but will rollback cleanly without orphaned resources.
21+
2. **Fixed EKS startup delay**: Refactored role creation to match original architecture - role is created in props and shared between IDE and EKS, eliminating CloudFormation dependency that delayed EKS cluster creation.
2122

2223
## Test & Debug
2324

@@ -43,7 +44,7 @@ aws logs get-log-events \
4344
### Check EKS Cluster
4445
```bash
4546
source .env
46-
aws eks describe-cluster --name workshop-cluster
47+
aws eks describe-cluster --name workshop-eks
4748
kubectl get nodes
4849
kubectl get pods -A
4950
```

.kiro/specs/infra/requirements.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ This document specifies the requirements for creating a new AWS workshop infrast
184184
#### Acceptance Criteria
185185

186186
1. WHEN EKS cluster is created, THE system SHALL use the EKS v2 developer preview construct from package "software.amazon.awscdk.services.eks.v2.alpha" for native CloudFormation resource support
187-
2. WHEN EKS cluster is created, THE system SHALL name it "workshop-cluster" for universal identification across workshop types
187+
2. WHEN EKS cluster is created, THE system SHALL name it "workshop-eks" for universal identification across workshop types
188188
3. WHEN EKS cluster is configured, THE system SHALL use version 1.34 for current Kubernetes features and security updates
189189
4. WHEN EKS cluster deploys, THE system SHALL enable Auto Mode with "system" and "general-purpose" node pools for automatic node management
190190
5. WHEN EKS cluster networking is configured, THE system SHALL place cluster in private subnets with public and private API access for security and flexibility

.kiro/specs/infra/tasks.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@
374374

375375
- [ ] 100.2 Create EKS construct using EKS v2 with Auto Mode
376376
- Create infra/cdk/src/main/java/sample/com/constructs/Eks.java using software.amazon.awscdk.services.eks.v2.alpha
377-
- Configure workshop-cluster with Auto Mode, version 1.34, system+general-purpose node pools
377+
- Configure workshop-eks with Auto Mode, version 1.34, system+general-purpose node pools
378378
- Add 3 EKS add-ons: AWS Secrets Store CSI Driver, AWS Mountpoint S3 CSI Driver, EKS Pod Identity Agent
379379
- Create Access Entry for WSParticipantRole AND IDE instance role with cluster admin permissions
380380
- Use Access Entries authentication mode instead of ConfigMap-based authentication
@@ -408,7 +408,7 @@
408408
- Use infra/scripts/lib/common.sh for consistent emoji-based logging and error handling
409409
- Use infra/scripts/lib/wait-for-resources.sh wait_for_eks_cluster() function for cluster readiness
410410
- Check cluster status and wait until kubectl get ns works successfully before proceeding
411-
- Update kubeconfig and add workshop-cluster to kubectl context
411+
- Update kubeconfig and add workshop-eks to kubectl context
412412
- Deploy GP3 StorageClass (encrypted, default) since EKS Auto Mode doesn't provide encrypted GP3 by default
413413
- Deploy ALB IngressClass + IngressClassParams for Application Load Balancer integration
414414
- Create SecretProviderClass for database secrets (workshop-db-secret, workshop-db-password-secret, workshop-db-connection-string)

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,19 @@ public WorkshopStack(final Construct scope, final String id, final StackProps pr
4747

4848
// Core infrastructure (always created)
4949
Vpc vpc = new Vpc(this, "Vpc");
50-
Ide ide = new Ide(this, "Ide", IdeProps.builder()
50+
51+
// Create IDE props and get role for parallel resource creation
52+
IdeProps ideProps = IdeProps.builder()
5153
.vpc(vpc.getVpc())
5254
.gitBranch(gitBranch)
5355
.templateType(templateType)
54-
.build());
56+
.build();
57+
Ide ide = new Ide(this, "Ide", ideProps);
5558

5659
// CodeBuild for workshop setup
5760
CodeBuild codeBuild = new CodeBuild(this, "CodeBuild",
5861
CodeBuild.CodeBuildProps.builder()
59-
.projectName("workshop-setup")
62+
.projectName("workshop-codebuild")
6063
.vpc(vpc.getVpc())
6164
.environmentVariables(Map.of(
6265
"TEMPLATE_TYPE", templateType,
@@ -73,7 +76,7 @@ public WorkshopStack(final Construct scope, final String id, final StackProps pr
7376
if (!"java-ai-agents".equals(templateType)) {
7477
Eks eks = new Eks(this, "Eks", Eks.EksProps.builder()
7578
.vpc(vpc.getVpc())
76-
.ideInstanceRole(ide.getIdeRole())
79+
.ideInstanceRole(ideProps.getIdeRole())
7780
.build());
7881
}
7982
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class CodeBuild extends Construct {
2525
private final Role lambdaRole;
2626

2727
public static class CodeBuildProps {
28-
private String projectName = "workshop-setup";
28+
private String projectName = "workshop-codebuild";
2929
private IBuildImage buildImage = LinuxBuildImage.AMAZON_LINUX_2_5;
3030
private ComputeType computeType = ComputeType.MEDIUM;
3131
private Duration timeout = Duration.minutes(30);

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public Eks(final Construct scope, final String id, final EksProps props) {
2525

2626
// Create EKS cluster with Auto Mode (default)
2727
cluster = Cluster.Builder.create(this, "Cluster")
28-
.clusterName("workshop-cluster")
28+
.clusterName("workshop-eks")
2929
.version(KubernetesVersion.V1_34)
3030
.vpc(props.getVpc())
3131
.build();
@@ -41,7 +41,7 @@ private void createAddons() {
4141
// AWS Secrets Store CSI Driver
4242
Addon.Builder.create(this, "SecretsStoreCsiDriver")
4343
.cluster(cluster)
44-
.addonName("aws-secrets-store-csi-driver")
44+
.addonName("aws-secrets-store-csi-driver-provider")
4545
.build();
4646

4747
// AWS Mountpoint S3 CSI Driver
@@ -66,15 +66,14 @@ private void createAccessEntries(EksProps props) {
6666
.build()
6767
);
6868

69-
// WSParticipantRole Access Entry
70-
String wsParticipantRoleArn = String.format("arn:aws:iam::%s:role/WSParticipantRole", Aws.ACCOUNT_ID);
71-
72-
AccessEntry.Builder.create(this, "WSParticipantAccessEntry")
73-
.cluster(cluster)
74-
.principal(wsParticipantRoleArn)
75-
.accessEntryType(AccessEntryType.STANDARD)
76-
.accessPolicies(List.of(clusterAdminPolicy))
77-
.build();
69+
// WSParticipantRole Access Entry - TEMPORARILY COMMENTED OUT FOR TESTING
70+
// String wsParticipantRoleArn = String.format("arn:aws:iam::%s:role/WSParticipantRole", Aws.ACCOUNT_ID);
71+
// AccessEntry.Builder.create(this, "WSParticipantAccessEntry")
72+
// .cluster(cluster)
73+
// .principal(wsParticipantRoleArn)
74+
// .accessEntryType(AccessEntryType.STANDARD)
75+
// .accessPolicies(List.of(clusterAdminPolicy))
76+
// .build();
7877

7978
// IDE Instance Role Access Entry (if provided)
8079
if (props.getIdeInstanceRole() != null) {

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

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public static class IdeProps {
5454
private int bootstrapTimeoutMinutes = 30;
5555
private String gitBranch = "main";
5656
private String templateType = "base";
57+
private Role ideRole;
5758

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

@@ -69,6 +70,7 @@ public static class Builder {
6970
public Builder bootstrapTimeoutMinutes(int bootstrapTimeoutMinutes) { props.bootstrapTimeoutMinutes = bootstrapTimeoutMinutes; return this; }
7071
public Builder gitBranch(String gitBranch) { props.gitBranch = gitBranch; return this; }
7172
public Builder templateType(String templateType) { props.templateType = templateType; return this; }
73+
public Builder ideRole(Role ideRole) { props.ideRole = ideRole; return this; }
7274
public IdeProps build() { return props; }
7375
}
7476

@@ -82,6 +84,7 @@ public static class Builder {
8284
public int getBootstrapTimeoutMinutes() { return bootstrapTimeoutMinutes; }
8385
public String getGitBranch() { return gitBranch; }
8486
public String getTemplateType() { return templateType; }
87+
public Role getIdeRole() { return ideRole; }
8588
}
8689

8790
public Ide(final Construct scope, final String id, final IVpc vpc) {
@@ -95,16 +98,19 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
9598

9699
String instanceName = props.getInstanceName();
97100

98-
// Create workshop role for IDE instances
99-
this.ideRole = Role.Builder.create(this, "IdeRole")
100-
.roleName("ide-user")
101-
.assumedBy(ServicePrincipal.Builder.create("ec2.amazonaws.com").build())
102-
.managedPolicies(List.of(
103-
ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess"),
104-
ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"),
105-
ManagedPolicy.fromAwsManagedPolicyName("CloudWatchAgentServerPolicy")
106-
))
107-
.build();
101+
// Create workshop role for IDE instances if not provided
102+
if (props.getIdeRole() == null) {
103+
props.ideRole = Role.Builder.create(this, "IdeRole")
104+
.roleName("ide-user")
105+
.assumedBy(ServicePrincipal.Builder.create("ec2.amazonaws.com").build())
106+
.managedPolicies(List.of(
107+
ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess"),
108+
ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"),
109+
ManagedPolicy.fromAwsManagedPolicyName("CloudWatchAgentServerPolicy")
110+
))
111+
.build();
112+
}
113+
this.ideRole = props.getIdeRole();
108114

109115
// Add CloudFormation signaling permissions
110116
PolicyStatement cfnSignalPermissions = PolicyStatement.Builder.create()
@@ -115,7 +121,7 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
115121
.resources(List.of("*"))
116122
.build();
117123

118-
ideRole.addToPolicy(cfnSignalPermissions);
124+
this.ideRole.addToPolicy(cfnSignalPermissions);
119125

120126
// Load additional IAM policy from file
121127
var policyDocumentJson = loadFile("/iam-policy.json");
@@ -124,7 +130,7 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
124130
var policy = ManagedPolicy.Builder.create(this, "WorkshopIdeUserPolicy")
125131
.document(policyDocument)
126132
.build();
127-
ideRole.addManagedPolicy(policy);
133+
this.ideRole.addManagedPolicy(policy);
128134
}
129135

130136
// Create Lambda role for IDE Lambda functions
@@ -210,8 +216,8 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
210216

211217
// Create instance profile
212218
var instanceProfile = InstanceProfile.Builder.create(this, "IdeInstanceProfile")
213-
.role(ideRole)
214-
.instanceProfileName(ideRole.getRoleName())
219+
.role(this.ideRole)
220+
.instanceProfileName(this.ideRole.getRoleName())
215221
.build();
216222

217223
// Create Elastic IP
@@ -244,7 +250,7 @@ public Ide(final Construct scope, final String id, final IdeProps props) {
244250
.removalPolicy(RemovalPolicy.DESTROY)
245251
.build();
246252

247-
ideSecretsManagerPassword.grantRead(ideRole);
253+
ideSecretsManagerPassword.grantRead(this.ideRole);
248254

249255
// Create User Data for bootstrap with CloudWatch logging
250256
var userData = UserData.forLinux();

infra/cfn/base-stack.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,6 @@ Resources:
714714
Fn::GetAtt:
715715
- IdeInstanceLauncherFunction803C5A2A
716716
- Arn
717-
InstanceName: ide
718717
IamInstanceProfileArn:
719718
Fn::GetAtt:
720719
- IdeIdeInstanceProfile8BD997EA
@@ -872,6 +871,7 @@ Resources:
872871
exit 1
873872
fi
874873
InstanceTypes: m5.xlarge,m6i.xlarge,t3.xlarge
874+
InstanceName: ide
875875
UpdateReplacePolicy: Delete
876876
DeletionPolicy: Delete
877877
IdeIdeEipAssociation6C6C215D:
@@ -1251,7 +1251,7 @@ Resources:
12511251
ImagePullCredentialsType: CODEBUILD
12521252
PrivilegedMode: false
12531253
Type: LINUX_CONTAINER
1254-
Name: workshop-setup
1254+
Name: workshop-codebuild
12551255
ServiceRole:
12561256
Fn::GetAtt:
12571257
- CodeBuildCodeBuildRoleBA9C6D5C
@@ -1449,7 +1449,7 @@ Resources:
14491449
CodeBuildBuildCompleteRule06AAF17D:
14501450
Type: AWS::Events::Rule
14511451
Properties:
1452-
Description: workshop-setup build complete
1452+
Description: workshop-codebuild build complete
14531453
EventPattern:
14541454
detail:
14551455
project-name:
@@ -1495,7 +1495,7 @@ Resources:
14951495
Fn::GetAtt:
14961496
- CodeBuildCodeBuildRoleBA9C6D5C
14971497
- Arn
1498-
ContentHash: "1765718855273"
1498+
ContentHash: "1765721378904"
14991499
DependsOn:
15001500
- CodeBuildBuildCompleteRuleAllowEventRuleWorkshopStackCodeBuildReportLambdaFunctionD77C6091DA4A4BD8
15011501
- CodeBuildBuildCompleteRule06AAF17D

0 commit comments

Comments
 (0)