cdk-factory 0.16.5__py3-none-any.whl → 0.16.6__py3-none-any.whl

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.

Potentially problematic release.


This version of cdk-factory might be problematic. Click here for more details.

@@ -23,7 +23,10 @@ class IStack(Stack, SsmParameterMixin, metaclass=StackABCMeta):
23
23
 
24
24
  @abstractmethod
25
25
  def __init__(self, scope: Construct, id: str, **kwargs) -> None:
26
- super().__init__(scope, id, **kwargs)
26
+ # Initialize Stack first
27
+ Stack.__init__(self, scope, id, **kwargs)
28
+ # Initialize SsmParameterMixin (no super() call to avoid MRO issues)
29
+ SsmParameterMixin.__init__(self, **kwargs)
27
30
 
28
31
  @abstractmethod
29
32
  def build(self, *, stack_config, deployment, workload) -> None:
@@ -0,0 +1,75 @@
1
+ """
2
+ Networked Stack Mixin - Combined SSM and VPC functionality for network-aware stacks
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for license information.
5
+ """
6
+
7
+ from typing import Any
8
+ from aws_cdk import aws_ec2 as ec2
9
+ from .ssm_parameter_mixin import SsmParameterMixin
10
+ from .vpc_provider_mixin import VPCProviderMixin
11
+
12
+
13
+ class NetworkedStackMixin(SsmParameterMixin, VPCProviderMixin):
14
+ """
15
+ Combined mixin for stacks that need both SSM imports and VPC resolution.
16
+
17
+ This mixin provides a complete solution for network-aware stacks by combining:
18
+ - Enhanced SSM parameter import functionality (with caching and list support)
19
+ - VPC resolution with multiple fallback strategies
20
+ - Standardized initialization patterns
21
+
22
+ Usage:
23
+ class MyStack(Stack, NetworkedStackMixin):
24
+ def __init__(self, scope, id, **kwargs):
25
+ super().__init__(scope, id, **kwargs)
26
+ # SSM initialization is handled automatically by SsmParameterMixin.__init__
27
+
28
+ def _build(self, stack_config, deployment, workload):
29
+ self.process_ssm_imports(stack_config, deployment, "my-resource")
30
+ self.vpc = self.resolve_vpc(stack_config, deployment, workload)
31
+ """
32
+
33
+ def _initialize_networked_stack(self) -> None:
34
+ """
35
+ Initialize all networked stack functionality.
36
+ Note: SSM initialization is handled by SsmParameterMixin.__init__
37
+ """
38
+ self._initialize_vpc_cache()
39
+
40
+ def build_networked_stack(
41
+ self,
42
+ config: Any,
43
+ deployment: Any,
44
+ workload: Any,
45
+ resource_type: str = "resource"
46
+ ) -> None:
47
+ """
48
+ Standard build sequence for networked stacks.
49
+
50
+ Args:
51
+ config: The stack configuration
52
+ deployment: The deployment configuration
53
+ workload: The workload configuration
54
+ resource_type: Type name for logging purposes
55
+ """
56
+ # Process SSM imports first (using enhanced SsmParameterMixin)
57
+ self.process_ssm_imports(config, deployment, resource_type)
58
+
59
+ # Store references for later use
60
+ self.config = config
61
+ self.deployment = deployment
62
+ self.workload = workload
63
+
64
+ @property
65
+ def vpc(self) -> ec2.IVpc:
66
+ """
67
+ Standard VPC property that uses the combined mixin functionality.
68
+
69
+ Returns:
70
+ Resolved VPC reference
71
+ """
72
+ if not hasattr(self, 'config') or not hasattr(self, 'deployment') or not hasattr(self, 'workload'):
73
+ raise AttributeError("Networked stack not properly initialized. Call build_networked_stack() first.")
74
+
75
+ return self.get_vpc_property(self.config, self.deployment, self.workload)
@@ -4,7 +4,7 @@ Maintainers: Eric Wilson
4
4
  MIT License. See Project Root for the license information.
5
5
  """
6
6
 
7
- from typing import Dict, Any, Optional
7
+ from typing import Dict, Any, Optional, Union, List
8
8
  from aws_cdk import aws_ssm as ssm
9
9
  from constructs import Construct
10
10
  from aws_lambda_powertools import Logger
@@ -19,8 +19,129 @@ class SsmParameterMixin:
19
19
 
20
20
  This mixin should be used by stack classes to standardize how SSM parameters
21
21
  are exported and imported across the project.
22
+
23
+ Enhanced to support:
24
+ - List parameter imports (for security groups, etc.)
25
+ - Cached imported values for easy access
26
+ - Backward compatibility with existing interfaces
22
27
  """
