pangea-aws 0.1.0 → 0.2.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/flake.lock +3 -3
  3. data/flake.nix +7 -41
  4. data/lib/pangea/architectures/aws/web_application_architecture/README.md +375 -0
  5. data/lib/pangea/architectures/aws/web_application_architecture/architecture/component_creation.rb +146 -0
  6. data/lib/pangea/architectures/aws/web_application_architecture/architecture/cost_estimation.rb +71 -0
  7. data/lib/pangea/architectures/aws/web_application_architecture/architecture/fallback_resources.rb +63 -0
  8. data/lib/pangea/architectures/aws/web_application_architecture/architecture/helpers.rb +50 -0
  9. data/lib/pangea/architectures/aws/web_application_architecture/architecture/outputs.rb +73 -0
  10. data/lib/pangea/architectures/aws/web_application_architecture/architecture/resource_creation.rb +54 -0
  11. data/lib/pangea/architectures/aws/web_application_architecture/architecture.rb +75 -0
  12. data/lib/pangea/architectures/aws/web_application_architecture/types/cost_estimation.rb +88 -0
  13. data/lib/pangea/architectures/aws/web_application_architecture/types/defaults.rb +90 -0
  14. data/lib/pangea/architectures/aws/web_application_architecture/types/input_schema.rb +91 -0
  15. data/lib/pangea/architectures/aws/web_application_architecture/types/output_schema.rb +49 -0
  16. data/lib/pangea/architectures/aws/web_application_architecture/types/validation.rb +81 -0
  17. data/lib/pangea/architectures/aws/web_application_architecture/types.rb +70 -0
  18. data/lib/pangea/components/aws/public_private_subnets/README.md +293 -0
  19. data/lib/pangea/components/aws/public_private_subnets/component/outputs.rb +49 -0
  20. data/lib/pangea/components/aws/public_private_subnets/component/routing/nat_gateways.rb +89 -0
  21. data/lib/pangea/components/aws/public_private_subnets/component/routing.rb +145 -0
  22. data/lib/pangea/components/aws/public_private_subnets/component/subnets.rb +70 -0
  23. data/lib/pangea/components/aws/public_private_subnets/component.rb +92 -0
  24. data/lib/pangea/components/aws/public_private_subnets/types.rb +152 -0
  25. data/lib/pangea/components/aws/secure_vpc/README.md +187 -0
  26. data/lib/pangea/components/aws/secure_vpc/component.rb +88 -0
  27. data/lib/pangea/components/aws/secure_vpc/types.rb +141 -0
  28. data/lib/pangea/components/aws/vpc_with_subnets/component.rb +175 -0
  29. data/lib/pangea/components/aws/vpc_with_subnets/types.rb +61 -0
  30. data/lib/pangea/components/capabilities.rb +93 -0
  31. data/lib/pangea/components/types.rb +198 -0
  32. data/lib/pangea/resources/aws/composition/auto_scaling_web_tier.rb +179 -0
  33. data/lib/pangea/resources/aws/composition/composite_auto_scaling_reference.rb +63 -0
  34. data/lib/pangea/resources/aws/composition/composite_vpc_reference.rb +73 -0
  35. data/lib/pangea/resources/aws/composition/composite_web_server_reference.rb +46 -0
  36. data/lib/pangea/resources/aws/composition/helpers.rb +75 -0
  37. data/lib/pangea/resources/aws/composition/vpc_with_subnets.rb +143 -0
  38. data/lib/pangea/resources/aws/composition/web_server.rb +72 -0
  39. data/lib/pangea/resources/aws/composition.rb +38 -0
  40. data/lib/pangea/resources/aws/examples/event_driven/dynamodb_tables.rb +103 -0
  41. data/lib/pangea/resources/aws/examples/event_driven/eventbridge_buses.rb +68 -0
  42. data/lib/pangea/resources/aws/examples/event_driven/eventbridge_rules.rb +94 -0
  43. data/lib/pangea/resources/aws/examples/event_driven/eventbridge_targets.rb +123 -0
  44. data/lib/pangea/resources/types/aws/core.rb +0 -28
  45. data/lib/pangea/resources/validators/aws_validators.rb +66 -0
  46. data/lib/pangea/types/aws_types.rb +65 -0
  47. data/lib/pangea/types/computed_types.rb +23 -0
  48. data/lib/pangea/utilities/aws/pricing.rb +102 -0
  49. data/lib/pangea-aws/version.rb +1 -1
  50. data/lib/pangea-aws.rb +22 -0
  51. data/pangea-aws.gemspec +1 -1
  52. metadata +54 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4fe3965d89b22bf5fd613fc817fa08d619e64a7e318085e5eed5fe45c06bb23
