Coverage for app.py: 100.00%

60 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-09-14 22:07 +0000

1#!/usr/bin/env python3 

2""" 

3GCO (Global Capacity Orchestrator on AWS) - Multi-Region EKS Auto Mode Platform for AI/ML Workloads 

4 

5This is the main CDK application entry point that orchestrates the deployment of: 

6- Global Stack: partition-wide state plus AWS Global Accelerator in the commercial `aws` partition 

7- API Gateway Stack: Centralized IAM-authenticated entry point 

8- Regional Stacks: EKS clusters, internal ALBs, and services per region 

9- Regional API Bridges: SigV4 entry points with VPC Lambdas for aggregation and direct access (optional in `aws`, required elsewhere) 

10- Monitoring Stack: Cross-region CloudWatch dashboards and alarms 

11- Optional Analytics Stack: SageMaker Studio and EMR Serverless 

12 

13Architecture: 

14 Commercial `aws`: User → API Gateway (IAM Auth) → Global Accelerator → Internal Regional ALB → EKS Services 

15 Other partitions: User → Regional API Gateway (IAM Auth) → VPC Lambda → Internal Regional ALB → EKS Services 

16 Aggregator → Regional API Gateway (SigV4) → VPC Lambda → Internal Regional ALB 

17 

18Usage: 

19 cdk deploy --all # Deploy all stacks 

20 cdk deploy gco-us-east-1 # Deploy single region 

21 cdk destroy --all # Cleanup all resources 

22""" 

23 

24import os 

25from pathlib import Path 

26 

27import aws_cdk as cdk 

28import jsii 

29from constructs import IConstruct 

30 

31from cli.stacks import cdk_asset_consumer 

32from gco.config.config_loader import ConfigLoader 

33from gco.stacks.analytics_stack import GCOAnalyticsStack 

34from gco.stacks.api_gateway_global_stack import AnalyticsApiConfig, GCOApiGatewayGlobalStack 

35from gco.stacks.global_stack import GCOGlobalStack 

36from gco.stacks.monitoring_stack import GCOMonitoringStack 

37from gco.stacks.nag_suppressions import nag_validation_plugins 

38from gco.stacks.regional_api_gateway_stack import GCORegionalApiGatewayStack 

39from gco.stacks.regional_stack import GCORegionalStack 

40 

41# <pyflowchart-code-diagram> BEGIN - auto-inserted, do not edit 

42# Generated at (UTC): 2026-09-01T14:42:56Z 

43# Generated from Git commit: 89b000378ed5a912a38c06f4feab2b029936ebcc 

44# Flowchart(s) generated from this file: 

45# * ``main`` -> ``diagrams/code_diagrams/app.main.html`` 

46# (PNG: ``diagrams/code_diagrams/app.main.png``) 

47# Regenerate with ``SOURCE_DATE_EPOCH=<unix-seconds> GCO_DIAGRAM_SOURCE_COMMIT=<40-char-sha> python diagrams/generate.py --code-only``. 

48# <pyflowchart-code-diagram> END 

49 

50 

51# AWS Solutions guidance identifier. Only the GCO *global* stack description is 

52# prefixed with this string, so a single deployment is attributable to the 

53# published guidance (SO9707) through one stack. 

54SOLUTION_ID = "SO9707" 

55SOLUTION_DESCRIPTION_PREFIX = ( 

56 f"({SOLUTION_ID}) - Guidance for EKS AutoMode Clusters with Global Capacity Orchestrator on AWS" 

57) 

58 

59 

60@jsii.implements(cdk.IAspect) 

61class LambdaTracingAspect: 

62 """CDK Aspect that enables X-Ray tracing on all Lambda functions. 

63 

64 This catches CDK Provider Framework Lambdas that we don't create directly, 

65 ensuring every Lambda in the stack has tracing=ACTIVE. 

66 """ 

67 

68 def visit(self, node: IConstruct) -> None: 

69 if isinstance(node, cdk.aws_lambda.CfnFunction): 

70 node.tracing_config = cdk.aws_lambda.CfnFunction.TracingConfigProperty(mode="Active") 

71 

72 

73@cdk_asset_consumer(Path(__file__).resolve().parent) 

74def main() -> None: 

75 """ 

76 Main application entry point. 

77 

78 Creates and configures all CDK stacks with proper dependencies: 

79 1. Global stack (shared state plus optional Global Accelerator) - must be created first 

80 2. API Gateway stack - uses Global Accelerator DNS only when available 

81 3. Regional stacks - depend on both global stacks 

82 4. Regional API bridges - depend on their matching regional stack 

83 (direct caller access is optional in `aws` and required elsewhere) 

84 5. Monitoring stack - depends on all regional stacks 

85 6. Optional analytics stack - feeds Studio routes into the API Gateway stack 

86 """ 