23
28
 
29
+ def __init__(self, *args, **kwargs):
30
+ """Initialize the mixin with cached storage for imported values."""
31
+ # Don't call super() to avoid MRO issues in multiple inheritance
32
+ # Initialize cached storage for imported values
33
+ self._ssm_imported_values: Dict[str, Union[str, List[str]]] = {}
34
+
35
+ def initialize_ssm_imports(self) -> None:
36
+ """
37
+ Initialize SSM imports storage.
38
+ Call this in your stack's __init__ method if not using __init__ above.
39
+ """
40
+ if not hasattr(self, '_ssm_imported_values'):
41
+ self._ssm_imported_values: Dict[str, Union[str, List[str]]] = {}
42
+
43
+ def get_ssm_imported_value(self, key: str, default: Any = None) -> Any:
44
+ """
45
+ Get a cached SSM imported value by key.
46
+
47
+ Args:
48
+ key: The SSM import key
49
+ default: Default value if key not found
50
+
51
+ Returns:
52
+ The imported value or default
53
+ """
54
+ return self._ssm_imported_values.get(key, default)
55
+
56
+ def has_ssm_import(self, key: str) -> bool:
57
+ """
58
+ Check if an SSM import key exists in cached values.
59
+
60
+ Args:
61
+ key: The SSM import key to check
62
+
63
+ Returns:
64
+ True if key exists, False otherwise
65
+ """
66
+ return key in self._ssm_imported_values
67
+
68
+ def process_ssm_imports(
69
+ self,
70
+ config: Any,
71
+ deployment: Any,
72
+ resource_type: str = "resource"
73
+ ) -> None:
74
+ """
75
+ Process SSM imports from configuration and cache them for later use.
76
+
77
+ This method handles list imports (like security_group_ids) and caches
78
+ the results for easy access via get_ssm_imported_value().
79
+
80
+ Args:
81
+ config: The configuration object with ssm_imports property
82
+ deployment: The deployment configuration for path resolution
83
+ resource_type: Type of resource for logging purposes
84
+ """
85
+ if not hasattr(config, 'ssm_imports'):
86
+ logger.debug(f"No ssm_imports property found on config for {resource_type}")
87
+ return
88
+
89
+ ssm_imports = config.ssm_imports
90
+
91
+ if not ssm_imports:
92
+ logger.debug(f"No SSM imports configured for {resource_type}")
93
+ return
94
+
95
+ logger.info(f"Processing {len(ssm_imports)} SSM imports for {resource_type}")
96
+
97
+ for param_key, param_value in ssm_imports.items():
98
+ try:
99
+ if isinstance(param_value, list):
100
+ # Handle list imports (like security_group_ids)
101
+ imported_list = []
102
+ for item in param_value:
103
+ param_path = self._resolve_ssm_path(item, deployment)
104
+
105
+ construct_id = f"ssm-import-{param_key}-{hash(param_path) % 10000}"
106
+ param = ssm.StringParameter.from_string_parameter_name(
107
+ self, construct_id, param_path
108
+ )
109
+ imported_list.append(param.string_value)
110
+
111
+ self._ssm_imported_values[param_key] = imported_list
112
+ logger.info(f"Imported SSM parameter list: {param_key} with {len(imported_list)} items")
113
+ else:
114
+ # Handle string values
115
+ param_path = self._resolve_ssm_path(param_value, deployment)
116
+
117
+ construct_id = f"ssm-import-{param_key}-{hash(param_path) % 10000}"
118
+ param = ssm.StringParameter.from_string_parameter_name(
119
+ self, construct_id, param_path
120
+ )
121
+
122
+ self._ssm_imported_values[param_key] = param.string_value
123
+ logger.info(f"Imported SSM parameter: {param_key} from {param_path}")
124
+
125
+ except Exception as e:
126
+ logger.error(f"Failed to import SSM parameter {param_key}: {e}")
127
+ raise
128
+
129
+ def _resolve_ssm_path(self, path: str, deployment: Any) -> str:
130
+ """
131
+ Resolve SSM parameter path (handle relative vs absolute paths).
132
+
133
+ Args:
134
+ path: The parameter path from configuration
135
+ deployment: The deployment configuration for context
136
+
137
+ Returns:
138
+ Fully resolved SSM parameter path
139
+ """
140
+ if not path.startswith('/'):
141
+ # Convert relative path to absolute path
142
+ return f"/{deployment.environment}/{deployment.workload_name}/{path}"
143
+ return path
144
+
24
145
  @staticmethod