4
- data.tar.gz: fb390445ba7da8a9d9d7d0f76f80d57c0a9ee8093c25ab3c3a199040404970aa
3
+ metadata.gz: 171b953acda35d607e7f18e2dd248e2535ffb11966cd85389288130bfaab807d
4
+ data.tar.gz: d1140dcd5eb37444b0ce9a34577e825bd3eba4421af2e32c90f8966dd80c2a6f
5
5
  SHA512:
6
- metadata.gz: 9ae4a9df1c5e2124fd3414749faaa5fa904c6c31e6fd2f1fe5529b729d4f1635fee2d2b414cde7ca04f9515e40c5d6955c9ad70746fe32973a7498b0fe98dd7d
7
- data.tar.gz: f63de27865e4f4708506773eb84ae457ead67ee28d266838d22fe879cc3a9481ce979f724203aeead5eeaa5c94a3d208799721a81bf1bec9fb60d4bb277c9e31
6
+ metadata.gz: 992c3aadad1f441386c8fba09cdbe6fadcd11e4bfbaf741622ee670a692c525af6d9202a4095fe5232f4e03a5cc751d2070f844f618f38db89692ad45b95118a
7
+ data.tar.gz: f6b08dd54ca87b02c9a7f2cb7aa35f0d1b0e3451f7c00fdad34845117e352bcb39527f3a25209d1dc0c962b77a3fe9697f06141732381ac7c2a6855e5f37be7b
data/flake.lock CHANGED
@@ -771,11 +771,11 @@
771
771
  ]
772
772
  },
773
773
  "locked": {
774
- "lastModified": 1771807706,
775
- "narHash": "sha256-JMDKxc0hfy7itVnURZamiz+2K94VCPOfY3a4OgqHYNc=",
774
+ "lastModified": 1771861648,
775
+ "narHash": "sha256-XjYnA7XQUFTg/XrgQL35oojiX/oddmuqHSsLbQg+X44=",
776
776
  "owner": "pleme-io",
777
777
  "repo": "substrate",
778
- "rev": "eb59960eb0dade9bd102b5d4ed774b452c313933",
778
+ "rev": "0f97a626e8141f4ffa2a4e143f96df2689a82b6b",
779
779
  "type": "github"
780
780
  },
781
781
  "original": {
data/flake.nix CHANGED
@@ -16,45 +16,11 @@
16
16
  };
17
17
  };
18
18
 