87 app = cdk.App() 

88 

89 # Enable cdk-nag compliance rule packs. These validate the synthesized 

90 # CloudFormation templates against security best practices. Any violations 

91 # that aren't explicitly acknowledged (see nag_suppressions.py) are written 

92 # to the cloud assembly's policy-validation report. 

93 # Note: These are rule packs, not certifications — passing cdk-nag does not 

94 # make the deployment automatically compliant with these frameworks. 

95 

96 # The X-Ray tracing aspect must run before the nag packs *see* the 

97 # templates. In cdk-nag v3 the packs are IPolicyValidationPlugins that 

98 # validate the synthesized templates AFTER every Aspect has run, so 

99 # registering the aspect here guarantees tracing=Active is already set by 

100 # the time the Serverless pack checks for it. 

101 cdk.Aspects.of(app).add(LambdaTracingAspect()) 

102 

103 # Register the five rule packs (AWS Solutions, HIPAA, NIST 800-53 R5, 

104 # PCI DSS 3.2.1, Serverless) as CDK policy-validation plugins. Each pack 

105 # reads the acknowledgment metadata written by ``acknowledge_nag_findings`` 

106 # natively, so the packs run directly. 

107 cdk.Validations.of(app).add_plugins(*nag_validation_plugins(app, verbose=True)) 

108 

109 # Load configuration from cdk.json 

110 config = ConfigLoader(app) 

111 

112 # Get configuration values 

113 project_name = config.get_project_name() 

114 deployment_regions = config.get_deployment_regions() 

115 tags = config.get_tags() 

116 

117 # Extract region configurations 

118 global_region = deployment_regions["global"] 

119 api_gateway_region = deployment_regions["api_gateway"] 

120 monitoring_region = deployment_regions["monitoring"] 

121 regional_regions = deployment_regions["regional"] 

122 api_gateway_config = config.get_api_gateway_config() 

123 manifest_processor_config = config.get_manifest_processor_config() 

124 

125 # Apply common tags to all stacks 

126 for key, value in tags.items(): 

127 cdk.Tags.of(app).add(key, value) 

128 

129 # Resolve the target AWS account for every stack. Deploying (or even 

130 # synthesizing against real infrastructure) requires valid credentials, so 

131 # the CDK CLI populates CDK_DEFAULT_ACCOUNT from the active identity. Pairing 

132 # it with each stack's region makes the stacks *environment-specific*, which 

133 # is what lets CDK's availability-zones context provider look up the real AZ 

134 # list for the account+region. The regional VPC relies on that lookup to 

135 # place a subnet in every AZ (regional_stack.py uses max_azs=99). When the 

136 # variable is unset — e.g. an environment-agnostic ``cdk synth`` in CI — this 

137 # is None and stacks stay agnostic exactly as before. 

138 account = os.environ.get("CDK_DEFAULT_ACCOUNT") 

139 

140 # Create global resources. Global Accelerator itself is included only in 

141 # the commercial ``aws`` partition; the shared data plane remains 

142 # available everywhere through regional IAM-authenticated API bridges. 

143 global_stack = GCOGlobalStack( 

144 app, 

145 f"{project_name}-global", 

146 config=config, 

147 env=cdk.Environment(account=account, region=global_region), 

148 description=f"{SOLUTION_DESCRIPTION_PREFIX} - Shared global resources for GCO (Global Capacity Orchestrator on AWS)", 

149 ) 

150 

151 # Create global API Gateway stack (authenticated entry point) 

152 api_gateway_stack = GCOApiGatewayGlobalStack( 

153 app, 

154 f"{project_name}-api-gateway", 

155 global_accelerator_dns=global_stack.get_accelerator_dns_name(), 

156 project_name=project_name, 

157 api_gateway_config=api_gateway_config, 

158 registry_region=global_region, 

159 certificate_regions=regional_regions, 

160 backend_tls_config=config.get_backend_tls_config(), 

161 max_request_body_bytes=manifest_processor_config.get("max_request_body_bytes", 1_048_576), 

162 env=cdk.Environment(account=account, region=api_gateway_region), 

163 description="Global API Gateway with IAM authentication", 

164 ) 

165 api_gateway_stack.add_stack_dependency(global_stack) 

166 

167 # Create regional stacks for each configured region 

168 regional_stacks = [] 

169 for region in regional_regions: 

170 regional_stack = GCORegionalStack( 

171 app, 

172 f"{project_name}-{region}", 

173 config=config, 

174 region=region, 

175 auth_secret_arn=api_gateway_stack.secret.secret_arn, 

176 env=cdk.Environment(account=account, region=region), 

177 description=f"Regional resources for {region} - EKS cluster, ALB, and services", 

178 ) 

179 

180 # Add dependencies 