25
146
  def normalize_resource_name(name: str, for_export: bool = False) -> str:
26
147
  """
@@ -272,6 +393,8 @@ class SsmParameterMixin:
272
393
 
273
394
  This is a higher-level method that makes it clear we're importing values.
274
395
  It first tries to use the ssm_imports property, then falls back to ssm_parameters.
396
+
397
+ Enhanced to also cache results for easy access via get_ssm_imported_value().
275
398
 
276
399
  Args:
277
400
  scope: The CDK construct scope
@@ -320,9 +443,11 @@ class SsmParameterMixin:
320
443
 
321
444
  if value:
322
445
  # Remove _path suffix if present
323
- if key.endswith("_path"):
324
- key = key[:-5] # Remove _path suffix
325
- imported_values[key] = value
446
+ final_key = key[:-5] if key.endswith("_path") else key
447
+ imported_values[final_key] = value
448
+
449
+ # Also cache for easy access via get_ssm_imported_value()
450
+ self._ssm_imported_values[final_key] = value
326
451
  else:
327
452
  logger.info(f"No SSM import paths configured for {resource_name} resources")
328
453
 
@@ -0,0 +1,154 @@
1
+ """
2
+ VPC Provider Mixin - Reusable VPC resolution functionality
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for license information.
5
+ """
6
+
7
+ from typing import Optional, List, Any
8
+ from aws_lambda_powertools import Logger
9
+ from aws_cdk import aws_ec2 as ec2
10
+ from constructs import Construct
11
+
12
+ logger = Logger(__name__)
13
+
14
+
15
+ class VPCProviderMixin:
16
+ """
17
+ Mixin class that provides reusable VPC resolution functionality for stacks.
18
+
19
+ This mixin eliminates code duplication across stacks that need to resolve
20
+ VPC references, providing a standardized way to handle:
21
+ - SSM imported VPC parameters (works with enhanced SsmParameterMixin)
22
+ - Configuration-based VPC resolution
23
+ - Workload-level VPC fallback
24
+ - Error handling and validation
25
+
26
+ Note: This mixin does NOT handle SSM imports directly - it expects
27
+ the SSM values to be available via the enhanced SsmParameterMixin.
28
+ """
29
+
30
+ def _initialize_vpc_cache(self) -> None:
31
+ """Initialize the VPC cache attribute"""
32
+ if not hasattr(self, '_vpc'):
33
+ self._vpc: Optional[ec2.IVpc] = None
34
+
35
+ def resolve_vpc(
36
+ self,
37
+ config: Any,
38
+ deployment: Any,
39
+ workload: Any,
40
+ availability_zones: Optional[List[str]] = None
41
+ ) -> ec2.IVpc:
42
+ """
43
+ Resolve VPC from multiple sources with standardized priority order.
44
+
45
+ Priority order:
46
+ 1. SSM imported VPC ID (from enhanced SsmParameterMixin)
47
+ 2. Config-level VPC ID
48
+ 3. Workload-level VPC ID
49
+ 4. Raise error if none found
50
+
51
+ Args:
52
+ config: The stack configuration
53
+ deployment: The deployment configuration
54
+ workload: The workload configuration
55
+ availability_zones: Optional AZ list for VPC attributes
56
+
57
+ Returns:
58
+ Resolved VPC reference
59
+
60
+ Raises:
61
+ ValueError: If no VPC configuration is found
62
+ """
63
+ if self._vpc:
64
+ return self._vpc
65
+
66
+ # Default availability zones if not provided
67
+ if not availability_zones:
68
+ availability_zones = ["us-east-1a", "us-east-1b"]
69
+
70
+ # Check SSM imported values first (tokens from SSM parameters)
71
+ # This works with the enhanced SsmParameterMixin
72
+ if hasattr(self, '_ssm_imported_values') and "vpc_id" in self._ssm_imported_values:
73
+ vpc_id = self._ssm_imported_values["vpc_id"]
74
+ return self._create_vpc_from_ssm(vpc_id, availability_zones)
75
+
76
+ # Check config-level VPC ID
77
+ if hasattr(config, 'vpc_id') and config.vpc_id:
78
+ return ec2.Vpc.from_lookup(self, "VPC", vpc_id=config.vpc_id)
79
+
80
+ # Check workload-level VPC ID
81
+ if hasattr(workload, 'vpc_id') and workload.vpc_id:
82
+ return ec2.Vpc.from_lookup(self, "VPC", vpc_id=workload.vpc_id)
83
+
84
+ # No VPC found - raise descriptive error
85
+ raise self._create_vpc_not_found_error(config, workload)
86
+
87
+ def _create_vpc_from_ssm(
88
+ self,
89
+ vpc_id: str,
90
+ availability_zones: List[str]
91
+ ) -> ec2.IVpc:
92
+ """
93
+ Create VPC reference from SSM imported VPC ID.
94
+
95
+ Args:
96
+ vpc_id: The VPC ID from SSM
97
+ availability_zones: List of availability zones
98
+
99
+ Returns:
100
+ VPC reference created from attributes
101
+ """
102
+ # Build VPC attributes
103
+ vpc_attrs = {
104
+ "vpc_id": vpc_id,
105
+ "availability_zones": availability_zones,
106
+ }
107
+
108
+ # If we have subnet_ids from SSM, provide dummy subnets
109
+ # The actual subnets will be set via CloudFormation escape hatch
110
+ if hasattr(self, '_ssm_imported_values') and "subnet_ids" in self._ssm_imported_values:
111
+ # Provide dummy subnet IDs - these will be overridden by the escape hatch
112
+ # We need at least one dummy subnet per AZ to satisfy CDK's validation
113
+ vpc_attrs["public_subnet_ids"] = ["subnet-dummy1", "subnet-dummy2"]
114
+
115
+ # Use from_vpc_attributes() for SSM tokens
116
+ self._vpc = ec2.Vpc.from_vpc_attributes(self, "VPC", **vpc_attrs)
117
+ return self._vpc
118
+
119
+ def _create_vpc_not_found_error(self, config: Any, workload: Any) -> ValueError:
120
+ """
121
+ Create a descriptive error message for missing VPC configuration.
122
+
123
+ Args:
124
+ config: The stack configuration
125
+ workload: The workload configuration
126
+
127
+ Returns:
128
+ ValueError with descriptive message
129
+ """
130
+ config_name = getattr(config, 'name', 'unknown')
131
+ workload_name = getattr(workload, 'name', 'unknown')
132
+
133
+ return ValueError(
134
+ f"VPC is not defined in the configuration for {config_name}. "
135
+ f"You can provide it at the following locations:\n"
136
+ f" 1. As an SSM import: config.ssm_imports.vpc_id\n"
137
+ f" 2. At the config level: config.vpc_id\n"
138
+ f" 3. At the workload level: workload.vpc_id\n"
139
+ f"Current workload: {workload_name}"
140
+ )
141
+
142
+ def get_vpc_property(self, config: Any, deployment: Any, workload: Any) -> ec2.IVpc:
143
+ """
144
+ Standard VPC property implementation that can be used by stacks.
145
+
146
+ Args:
147
+ config: The stack configuration
148
+ deployment: The deployment configuration
149
+ workload: The workload configuration
150
+
151
+ Returns:
152
+ Resolved VPC reference
153
+ """
154
+ return self.resolve_vpc(config, deployment, workload)
@@ -12,7 +12,7 @@ from aws_cdk import aws_autoscaling as autoscaling
12
12
  from aws_cdk import aws_cloudwatch as cloudwatch
13
13
  from aws_cdk import aws_iam as iam
14
14
  from aws_cdk import aws_ssm as ssm
15
- from aws_cdk import Duration
15
+ from aws_cdk import Duration, Stack
16
16
  from aws_lambda_powertools import Logger
17
17
  from constructs import Construct
18
18
 
@@ -20,7 +20,6 @@ from cdk_factory.configurations.deployment import DeploymentConfig
20
20
  from cdk_factory.configurations.stack import StackConfig
21
21
  from cdk_factory.configurations.resources.auto_scaling import AutoScalingConfig
22
22
  from cdk_factory.interfaces.istack import IStack
23
- from cdk_factory.interfaces.enhanced_ssm_parameter_mixin import EnhancedSsmParameterMixin
24
23
  from cdk_factory.stack.stack_module_registry import register_stack
25
24
  from cdk_factory.workload.workload_factory import WorkloadConfig
26
25
 
@@ -29,14 +28,18 @@ logger = Logger(service="AutoScalingStack")
29
28
 
30
29
  @register_stack("auto_scaling_library_module")
31
30
  @register_stack("auto_scaling_stack")
32
- class AutoScalingStack(IStack, EnhancedSsmParameterMixin):
31
+ class AutoScalingStack(IStack):
33
32
  """