19
- outputs = {
20
- self,
21
- nixpkgs,
22
- ruby-nix,
23
- flake-utils,
24
- substrate,
25
- forge,
26
- ...
27
- }:
28
- flake-utils.lib.eachSystem ["x86_64-linux" "aarch64-linux" "aarch64-darwin"] (system: let
29
- pkgs = import nixpkgs {
30
- inherit system;
31
- overlays = [ruby-nix.overlays.ruby];
32
- };
33
- rnix = ruby-nix.lib pkgs;
34
- rnix-env = rnix {
35
- name = "pangea-aws";
36
- gemset = ./gemset.nix;
37
- };
38
- env = rnix-env.env;
39
- ruby = rnix-env.ruby;
40
-
41
- rubyBuild = import "${substrate}/lib/ruby-build.nix" {
42
- inherit pkgs;
43
- forgeCmd = "${forge.packages.${system}.default}/bin/forge";
44
- defaultGhcrToken = "";
45
- };
46
- in {
47
- devShells.default = pkgs.mkShell {
48
- buildInputs = [env ruby];
49
- shellHook = ''
50
- export RUBYLIB=$PWD/lib:$RUBYLIB
51
- export DRY_TYPES_WARNINGS=false
52
- '';
53
- };
54
-
55
- apps = rubyBuild.mkRubyGemApps {
56
- srcDir = self;
57
- name = "pangea-aws";
58
- };
59
- });
19
+ outputs = { self, nixpkgs, ruby-nix, flake-utils, substrate, forge, ... }:
20
+ (import "${substrate}/lib/ruby-gem-flake.nix" {
21
+ inherit nixpkgs ruby-nix flake-utils substrate forge;
22
+ }) {
23
+ inherit self;
24
+ name = "pangea-aws";
25
+ };
60
26
  }
