-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
45 changed files
with
958 additions
and
390 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,4 @@ | |
SAM CLI version | ||
""" | ||
|
||
__version__ = "1.81.0" | ||
__version__ = "1.82.0" |
163 changes: 163 additions & 0 deletions
163
samcli/hook_packages/terraform/designs/resource_linking_generalized.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
# Resource Linking | ||
|
||
After translating a resource from Terraform to CloudFormation, | ||
that resource often needs to be linked to another based on a field. | ||
|
||
For example, AWS Lambda Functions are linked to AWS Lambda Layers through the | ||
`Layers` property of a Lambda Function. | ||
|
||
E.g. | ||
```yaml | ||
Resources: | ||
AwsLambdaFunction: | ||
Type: AWS::Lambda::Function | ||
Properties: | ||
FunctionName: s3_lambda_function | ||
Code: function.zip | ||
Handler: app.lambda_handler | ||
PackageType: Zip | ||
Runtime: python3.8 | ||
Layers: | ||
- Ref: AwsLambdaLayerVersion | ||
AwsLambdaLayerVersion: | ||
Type: AWS::Lambda::LayerVersion | ||
Properties: | ||
LayerName: lambda_layer1 | ||
CompatibleRuntimes: | ||
- python3.8 | ||
Content: layer.zip | ||
``` | ||
In this case, the function will be defined as the `source` resource and the layer | ||
as the `destination` resource. The `Layers` field links to the destination resource | ||
using a CloudFormation intrinsic function `!Ref`, and points to the Lambda Layer Arn. | ||
|
||
Today, the linking logic is specific to Functions and Layers. The section below proposes | ||
a method of generalization to make the linking of two resources more extensible and easier to implement. | ||
|
||
## Proposed Solution | ||
Currently, the linking design is functional and passes certain required parameters from | ||
the translation function to a specific Function to Layer linking function. Since the fields required to link any two resources primarily the same, they can be abstracted away to a data class | ||
that will house them. | ||
|
||
```python | ||
@dataclass | ||
class ResourceLinkingPair: | ||
source_resource_cfn_resource: Dict[str, List] | ||
source_resource_tf_config: Dict[str, TFResource] | ||
destination_resource_tf: Dict[str, Dict] | ||
intrinsic_type: LinkerIntrinsics | ||
cfn_intrinsic_attribute: Optional[str] | ||
source_link_field_name: str | ||
terraform_resource_type_prefix: str | ||
linking_exceptions: ResourcePairLinkingExceptions | ||
``` | ||
|
||
- `source_resource_cfn_resource` this the CFN representation of the resource to which the linked resource will be added | ||
- `source_resource_tf_config` the Terraform configuration object for the source resource | ||
- `destination_resource_tf` the destination resources' Terraform planned values (not the configuration object) | ||
- `intrinsic_type` the CFN intrinsic on which to link (`Ref` or `GetAtt`) | ||
- `cfn_intrinsic_attribute` in the case of `GetAtt`, the resource attribute to link to (should be None for `Ref`) | ||
- `source_link_field_name` the name in the source CFN resource to add the linked resource to | ||
- `terraform_resource_type_prefix` the Terraform resource type prefix used for finding all resource of that type | ||
- `linking_exceptions` these are exceptions that need to be created with messages specific to the resource linking pair to be used | ||
by the `ResourceLinker`. With specific exception types, metric data can be collected specific to the resources being linked. | ||
|
||
```python | ||
class ResourcePairLinkingExceptions: | ||
multiple_resource_linking_exception: Type[UserException] | ||
local_variable_linking_exception: Type[UserException] | ||
``` | ||
|
||
|
||
Only the first three fields are computed, and need to be collected the same way they are today, when parsing the Terraform modules. | ||
E.g. collecting the Lambda function `source_resource_cfn_resource` and `source_resource_tf_config` looks like this: | ||
```python | ||
if resource_type == TF_AWS_LAMBDA_FUNCTION: | ||
resolved_config_address = _get_configuration_address(resource_full_address) | ||
matched_lambdas = source_resource_cfn_resource.get(resolved_config_address, []) | ||
matched_lambdas.append(translated_resource) | ||
source_resource_cfn_resource[resolved_config_address] = matched_lambdas | ||
source_resource_tf_config[resolved_config_address] = config_resource | ||
``` | ||
|
||
and on the destination Layer resource, collecting the `destination_resource_tf` | ||
```python | ||
if resource_type == TF_AWS_LAMBDA_LAYER_VERSION: | ||
destination_resource_tf[logical_id] = resource | ||
``` | ||
|
||
After collecting those three fields, a `ResourceLinkingPair` object can be instantiated. | ||
|
||
Once all `ResourceLinkingPair` objects have been created, a list of these objects can be passed to the `ResourceLinker`. | ||
```python | ||
class ResourceLinker: | ||
_resource_pairs: List[ResourceLinkingPair] | ||
def link_resources(self): | ||
""" | ||
Iterate through all of the ResourceLinkingPair items and link the | ||
corresponding source resource to destination resource | ||
""" | ||
def _update_mapped_parent_resource_with_resolved_child_resources(self, destination_resources: List): | ||
""" | ||
Set the resolved destination resource list to the mapped source resources. | ||
Parameters | ||
---------- | ||
destination_resources: List | ||
The resolved destination resource values that will be used as a value for the mapped CFN resource attribute. | ||
""" | ||
def _process_reference_resource_value(self, resolved_destination_resource: ResolvedReference): | ||
""" | ||
Process the a reference destination resource value of type ResolvedReference. | ||
Parameters | ||
---------- | ||
resolved_destination_resource: ResolvedReference | ||
The resolved destination resource reference. | ||
Returns | ||
------- | ||
List[Dict[str, str]] | ||
The resolved values that will be used as a value for the mapped CFN resource attribute. | ||
""" | ||
def _process_resolved_resources(self, resolved_destination_resource: List[Union[ConstantValue, ResolvedReference]]): | ||
""" | ||
Process the resolved destination resources. | ||
Parameters | ||
---------- | ||
resolved_destination_resource: List[Union[ConstantValue, ResolvedReference]] | ||
The resolved destination resources to be processed for the input source resource. | ||
Returns | ||
-------- | ||
List[Dict[str, str]]: | ||
The list of destination resources after processing | ||
""" | ||
``` | ||
|
||
The `ResourceLinker` contains a public `link_resources` method to begin execution of the resource linking. The methods | ||
shown in the class are all generalized versions of the existing Function to Layer linking functions that exist today. | ||
|
||
`link_resources` ← `_link_lambda_function_to_layer`, `_link_lambda_functions_to_layers` | ||
`_update_mapped_parent_resource_with_resolved_child_resources` ← `_update_mapped_lambda_function_with_resolved_layers` | ||
`_process_reference_resource_value` ← `_process_reference_layer_value` | ||
`_process_resolved_resources` ← `_process_resolved_layers` | ||
|
||
To generalize these functions: | ||
- All instances of hard-coded properties need to be replaced with the corresponding values | ||
defined in the `ResourceLinkingPair` instance | ||
- Exception messages should be updated to be more generic | ||
- The `_update_mapped_parent_resource_with_resolved_child_resources` method should be updated to support writing other intrinsic types. | ||
|
||
|
||
### Adding New Resource Links | ||
With the proposed change, creating a new link between two resources will include: | ||
1. Collecting the three required fields (`source_resource_cfn_resource`, `source_resource_tf_config` and `destination_resource_tf`) | ||
2. Creating a `ResourceLinkingPair` instance | ||
3. Appending the `ResourceLinkingPair` to the list of pairs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ | |
""" | ||
from typing import Set | ||
|
||
PREVIEW_RUNTIMES: Set[str] = {"java17"} | ||
PREVIEW_RUNTIMES: Set[str] = set() |
Oops, something went wrong.