34
33
  Reusable stack for AWS Auto Scaling Groups.
35
34
  Supports creating EC2 Auto Scaling Groups with customizable configurations.
35
+
36
+ Uses enhanced SsmParameterMixin (via IStack) to eliminate SSM code duplication.
36
37
  """
37
38
 
38
39
  def __init__(self, scope: Construct, id: str, **kwargs) -> None:
40
+ # Initialize parent class properly - IStack inherits from enhanced SsmParameterMixin
39
41
  super().__init__(scope, id, **kwargs)
42
+
40
43
  self.asg_config = None
41
44
  self.stack_config = None
42
45
  self.deployment = None
@@ -46,9 +49,8 @@ class AutoScalingStack(IStack, EnhancedSsmParameterMixin):
46
49
  self.launch_template = None
47
50
  self.instance_role = None
48
51
  self.user_data = None
49
- self._vpc = None
50
- # SSM imported values
51
- self.ssm_imported_values: Dict[str, str] = {}
52
+
53
+ # SSM imports storage is now handled by the enhanced SsmParameterMixin via IStack
52
54
 
53
55
  def build(
54
56
  self,
@@ -75,10 +77,10 @@ class AutoScalingStack(IStack, EnhancedSsmParameterMixin):
75
77
  )
76
78
  asg_name = deployment.build_resource_name(self.asg_config.name)
77
79
 
78
- # Process SSM imports
79
- self._process_ssm_imports()
80
+ # Process SSM imports using enhanced SsmParameterMixin
81
+ self.process_ssm_imports(self.asg_config, deployment, "Auto Scaling Group")
80
82
 
81
- # Get VPC and security groups
83
+ # Get security groups
82
84
  self.security_groups = self._get_security_groups()
83
85
 
84
86
  # Create IAM role for instances
@@ -90,44 +92,57 @@ class AutoScalingStack(IStack, EnhancedSsmParameterMixin):
90
92
  # Create launch template
91
93
  self.launch_template = self._create_launch_template(asg_name)
92
94
 
93
- # Create auto scaling group
95
+ # Create Auto Scaling Group
94
96
  self.auto_scaling_group = self._create_auto_scaling_group(asg_name)
95
97
 
96
- # Configure scaling policies
97
- self._configure_scaling_policies()
98
+ # Add scaling policies
99
+ self._add_scaling_policies()
98
100
 
99
- # Add outputs
100
- self._add_outputs(asg_name)
101
+ # Add scheduled actions
102
+ self._add_scheduled_actions()
103
+
104
+ # Export resources
105
+ self._export_resources(asg_name)
101
106
 
102
107
  @property
103
108
  def vpc(self) -> ec2.IVpc:
104
- """Get the VPC for the Auto Scaling Group"""
105
- if self._vpc:
106
- return self._vpc
109
+ """Get the VPC for the Auto Scaling Group using enhanced SsmParameterMixin"""
110
+ if not self.asg_config:
111
+ raise AttributeError("AutoScalingStack not properly initialized. Call build() first.")
107
112
 
108
- # Check SSM imported values first (tokens from SSM parameters)
109
- if "vpc_id" in self.ssm_imported_values:
110
- vpc_id = self.ssm_imported_values["vpc_id"]
113
+ # Check SSM imported values first using enhanced mixin
114
+ if self.has_ssm_import("vpc_id"):
115
+ vpc_id = self.get_ssm_imported_value("vpc_id")
116
+
117
+ # Get subnet IDs first to determine AZ count
118
+ subnet_ids = []
119
+ if self.has_ssm_import("subnet_ids"):
120
+ imported_subnets = self.get_ssm_imported_value("subnet_ids", [])
121
+ if isinstance(imported_subnets, str):
122
+ # Split comma-separated subnet IDs
123
+ subnet_ids = [s.strip() for s in imported_subnets.split(",") if s.strip()]
124
+ elif isinstance(imported_subnets, list):
125
+ subnet_ids = imported_subnets
111
126
 
112
- # Build VPC attributes
127
+ # Build VPC attributes with matching AZ count
113
128
  vpc_attrs = {
114
129
  "vpc_id": vpc_id,
115
- "availability_zones": ["us-east-1a", "us-east-1b"],
130
+ "availability_zones": [f"us-east-1{chr(97+i)}" for i in range(len(subnet_ids))] if subnet_ids else ["us-east-1a", "us-east-1b"],
116
131
  }
117
132
 
118
- # If we have subnet_ids from SSM, provide dummy subnets
119
- # The actual subnets will be set via CloudFormation escape hatch
120
- if "subnet_ids" in self.ssm_imported_values:
121
- # Provide dummy subnet IDs - these will be overridden by the escape hatch
122
- # We need at least one dummy subnet per AZ to satisfy CDK's validation
133
+ # Use the actual subnet IDs from SSM
134
+ if subnet_ids:
135
+ vpc_attrs["public_subnet_ids"] = subnet_ids
136
+ else:
137
+ # Fallback to dummy subnets if no valid subnet IDs
123
138
  vpc_attrs["public_subnet_ids"] = ["subnet-dummy1", "subnet-dummy2"]
124
139
 
125
140
  # Use from_vpc_attributes() for SSM tokens
126
- self._vpc = ec2.Vpc.from_vpc_attributes(self, "VPC", **vpc_attrs)
141
+ return ec2.Vpc.from_vpc_attributes(self, "VPC", **vpc_attrs)
127
142
  elif self.asg_config.vpc_id:
128
- self._vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=self.asg_config.vpc_id)
143
+ return ec2.Vpc.from_lookup(self, "VPC", vpc_id=self.asg_config.vpc_id)
129
144
  elif self.workload.vpc_id:
130
- self._vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=self.workload.vpc_id)
145
+ return ec2.Vpc.from_lookup(self, "VPC", vpc_id=self.workload.vpc_id)
131
146
  else:
132
147
  # Use default VPC if not provided
133
148
  raise ValueError(
@@ -136,15 +151,13 @@ class AutoScalingStack(IStack, EnhancedSsmParameterMixin):
136
151
  "or a top level workload.vpc_id in the workload configuration."
137
152
  )
138
153
 
139
- return self._vpc
140
-
141
154
  def _get_target_group_arns(self) -> List[str]:
142
- """Get target group ARNs from SSM imports"""
155
+ """Get target group ARNs from SSM imports using enhanced SsmParameterMixin"""
143
156
  target_group_arns = []
144
157
 
145
- # Check if we have SSM imports for target groups
146
- if "target_group_arns" in self.ssm_imported_values:
147
- imported_tg_arns = self.ssm_imported_values["target_group_arns"]
158
+ # Check if we have SSM imports for target groups using enhanced mixin
159
+ if self.has_ssm_import("target_group_arns"):
160
+ imported_tg_arns = self.get_ssm_imported_value("target_group_arns", [])
148
161
  if isinstance(imported_tg_arns, list):
149
162
  target_group_arns.extend(imported_tg_arns)
150
163
  else:
@@ -579,47 +592,33 @@ class AutoScalingStack(IStack, EnhancedSsmParameterMixin):
579
592
  export_name=f"{self.deployment.build_resource_name(asg_name)}-launch-template-id",
580
593
  )
581
594
 
582
- def _process_ssm_imports(self) -> None:
583
- """
584
- Process SSM imports from configuration.
595
+
596
+ def _add_scaling_policies(self) -> None:
597
+ """Add scaling policies to the Auto Scaling Group"""
598
+ for policy_config in self.asg_config.scaling_policies:
599
+ # Scaling policy implementation would go here
600
+ pass
601
+
602
+ def _add_scheduled_actions(self) -> None:
603
+ """Add scheduled actions to the Auto Scaling Group"""
604
+ for action_config in self.asg_config.scheduled_actions:
605
+ # Scheduled action implementation would go here
606
+ pass
607
+
608
+ def _export_resources(self, asg_name: str) -> None:
609
+ """Export stack resources to SSM and CloudFormation outputs"""
610
+ # Export ASG name
611
+ cdk.CfnOutput(
612
+ self,
613
+ f"{asg_name}-name",
614
+ value=self.auto_scaling_group.auto_scaling_group_name,
615
+ export_name=f"{self.deployment.build_resource_name(asg_name)}-name",
616
+ )
585
617
 