@@ -0,0 +1,375 @@
1
+ # Web Application Architecture
2
+
3
+ Production-ready 3-tier web application architecture with load balancing, auto-scaling, database, monitoring, and optional caching/CDN capabilities.
4
+
5
+ ## Overview
6
+
7
+ The Web Application Architecture creates a complete, production-ready infrastructure for web applications. It automatically configures networking, security, compute resources, database, monitoring, and optional performance enhancements based on environment and requirements.
8
+
9
+ ## Architecture Components
10
+
11
+ ### Core Infrastructure
12
+ - **VPC with Public/Private Subnets**: Multi-AZ network foundation with proper isolation
13
+ - **Application Load Balancer**: SSL termination, health checks, and traffic distribution
14
+ - **Auto Scaling Group**: Elastic compute capacity with configurable scaling policies
15
+ - **RDS Database**: Managed database with backups, encryption, and multi-AZ support
16
+ - **Security Groups**: Least-privilege security rules for each tier
17
+
18
+ ### Optional Components
19
+ - **ElastiCache Redis**: In-memory caching for improved performance
20
+ - **CloudFront CDN**: Global content delivery network
21
+ - **Route53 DNS**: Custom domain management
22
+ - **ACM SSL Certificate**: Automatic SSL certificate provisioning
23
+ - **CloudWatch Monitoring**: Comprehensive monitoring, logging, and alerting
24
+
25
+ ## Usage
26
+
27
+ ### Basic Web Application
28
+
29
+ ```ruby
30
+ web_app = web_application_architecture(:myapp, {
31
+ domain_name: "myapp.com",
32
+ environment: "production"
33
+ })
34
+
35
+ # Architecture automatically configures:
36
+ # - Multi-AZ VPC with public/private subnets
37
+ # - Application Load Balancer with SSL termination
38
+ # - Auto Scaling Group (min: 2, max: 10)
39
+ # - MySQL RDS database with Multi-AZ
40
+ # - CloudWatch monitoring and alarms
41
+ # - Security groups with proper isolation
42
+ ```
43
+
44
+ ### Development Environment
45
+
46
+ ```ruby
47
+ dev_app = web_application_architecture(:myapp_dev, {
48
+ domain_name: "dev.myapp.com",
49
+ environment: "development",
50
+ auto_scaling: { min: 1, max: 2 },
51
+ instance_type: "t3.micro",
52
+ database_instance_class: "db.t3.micro",
53
+ high_availability: false
54
+ })
55
+ ```
56
+
57
+ ### Production with Performance Features
58
+
59
+ ```ruby
60
+ prod_app = web_application_architecture(:myapp_prod, {
61
+ domain_name: "myapp.com",
62
+ environment: "production",
63
+
64
+ # High performance configuration
65
+ instance_type: "c5.large",
66
+ auto_scaling: { min: 3, max: 20, desired: 5 },
67
+
68
+ # Database optimization
69
+ database_engine: "aurora-mysql",
70
+ database_instance_class: "db.r5.xlarge",
71
+
72
+ # Performance features
73
+ enable_caching: true,
74
+ enable_cdn: true,
75
+
76
+ # Security enhancements
77
+ security: {
78
+ enable_waf: true,
79
+ enable_ddos_protection: true,
80
+ compliance_standards: ["PCI-DSS"]
81
+ }
82
+ })
83
+ ```
84
+
85
+ ## Configuration Parameters
86
+
87
+ ### Required Parameters
88
+
89
+ - **domain_name**: Primary domain for the application
90
+ - **environment**: Deployment environment (`development`, `staging`, `production`)
91
+
92
+ ### Network Configuration
93
+
94
+ ```ruby
95
+ # Network settings
96
+ region: "us-east-1",
97
+ vpc_cidr: "10.0.0.0/16",
98
+ availability_zones: ["us-east-1a", "us-east-1b", "us-east-1c"]
99
+ ```
100
+
101
+ ### Compute Configuration
102
+
103
+ ```ruby
104
+ # Instance and scaling settings
105
+ instance_type: "t3.medium",
106
+ auto_scaling: {
107
+ min: 2,
108
+ max: 10,
109
+ desired: 3
110
+ }
111
+ ```
112
+
113
+ ### Database Configuration
114
+
115
+ ```ruby
116
+ # Database settings
117
+ database_enabled: true,
118
+ database_engine: "mysql", # mysql, postgresql, aurora
119
+ database_instance_class: "db.t3.small",
120
+ database_allocated_storage: 100,
121
+ high_availability: true # Enables Multi-AZ
122
+ ```
123
+
124
+ ### Performance Features
125
+
126
+ ```ruby
127
+ # Performance optimization
128
+ enable_caching: true, # ElastiCache Redis cluster
129
+ enable_cdn: true, # CloudFront distribution
130
+ ssl_certificate_arn: "...", # Custom SSL cert (optional)
131
+ ```
132
+
133
+ ### Security Configuration
134
+
135
+ ```ruby
136
+ security: {
137
+ encryption_at_rest: true,
138
+ encryption_in_transit: true,
139
+ enable_waf: true,
140
+ enable_ddos_protection: true,
141
+ compliance_standards: ["SOC2", "PCI-DSS"]
142
+ }
143
+ ```
144
+
145
+ ### Monitoring Configuration
146
+
147
+ ```ruby
148
+ monitoring: {
149
+ detailed_monitoring: true,
150
+ enable_logging: true,
151
+ log_retention_days: 30,
152
+ enable_alerting: true,
153
+ enable_tracing: false
154
+ }
155
+ ```
156
+
157
+ ### Backup Configuration
158
+
159
+ ```ruby
160
+ backup: {
161
+ backup_schedule: "daily",
162
+ retention_days: 30,
163
+ cross_region_backup: true,
164
+ point_in_time_recovery: true
165
+ }
166
+ ```
167
+
168
+ ## Environment Defaults
169
+
170
+ The architecture automatically applies environment-appropriate defaults:
171
+
172
+ ### Development
173
+ - **Instance Type**: t3.micro
174
+ - **Auto Scaling**: min=1, max=2
175
+ - **Database**: db.t3.micro
176
+ - **High Availability**: false
177
+ - **Caching**: disabled
178
+ - **CDN**: disabled
179
+ - **Backup Retention**: 1 day
180
+
181
+ ### Staging
182
+ - **Instance Type**: t3.small
183
+ - **Auto Scaling**: min=1, max=4
184
+ - **Database**: db.t3.small
185
+ - **High Availability**: true
186
+ - **Caching**: enabled
187
+ - **CDN**: disabled
188
+ - **Backup Retention**: 3 days
189
+
190
+ ### Production
191
+ - **Instance Type**: t3.medium
192
+ - **Auto Scaling**: min=2, max=10
193
+ - **Database**: db.r5.large
194
+ - **High Availability**: true
195
+ - **Caching**: enabled
196
+ - **CDN**: enabled
197
+ - **Backup Retention**: 30 days
198
+ - **WAF & DDoS Protection**: enabled
199
+
200
+ ## Architecture Outputs
201
+
202
+ ### Primary Outputs
203
+ ```ruby
204
+ web_app.application_url # https://myapp.com
205
+ web_app.load_balancer_dns # myapp-alb-123.us-east-1.elb.amazonaws.com
206
+ web_app.database_endpoint # myapp-db.cluster-xyz.rds.amazonaws.com
207
+ ```
208
+
209
+ ### Optional Outputs
210
+ ```ruby
211
+ web_app.cdn_domain # d1234567890.cloudfront.net
212
+ web_app.monitoring_dashboard_url # CloudWatch dashboard URL
213
+ web_app.estimated_monthly_cost # $247.50
214
+ ```
215
+
216
+ ### Architecture Capabilities
217
+ ```ruby
218
+ web_app.capabilities = {
219
+ high_availability: true,
220
+ auto_scaling: true,
221
+ caching: true,
222
+ cdn: true,
223
+ ssl_termination: true,
224
+ monitoring: true,
225
+ backup: true
226
+ }
227
+ ```
228
+
229
+ ## Architecture Validation
230
+
231
+ ### Security Compliance Score
232
+ ```ruby
233
+ web_app.security_compliance_score # 95.2
234
+ ```
235
+
236
+ ### High Availability Score
237
+ ```ruby
238
+ web_app.high_availability_score # 88.0
239
+ ```
240
+
241
+ ### Performance Score
242
+ ```ruby
243
+ web_app.performance_score # 92.5
244
+ ```
245
+
246
+ ## Cost Estimation
247
+
248
+ ### Monthly Cost Breakdown
249
+ ```ruby
250
+ web_app.cost_breakdown = {
251
+ components: {
252
+ load_balancer: 22.0,
253
+ web_servers: 204.0, # 3 x t3.medium
254
+ database: 180.0, # db.r5.large Multi-AZ
255
+ cache: 15.0, # ElastiCache
256
+ cdn: 10.0 # CloudFront
257
+ },
258
+ total: 431.0
259
+ }
260
+ ```
261
+
262
+ ## Customization and Overrides
263
+
264
+ ### Override Database with Aurora Serverless
265
+ ```ruby
266
+ web_app.override(:database) do |arch_ref|
267
+ aurora_serverless_cluster(:"#{arch_ref.name}_db", {
268
+ engine: "aurora-mysql",
269
+ vpc_ref: arch_ref.network.vpc,
270
+ scaling: { min_capacity: 2, max_capacity: 16 }
271
+ })
272
+ end
273
+ ```
274
+
275
+ ### Extend with Additional Components
276
+ ```ruby
277
+ web_app.extend_with({
278
+ api_gateway: aws_api_gateway_rest_api(:"#{web_app.name}_api", {
279
+ description: "API Gateway for #{web_app.name}"
280
+ }),
281
+
282
+ lambda_functions: aws_lambda_function(:"#{web_app.name}_processor", {
283
+ runtime: "python3.9",
284
+ handler: "lambda_function.lambda_handler"
285
+ })
286
+ })
287
+ ```
288
+
289
+ ### Compose with Other Architectures
290
+ ```ruby
291
+ web_app.compose_with do |arch_ref|
292
+ # Add data analytics pipeline
293
+ arch_ref.analytics = data_lake_architecture(:"#{arch_ref.name}_analytics", {
294
+ vpc_ref: arch_ref.network.vpc,
295
+ source_database: arch_ref.database
296
+ })
297
+ end
298
+ ```
299
+
300
+ ## Template Integration
301
+
302
+ ### Basic Template Usage
303
+ ```ruby
304
+ template :web_application do
305
+ include Pangea::Architectures
306
+
307
+ web_app = web_application_architecture(:myapp, {
308
+ domain_name: "myapp.com",
309
+ environment: "production"
310
+ })
311
+
312
+ output :application_url do
313
+ value web_app.application_url
314
+ end
315
+
316
+ output :monthly_cost do
317
+ value web_app.estimated_monthly_cost
318
+ end
319
+ end
320
+ ```
321
+
322
+ ### Multi-Environment Deployment
323
+ ```ruby
324
+ template :multi_environment_web_app do
325
+ include Pangea::Architectures
326
+
327
+ environments = ["development", "staging", "production"]
328
+
329
+ environments.each do |env|
330
+ web_app = web_application_architecture(:"myapp_#{env}", {
331
+ domain_name: "#{env == 'production' ? '' : env + '.'}myapp.com",
332
+ environment: env
333
+ })
334
+
335
+ output :"#{env}_url" do
336
+ value web_app.application_url
337
+ end
338
+ end
339
+ end
340
+ ```
341
+
342
+ ## Best Practices
343
+
344
+ 1. **Environment Separation**: Use separate architectures per environment
345
+ 2. **Domain Strategy**: Use subdomains for non-production environments
346
+ 3. **Scaling Configuration**: Set appropriate min/max based on traffic patterns
347
+ 4. **Database Sizing**: Choose instance classes based on performance requirements
348
+ 5. **Security**: Enable WAF and DDoS protection for production
349
+ 6. **Monitoring**: Always enable detailed monitoring and alerting
350
+ 7. **Backup Strategy**: Configure appropriate retention for your RPO requirements
351
+ 8. **Cost Optimization**: Use spot instances for development environments
352
+ 9. **SSL Certificates**: Let the architecture manage ACM certificates automatically
353
+ 10. **Tags**: Use consistent tagging for cost allocation and management
354
+
355
+ ## Troubleshooting
356
+
357
+ ### High Costs
358
+ - Review instance types and auto scaling settings
359
+ - Consider using spot instances for non-production
360
+ - Optimize database instance class selection
361
+
362
+ ### Performance Issues
363
+ - Enable caching with ElastiCache
364
+ - Add CloudFront CDN for static content
365
+ - Consider upgrading instance types
366
+
367
+ ### Security Compliance
368
+ - Enable WAF and DDoS protection
369
+ - Ensure encryption at rest and in transit
370
+ - Review security group rules
371
+
372
+ ### High Availability Issues
373
+ - Verify Multi-AZ database configuration
374
+ - Ensure auto scaling spans multiple availability zones
375
+ - Check load balancer health check configuration
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2025 The Pangea Authors
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Pangea
18
+ module Architectures
19
+ module WebApplicationArchitecture
20
+ class Architecture
21
+ # Component creation methods
22
+ module ComponentCreation
23
+ def create_components(name, attributes)
24
+ extend Pangea::Components if defined?(Pangea::Components)
25
+
26
+ components = {}
27
+ components[:network] = create_network_component(name, attributes)
28
+ components[:security_groups] = create_security_groups(name, attributes, components[:network])
29
+ components[:load_balancer] = create_load_balancer(name, attributes, components[:network], components[:security_groups])
30
+ components[:web_servers] = create_web_servers(name, attributes, components[:network], components[:security_groups], components[:load_balancer])
31
+ components[:database] = create_database(name, attributes, components[:network], components[:security_groups]) if attributes[:database_enabled] != false
32
+ components[:monitoring] = create_monitoring(name, attributes, components)
33
+ components[:cache] = create_cache_component(name, attributes, components[:network], components[:security_groups]) if attributes[:enable_caching]
34
+ components[:cdn] = create_cdn_component(name, attributes, components[:load_balancer]) if attributes[:enable_cdn]
35
+ components
36
+ end
37
+
38
+ def create_network_component(name, attributes)
39
+ if defined?(Pangea::Components) && respond_to?(:secure_vpc)
40
+ secure_vpc(:"#{name}_network", {
41
+ cidr_block: attributes[:vpc_cidr] || '10.0.0.0/16',
42
+ availability_zones: attributes[:availability_zones] || %w[us-east-1a us-east-1b us-east-1c],
43
+ enable_flow_logs: attributes[:environment] == 'production',
44
+ tags: architecture_tags(attributes)
45
+ })
46
+ else
47
+ create_vpc_directly(name, attributes)
48
+ end
49
+ end
50
+
51
+ def create_security_groups(name, attributes, network)
52
+ if defined?(Pangea::Components) && respond_to?(:web_security_group)
53
+ web_security_group(:"#{name}_web_sg", {
54
+ vpc_ref: network.respond_to?(:vpc) ? network.vpc : network,
55
+ allowed_cidr_blocks: attributes[:allowed_cidr_blocks] || ['0.0.0.0/0'],
56
+ tags: architecture_tags(attributes)
57
+ })
58
+ else
59
+ create_security_groups_directly(name, attributes, network)
60
+ end
61
+ end
62
+
63
+ def create_load_balancer(name, attributes, network, security_groups)
64
+ if defined?(Pangea::Components) && respond_to?(:application_load_balancer)
65
+ subnets = network.respond_to?(:public_subnets) ? network.public_subnets : []
66
+ sg_refs = security_groups.respond_to?(:security_groups) ? security_groups.security_groups : [security_groups]
67
+
68
+ application_load_balancer(:"#{name}_alb", {
69
+ subnet_refs: subnets, security_group_refs: sg_refs,
70
+ enable_deletion_protection: attributes[:environment] == 'production',
71
+ certificate_arn: attributes[:ssl_certificate_arn],
72
+ tags: architecture_tags(attributes)
73
+ })
74
+ else
75
+ create_load_balancer_directly(name, attributes, network, security_groups)
76
+ end
77
+ end
78
+
79
+ def create_web_servers(name, attributes, network, security_groups, load_balancer)
80
+ if defined?(Pangea::Components) && respond_to?(:auto_scaling_web_servers)
81
+ subnets = network.respond_to?(:private_subnets) ? network.private_subnets : []
82
+ auto_scaling_web_servers(:"#{name}_web", {
83
+ subnet_refs: subnets,
84
+ target_group_ref: load_balancer.respond_to?(:target_group) ? load_balancer.target_group : nil,
85
+ min_size: attributes[:auto_scaling][:min], max_size: attributes[:auto_scaling][:max],
86
+ desired_capacity: attributes[:auto_scaling][:desired] || attributes[:auto_scaling][:min],
87
+ instance_type: attributes[:instance_type] || 't3.medium',
88
+ tags: architecture_tags(attributes)
89
+ })
90
+ else
91
+ create_web_servers_directly(name, attributes, network, security_groups, load_balancer)
92
+ end
93
+ end
94
+
95
+ def create_database(name, attributes, network, security_groups)
96
+ engine = attributes[:database_engine] || 'mysql'
97
+
98
+ if defined?(Pangea::Components)
99
+ component_method = engine == 'postgresql' ? :postgresql_database : :mysql_database
100
+ return create_database_directly(name, attributes, network, security_groups) unless respond_to?(component_method)
101
+
102
+ subnets = network.respond_to?(:private_subnets) ? network.private_subnets : []
103
+ vpc = network.respond_to?(:vpc) ? network.vpc : network
104
+
105
+ send(component_method, :"#{name}_db", {
106
+ subnet_refs: subnets, vpc_ref: vpc,
107
+ instance_class: attributes[:database_instance_class] || 'db.t3.micro',
108
+ allocated_storage: attributes[:database_allocated_storage] || 20,
109
+ storage_encrypted: attributes[:environment] == 'production',
110
+ backup_retention_days: attributes.dig(:backup, :retention_days) || (attributes[:environment] == 'production' ? 7 : 1),
111
+ multi_az: attributes[:high_availability] && attributes[:environment] == 'production',
112
+ tags: architecture_tags(attributes)
113
+ })
114
+ else
115
+ create_database_directly(name, attributes, network, security_groups)
116
+ end
117
+ end
118
+
119
+ def create_monitoring(name, attributes, components)
120
+ monitoring_resources = {}
121
+ monitoring_resources[:alarms] = create_cloudwatch_alarms(name, attributes, components) if attributes[:monitoring][:enable_alerting]
122
+ monitoring_resources[:dashboard] = create_cloudwatch_dashboard(name, attributes, components) if attributes[:monitoring][:detailed_monitoring]
123
+ monitoring_resources
124
+ end
125
+
126
+ def create_cache_component(name, attributes, network, security_groups)
127
+ if defined?(Pangea::Components) && respond_to?(:elasticache_redis)
128
+ subnets = network.respond_to?(:private_subnets) ? network.private_subnets : []
129
+ elasticache_redis(:"#{name}_cache", { subnet_refs: subnets, node_type: 'cache.t3.micro', num_cache_nodes: 1, port: 6379, tags: architecture_tags(attributes) })
130
+ else
131
+ create_cache_directly(name, attributes, network, security_groups)
132
+ end
133
+ end
134
+
135
+ def create_cdn_component(name, attributes, load_balancer)
136
+ if defined?(Pangea::Components) && respond_to?(:cloudfront_distribution)
137
+ cloudfront_distribution(:"#{name}_cdn", { origin_domain_name: load_balancer.respond_to?(:dns_name) ? load_balancer.dns_name : '', price_class: 'PriceClass_100', tags: architecture_tags(attributes) })
138
+ else
139
+ create_cdn_directly(name, attributes, load_balancer)
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2025 The Pangea Authors
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Pangea
18
+ module Architectures
19
+ module WebApplicationArchitecture
20
+ class Architecture
21
+ # Cost estimation methods
22
+ module CostEstimation
23
+ def calculate_monthly_cost(components, _resources)
24
+ cost = 0.0
25
+ cost += 22.0 if components[:load_balancer]
26
+ cost += calculate_instance_costs(components[:web_servers])
27
+ cost += calculate_database_costs(components[:database])
28
+ cost += 15.0 if components[:cache]
29
+ cost += 10.0 if components[:cdn]
30
+ cost.round(2)
31
+ end
32
+
33
+ private
34
+
35
+ def calculate_instance_costs(web_servers)
36
+ return 0.0 unless web_servers&.[](:min_size)
37
+
38
+ instance_cost = estimate_instance_cost(web_servers[:instance_type] || 't3.medium')
39
+ instance_cost * web_servers[:min_size]
40
+ end
41
+
42
+ def calculate_database_costs(database)
43
+ return 0.0 unless database
44
+
45
+ estimate_database_cost(database[:instance_class] || 'db.t3.micro')
46
+ end
47
+
48
+ def estimate_instance_cost(instance_type)
49
+ case instance_type
50
+ when /t3\.micro/ then 8.5
51
+ when /t3\.small/ then 17.0
52
+ when /t3\.medium/ then 34.0
53
+ when /t3\.large/ then 67.0
54
+ when /c5\.large/ then 72.0
55
+ else 50.0
56
+ end
57
+ end
58
+
59
+ def estimate_database_cost(instance_class)
60
+ case instance_class
61
+ when /db\.t3\.micro/ then 16.0
62
+ when /db\.t3\.small/ then 32.0
63
+ when /db\.r5\.large/ then 180.0
64
+ else 80.0
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end