181 regional_stack.add_stack_dependency(global_stack) 

182 regional_stack.add_stack_dependency(api_gateway_stack) 

183 regional_stacks.append(regional_stack) 

184 

185 # Every region gets an IAM-authenticated API bridge so the centralized 

186 # aggregator can reach the private ALB through a VPC-attached Lambda. 

187 # In commercial ``aws``, ``regional_api_enabled`` controls whether 

188 # other account principals may invoke the bridge directly. Other 

189 # partitions enable that IAM-authenticated workload ingress 

190 # automatically. Neither mode disables the aggregator's required path. 

191 regional_api_stack = GCORegionalApiGatewayStack( 

192 app, 

193 f"{project_name}-regional-api-{region}", 

194 config=config, 

195 region=region, 

196 vpc=regional_stack.vpc, 

197 auth_secret_arn=api_gateway_stack.secret.secret_arn, 

198 aggregator_role_arn=api_gateway_stack.aggregator_role.role_arn, 

199 env=cdk.Environment(account=account, region=region), 

200 description=f"Regional aggregation and workload bridge for {region}", 

201 ) 

202 regional_api_stack.add_stack_dependency(regional_stack) 

203 

204 # Create monitoring stack 

205 monitoring_stack = GCOMonitoringStack( 

206 app, 

207 f"{project_name}-monitoring", 

208 config=config, 

209 global_stack=global_stack, 

210 regional_stacks=regional_stacks, 

211 api_gateway_stack=api_gateway_stack, 

212 env=cdk.Environment(account=account, region=monitoring_region), 

213 description="Cross-region monitoring and observability for GCO (Global Capacity Orchestrator on AWS)", 

214 ) 

215 

216 # Add dependencies on all regional stacks 

217 for regional_stack in regional_stacks: 

218 monitoring_stack.add_stack_dependency(regional_stack) 

219 

220 # Optionally instantiate the analytics stack when explicitly enabled via 

221 # cdk.json. The stack lives in the API gateway region so the 

222 # presigned-URL Lambda can be wired into the existing /studio/* API 

223 # Gateway routes without a cross-region hop. 

224 # When the toggle is off, the stack is skipped entirely so cdk synth 

225 # emits no SageMaker, EMR Serverless, or Cognito resources. 

226 if config.get_analytics_enabled(): 

227 # Note: we intentionally do NOT pass ``api_gateway_secret_arn`` 

228 # here. That kwarg is reserved for future auth wiring and is not 

229 # consumed by any CloudFormation resource. Passing the secret 

230 # ARN (a cross-stack token) would force an implicit 

231 # ``analytics_stack → api_gateway_stack`` dependency, which 

232 # would deadlock against the reverse dependency we add below 

233 # (api_gateway_stack needs the presigned-URL Lambda ARN). 

234 analytics_stack = GCOAnalyticsStack( 

235 app, 

236 f"{project_name}-analytics", 

237 config=config, 

238 env=cdk.Environment(account=account, region=api_gateway_region), 

239 description="Optional ML and analytics environment (SageMaker Studio, EMR Serverless, Cognito)", 

240 ) 

241 analytics_stack.add_stack_dependency(global_stack) 

242 

243 # Wire the analytics stack's presigned-URL Lambda into the API 

244 # Gateway stack via a mutator. The API gateway stack was already 

245 # created above (before the analytics stack) because every 

246 # regional stack declares a dependency on it; re-ordering the 

247 # two globals would ripple through the entire stack graph. The 

248 # mutator lets us defer the /studio/* wiring until both stacks 

249 # exist without changing the existing dependency chain. 

250 # 

251 # ``api_gateway_stack.add_stack_dependency(analytics_stack)`` ensures 

252 # the analytics stack (and its Lambda) finish deploying before 

253 # CloudFormation updates the API gateway stack — the Lambda 

254 # ARN is now a cross-stack reference on the API gateway side. 

255 analytics_api_config = AnalyticsApiConfig( 

256 user_pool_arn=analytics_stack.cognito_pool.user_pool_arn, 

257 user_pool_client_id=analytics_stack.cognito_client.user_pool_client_id, 

258 presigned_url_lambda=analytics_stack.presigned_url_lambda, 

259 studio_domain_name=analytics_stack.studio_domain.domain_name or "", 

260 callback_url=( 

261 f"https://{api_gateway_stack.api.rest_api_id}." 

262 f"execute-api.{api_gateway_region}." 

263 f"{api_gateway_stack.url_suffix}/prod/studio/callback" 

264 ), 

265 ) 

266 api_gateway_stack.set_analytics_config(analytics_api_config) 

267 api_gateway_stack.add_stack_dependency(analytics_stack) 

268 

269 app.synth() 

270 

271 

272if __name__ == "__main__": 

273 main()