586
- This method handles importing SSM parameters that are specified in the
587
- auto_scaling configuration under the 'ssm.imports' section.
588
- """
589
- logger.info(f"Processing {len(self.asg_config.ssm_imports)} SSM imports for Auto Scaling Group")
590
-
591
- for param_key, param_value in self.asg_config.ssm_imports.items():
592
- try:
593
- if isinstance(param_value, list):
594
- # Handle list imports (like security_group_ids)
595
- imported_list = []
596
- for item in param_value:
597
- param_path = item
598
- if not param_path.startswith('/'):
599
- param_path = f"/{self.deployment.environment}/{self.deployment.workload_name}/{item}"
600
-
601
- construct_id = f"ssm-import-{param_key}-{hash(param_path) % 10000}"
602
- param = ssm.StringParameter.from_string_parameter_name(
603
- self, construct_id, param_path
604
- )
605
- imported_list.append(param.string_value)
606
-
607
- self.ssm_imported_values[param_key] = imported_list
608
- logger.info(f"Imported SSM parameter list: {param_key} with {len(imported_list)} items")
609
- else:
610
- # Handle string values
611
- param_path = param_value
612
- if not param_path.startswith('/'):
613
- param_path = f"/{self.deployment.environment}/{self.deployment.workload_name}/{param_path}"
614
-
615
- construct_id = f"ssm-import-{param_key}-{hash(param_path) % 10000}"
616
- param = ssm.StringParameter.from_string_parameter_name(
617
- self, construct_id, param_path
618
- )
619
-
620
- self.ssm_imported_values[param_key] = param.string_value
621
- logger.info(f"Imported SSM parameter: {param_key} from {param_path}")
622
-
623
- except Exception as e:
624
- logger.error(f"Failed to import SSM parameter {param_key}: {e}")
625
- raise
618
+ # Export ASG ARN
619
+ cdk.CfnOutput(
620
+ self,
621
+ f"{asg_name}-arn",
622
+ value=self.auto_scaling_group.auto_scaling_group_arn,
623
+ export_name=f"{self.deployment.build_resource_name(asg_name)}-arn",
624
+ )
cdk_factory/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.16.5"
1
+ __version__ = "0.16.6"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdk_factory
3
- Version: 0.16.5
3
+ Version: 0.16.6
4
4
  Summary: CDK Factory. A QuickStarter and best practices setup for CDK projects
5
5
  Author-email: Eric Wilson <eric.wilson@geekcafe.com>
6
6
  License: MIT License
@@ -2,7 +2,7 @@ cdk_factory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  cdk_factory/app.py,sha256=RnX0-pwdTAPAdKJK_j13Zl8anf9zYKBwboR0KA8K8xM,10346
3
3
  cdk_factory/cdk.json,sha256=SKZKhJ2PBpFH78j-F8S3VDYW-lf76--Q2I3ON-ZIQfw,3106
4
4
  cdk_factory/cli.py,sha256=FGbCTS5dYCNsfp-etshzvFlGDCjC28r6rtzYbe7KoHI,6407
5
- cdk_factory/version.py,sha256=r0anPjT1FU7ZF59Wu8yrTS7JfVcf5Cbwqs29-uSLGyo,23
5
+ cdk_factory/version.py,sha256=vgsezcoqCKtoa7hPZmv2Zn1ce_NBglKR7w9c6ZIxjU0,23
6
6
  cdk_factory/builds/README.md,sha256=9BBWd7bXpyKdMU_g2UljhQwrC9i5O_Tvkb6oPvndoZk,90
7
7
  cdk_factory/commands/command_loader.py,sha256=QbLquuP_AdxtlxlDy-2IWCQ6D-7qa58aphnDPtp_uTs,3744
8
8
  cdk_factory/configurations/base_config.py,sha256=JKjhNsy0RCUZy1s8n5D_aXXI-upR9izaLtCTfKYiV9k,9624
@@ -63,9 +63,11 @@ cdk_factory/constructs/s3_buckets/s3_bucket_replication_destination_construct.py
63
63
  cdk_factory/constructs/s3_buckets/s3_bucket_replication_source_construct.py,sha256=ZLKbRcMK1q73VruxCH62XbymebKt-lKV5Kul9OjkZiA,3763
64
64
  cdk_factory/constructs/sqs/policies/sqs_policies.py,sha256=4p0G8G-fqNKSr68I55fvqH-DkhIeXyGaFBKkICIJ-qM,1277
65
65
  cdk_factory/interfaces/enhanced_ssm_parameter_mixin.py,sha256=5-aQ4sg47LQ4AHjd0j20gxyM5U5-NOTeBsGsEUA_K3E,14374
66
- cdk_factory/interfaces/istack.py,sha256=bhTBs-o9FgKwvJMSuwxjUV6D3nUlvZHVzfm27jP9x9Y,987
66
+ cdk_factory/interfaces/istack.py,sha256=4Bqls3Xbgwbnl9MjxsX8S2d5lMOMPdhlVu0DiAiTJ6Q,1152
67
67
  cdk_factory/interfaces/live_ssm_resolver.py,sha256=3FIr9a02SXqZmbFs3RT0WxczWEQR_CF7QSt7kWbDrVE,8163
68
- cdk_factory/interfaces/ssm_parameter_mixin.py,sha256=uA2j8HmAOpuEA9ynRj51s0WjUHMVLsbLQN-QS9NKyHA,12089
68
+ cdk_factory/interfaces/networked_stack_mixin.py,sha256=c_wDWPU4Y8HrTt2yGRwBJvVCfwHNy0SEeNMQjaUgcrI,2808
69
+ cdk_factory/interfaces/ssm_parameter_mixin.py,sha256=Z0KUbvDfvU-Kfpjtjm33Eo0ZonHQbnMlenR8FtG-0ls,17194
70
+ cdk_factory/interfaces/vpc_provider_mixin.py,sha256=-AZJRRHzaxej8hToGFAa0zK0ax_t0x46Cjg5v6WyMwQ,5602
69
71
  cdk_factory/lambdas/health_handler.py,sha256=dd40ykKMxWCFEIyp2ZdQvAGNjw_ylI9CSm1N24Hp2ME,196
70
72
  cdk_factory/lambdas/edge/ip_gate/handler.py,sha256=YrXO42gEhJoBTaH6jS7EWqjHe9t5Fpt4WLgY8vjtou0,10474
71
73
  cdk_factory/pipeline/path_utils.py,sha256=fvWdrcb4onmpIu1APkHLhXg8zWfK74HcW3Ra2ynxfXM,2586
@@ -84,7 +86,7 @@ cdk_factory/stack_library/acm/__init__.py,sha256=4FNRLykblcKZvq_wieYwvv9N_jgrZnJ
84
86
  cdk_factory/stack_library/acm/acm_stack.py,sha256=hflRXyOSjqGeJxBx87EV3Z3MJ5HEX2rnrjJ_E9wwhH8,5862
85
87
  cdk_factory/stack_library/api_gateway/api_gateway_stack.py,sha256=l6J5uurBQqbhj9JuvQitV9PiIHS5kqa-dFWifCeA3GM,39347
86
88
  cdk_factory/stack_library/auto_scaling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
- cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py,sha256=0q3wF7b6JX8yQiPQWnlII05_pwJif63ijvaQS5rzqyI,26451
89
+ cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py,sha256=qclpCa42KTsj8C0dyc8Qn2PadXkDeKSM3bi5jUPKOSo,26072
88
90
  cdk_factory/stack_library/aws_lambdas/lambda_stack.py,sha256=SFbBPvvCopbyiuYtq-O5sQkFCf94Wzua6aDUXiFDSB4,26161
89
91
  cdk_factory/stack_library/buckets/README.md,sha256=XkK3UNVtRLE7NtUvbhCOBBYUYi8hlrrSaI1s3GJVrqI,78
90
92
  cdk_factory/stack_library/buckets/bucket_stack.py,sha256=SLoZqSffAqmeBBEVUQg54D_8Ad5UKdkjEAmKAVgAqQo,1778
@@ -132,8 +134,8 @@ cdk_factory/utilities/lambda_function_utilities.py,sha256=S1GvBsY_q2cyUiaud3HORJ
132
134
  cdk_factory/utilities/os_execute.py,sha256=5Op0LY_8Y-pUm04y1k8MTpNrmQvcLmQHPQITEP7EuSU,1019
133
135
  cdk_factory/utils/api_gateway_utilities.py,sha256=If7Xu5s_UxmuV-kL3JkXxPLBdSVUKoLtohm0IUFoiV8,4378
134
136
  cdk_factory/workload/workload_factory.py,sha256=yDI3cRhVI5ELNDcJPLpk9UY54Uind1xQoV3spzT4z7E,6068
135
- cdk_factory-0.16.5.dist-info/METADATA,sha256=D2vXNb4pXKyPu01N3lbLxoY_hHCmL_SdzCQx0uUppyE,2451
136
- cdk_factory-0.16.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
137
- cdk_factory-0.16.5.dist-info/entry_points.txt,sha256=S1DPe0ORcdiwEALMN_WIo3UQrW_g4YdQCLEsc_b0Swg,53
138
- cdk_factory-0.16.5.dist-info/licenses/LICENSE,sha256=NOtdOeLwg2il_XBJdXUPFPX8JlV4dqTdDGAd2-khxT8,1066
139
- cdk_factory-0.16.5.dist-info/RECORD,,
137
+ cdk_factory-0.16.6.dist-info/METADATA,sha256=xpqNfI6Qt7mH9IXaN-5vfU9UAiV3lWCLWsgU3XlmaqA,2451
138
+ cdk_factory-0.16.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
139
+ cdk_factory-0.16.6.dist-info/entry_points.txt,sha256=S1DPe0ORcdiwEALMN_WIo3UQrW_g4YdQCLEsc_b0Swg,53
140
+ cdk_factory-0.16.6.dist-info/licenses/LICENSE,sha256=NOtdOeLwg2il_XBJdXUPFPX8JlV4dqTdDGAd2-khxT8,1066
141
+ cdk_factory-0.16.6.dist-info/RECORD,,