diff --git a/integration/config/code_key_to_file_map.json b/integration/config/code_key_to_file_map.json index a58131d85..68709d999 100644 --- a/integration/config/code_key_to_file_map.json +++ b/integration/config/code_key_to_file_map.json @@ -3,6 +3,7 @@ "codeuri": "code.zip", "contenturi": "layer1.zip", "definitionuri": "swagger1.json", + "microvmcodeuri": "microvm_code.zip", "mtlsuri": "MTLSCert.pem", "templateurl": "template.yaml" } diff --git a/integration/config/file_to_s3_map.json b/integration/config/file_to_s3_map.json index bdffb17e7..8c82f7a5a 100644 --- a/integration/config/file_to_s3_map.json +++ b/integration/config/file_to_s3_map.json @@ -27,6 +27,10 @@ "type": "s3", "uri": "" }, + "microvm_code.zip": { + "type": "s3", + "uri": "" + }, "swagger1.json": { "type": "s3", "uri": "" diff --git a/integration/config/service_names.py b/integration/config/service_names.py index 6f975d846..3296f64b2 100644 --- a/integration/config/service_names.py +++ b/integration/config/service_names.py @@ -32,6 +32,7 @@ STATE_MACHINE_WITH_APIS = "StateMachineWithApis" LAMBDA_URL = "LambdaUrl" LAMBDA_MANAGED_INSTANCES = "LambdaManagedInstances" +MICROVM_IMAGE = "MicrovmImage" LAMBDA_ENV_VARS = "LambdaEnvVars" EVENT_INVOKE_CONFIG = "EventInvokeConfig" API_KEY = "ApiKey" diff --git a/integration/resources/code/microvm_code.zip b/integration/resources/code/microvm_code.zip new file mode 100644 index 000000000..56ce345d7 Binary files /dev/null and b/integration/resources/code/microvm_code.zip differ diff --git a/integration/resources/expected/single/basic_microvm_image.json b/integration/resources/expected/single/basic_microvm_image.json new file mode 100644 index 000000000..01ef3c143 --- /dev/null +++ b/integration/resources/expected/single/basic_microvm_image.json @@ -0,0 +1,10 @@ +[ + { + "LogicalResourceId": "MyMicroVMImage", + "ResourceType": "AWS::Lambda::MicrovmImage" + }, + { + "LogicalResourceId": "MyMicroVMImageBuildRole", + "ResourceType": "AWS::IAM::Role" + } +] diff --git a/integration/resources/expected/single/basic_microvm_image_minimal.json b/integration/resources/expected/single/basic_microvm_image_minimal.json new file mode 100644 index 000000000..3a6e17aa6 --- /dev/null +++ b/integration/resources/expected/single/basic_microvm_image_minimal.json @@ -0,0 +1,10 @@ +[ + { + "LogicalResourceId": "MyMinimalMicroVMImage", + "ResourceType": "AWS::Lambda::MicrovmImage" + }, + { + "LogicalResourceId": "MyMinimalMicroVMImageBuildRole", + "ResourceType": "AWS::IAM::Role" + } +] diff --git a/integration/resources/expected/single/basic_microvm_image_with_build_role.json b/integration/resources/expected/single/basic_microvm_image_with_build_role.json new file mode 100644 index 000000000..d333c14b1 --- /dev/null +++ b/integration/resources/expected/single/basic_microvm_image_with_build_role.json @@ -0,0 +1,10 @@ +[ + { + "LogicalResourceId": "MyMicroVMImageWithBuildRole", + "ResourceType": "AWS::Lambda::MicrovmImage" + }, + { + "LogicalResourceId": "CustomBuildRole", + "ResourceType": "AWS::IAM::Role" + } +] diff --git a/integration/resources/expected/single/basic_network_connector.json b/integration/resources/expected/single/basic_network_connector.json new file mode 100644 index 000000000..ce4de8d99 --- /dev/null +++ b/integration/resources/expected/single/basic_network_connector.json @@ -0,0 +1,10 @@ +[ + { + "LogicalResourceId": "MyNetworkConnector", + "ResourceType": "AWS::Lambda::NetworkConnector" + }, + { + "LogicalResourceId": "MyNetworkConnectorOperatorRole", + "ResourceType": "AWS::IAM::Role" + } +] diff --git a/integration/resources/expected/single/basic_network_connector_with_role.json b/integration/resources/expected/single/basic_network_connector_with_role.json new file mode 100644 index 000000000..842be81c6 --- /dev/null +++ b/integration/resources/expected/single/basic_network_connector_with_role.json @@ -0,0 +1,10 @@ +[ + { + "LogicalResourceId": "MyNetworkConnectorWithRole", + "ResourceType": "AWS::Lambda::NetworkConnector" + }, + { + "LogicalResourceId": "CustomOperatorRole", + "ResourceType": "AWS::IAM::Role" + } +] diff --git a/integration/resources/templates/single/basic_microvm_image.yaml b/integration/resources/templates/single/basic_microvm_image.yaml new file mode 100644 index 000000000..42bcc09ab --- /dev/null +++ b/integration/resources/templates/single/basic_microvm_image.yaml @@ -0,0 +1,23 @@ +Resources: + MyMicroVMImage: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: + Fn::Select: + - 2 + - Fn::Split: + - / + - !Ref AWS::StackId + CodeUri: ${microvmcodeuri} + BaseImageArn: !Sub arn:aws:lambda:${AWS::Region}:aws:microvm-image:al2023-0 + BaseImageVersion: '0' + Resources: + - MinimumMemoryInMiB: 512 + CpuConfigurations: + - Architecture: ARM_64 + Hooks: + Port: 9000 + Tags: + Environment: IntegTest +Metadata: + SamTransformTest: true diff --git a/integration/resources/templates/single/basic_microvm_image_minimal.yaml b/integration/resources/templates/single/basic_microvm_image_minimal.yaml new file mode 100644 index 000000000..4375f3ff8 --- /dev/null +++ b/integration/resources/templates/single/basic_microvm_image_minimal.yaml @@ -0,0 +1,15 @@ +Resources: + MyMinimalMicroVMImage: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: + Fn::Select: + - 2 + - Fn::Split: + - / + - !Ref AWS::StackId + CodeUri: ${microvmcodeuri} + BaseImageArn: !Sub arn:aws:lambda:${AWS::Region}:aws:microvm-image:al2023-0 + BaseImageVersion: '0' +Metadata: + SamTransformTest: true diff --git a/integration/resources/templates/single/basic_microvm_image_with_build_role.yaml b/integration/resources/templates/single/basic_microvm_image_with_build_role.yaml new file mode 100644 index 000000000..5c56404c1 --- /dev/null +++ b/integration/resources/templates/single/basic_microvm_image_with_build_role.yaml @@ -0,0 +1,48 @@ +Resources: + MyMicroVMImageWithBuildRole: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: + Fn::Select: + - 2 + - Fn::Split: + - / + - !Ref AWS::StackId + CodeUri: ${microvmcodeuri} + BaseImageArn: !Sub arn:aws:lambda:${AWS::Region}:aws:microvm-image:al2023-0 + BaseImageVersion: '0' + BuildRoleArn: !GetAtt CustomBuildRole.Arn + Resources: + - MinimumMemoryInMiB: 512 + CpuConfigurations: + - Architecture: ARM_64 + Hooks: + Port: 9000 + + CustomBuildRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + - sts:TagSession + Policies: + - PolicyName: CustomBuildPolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - s3:GetObject + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: '*' +Metadata: + SamTransformTest: true diff --git a/integration/resources/templates/single/basic_network_connector.yaml b/integration/resources/templates/single/basic_network_connector.yaml new file mode 100644 index 000000000..2deebd052 --- /dev/null +++ b/integration/resources/templates/single/basic_network_connector.yaml @@ -0,0 +1,21 @@ +Resources: + MyNetworkConnector: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - !Ref SubnetId + SecurityGroupIds: + - !Ref SecurityGroup + NetworkProtocol: IPv4 + Tags: + Environment: IntegTest + +Parameters: + SubnetId: + Type: String + SecurityGroup: + Type: String + +Metadata: + SamTransformTest: true diff --git a/integration/resources/templates/single/basic_network_connector_with_role.yaml b/integration/resources/templates/single/basic_network_connector_with_role.yaml new file mode 100644 index 000000000..2cbaa5232 --- /dev/null +++ b/integration/resources/templates/single/basic_network_connector_with_role.yaml @@ -0,0 +1,41 @@ +Resources: + MyNetworkConnectorWithRole: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - !Ref SubnetId + SecurityGroupIds: + - !Ref SecurityGroup + NetworkProtocol: IPv4 + OperatorRole: !GetAtt CustomOperatorRole.Arn + + CustomOperatorRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: CustomOperatorPolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - ec2:CreateNetworkInterface + - ec2:CreateTags + Resource: '*' + +Parameters: + SubnetId: + Type: String + SecurityGroup: + Type: String + +Metadata: + SamTransformTest: true diff --git a/integration/single/test_basic_microvm_image.py b/integration/single/test_basic_microvm_image.py new file mode 100644 index 000000000..a6a014e73 --- /dev/null +++ b/integration/single/test_basic_microvm_image.py @@ -0,0 +1,81 @@ +import logging +from unittest.case import skipIf + +from integration.helpers.base_test import BaseTest + +LOG = logging.getLogger(__name__) + + +@skipIf(True, "MicroVMImage is not yet GA - enable when RIP feature flag is available") +class TestBasicMicroVMImage(BaseTest): + """ + Basic AWS::Serverless::MicroVMImage tests + """ + + def test_basic_microvm_image(self): + """ + Creates a MicroVMImage with auto-generated BuildRole + """ + self.create_and_verify_stack("single/basic_microvm_image") + + # Verify the auto-generated BuildRole exists and has correct trust policy + role_name = self.get_physical_id_by_logical_id("MyMicroVMImageBuildRole") + iam_client = self.client_provider.iam_client + role = iam_client.get_role(RoleName=role_name) + + # Verify trust policy principal + trust_policy = role["Role"]["AssumeRolePolicyDocument"] + principals = [] + for stmt in trust_policy["Statement"]: + if stmt["Effect"] != "Allow": + continue + service = stmt["Principal"].get("Service", []) + if isinstance(service, str): + principals.append(service) + else: + principals.extend(service) + self.assertIn( + "lambda.amazonaws.com", + principals, + "BuildRole should trust lambda-microvms service", + ) + + # Verify inline policy exists with scoped S3 permissions + role_policy = iam_client.get_role_policy(RoleName=role_name, PolicyName="MicrovmImageBuildPolicy") + statements = role_policy["PolicyDocument"]["Statement"] + s3_statement = next((s for s in statements if "s3:GetObject" in s["Action"]), None) + logs_statement = next((s for s in statements if "logs:CreateLogGroup" in s["Action"]), None) + + self.assertIsNotNone(s3_statement, "Should have s3:GetObject statement") + self.assertIsNotNone(logs_statement, "Should have logs statement") + # S3 should be scoped (not wildcard) + self.assertNotEqual(s3_statement["Resource"], "*", "s3:GetObject should not use wildcard resource") + # Logs uses wildcard (expected) + self.assertEqual(logs_statement["Resource"], "*", "logs should use wildcard resource") + # kms:Decrypt should NOT be present + all_actions = [action for stmt in statements for action in stmt["Action"]] + self.assertNotIn("kms:Decrypt", all_actions, "kms:Decrypt should not be in auto-generated role") + + def test_microvm_image_with_custom_build_role(self): + """ + Creates a MicroVMImage with customer-provided BuildRole (no auto-generation) + """ + self.create_and_verify_stack("single/basic_microvm_image_with_build_role") + + # Verify only the customer-provided role exists (no auto-generated role) + stack_resources = self.get_stack_resources("AWS::IAM::Role") + role_logical_ids = [r["LogicalResourceId"] for r in stack_resources] + + self.assertIn("CustomBuildRole", role_logical_ids) + self.assertNotIn( + "MyMicroVMImageWithBuildRoleBuildRole", + role_logical_ids, + "Should NOT auto-generate BuildRole when BuildRoleArn is provided", + ) + + def test_basic_microvm_image_minimal(self): + """ + Creates a MicroVMImage with only required fields — all optional fields omitted. + Verifies SAM auto-injects defaults and generates BuildRole. + """ + self.create_and_verify_stack("single/basic_microvm_image_minimal") diff --git a/integration/single/test_basic_network_connector.py b/integration/single/test_basic_network_connector.py new file mode 100644 index 000000000..d05cb8505 --- /dev/null +++ b/integration/single/test_basic_network_connector.py @@ -0,0 +1,73 @@ +import logging +from unittest.case import skipIf + +import pytest + +from integration.helpers.base_test import BaseTest + +LOG = logging.getLogger(__name__) + + +@skipIf(True, "NetworkConnector is not yet GA - enable when RIP feature flag is available") +class TestBasicNetworkConnector(BaseTest): + """ + Basic AWS::Serverless::NetworkConnector tests + """ + + @pytest.fixture(autouse=True) + def companion_stack_outputs(self, get_companion_stack_outputs): + self.companion_stack_outputs = get_companion_stack_outputs + + def generate_nc_parameters(self): + return [ + self.generate_parameter("SubnetId", self.companion_stack_outputs["LMISubnetId"]), + self.generate_parameter("SecurityGroup", self.companion_stack_outputs["LMISecurityGroupId"]), + ] + + def test_basic_network_connector(self): + """ + Creates a NetworkConnector with auto-generated OperatorRole + """ + parameters = self.generate_nc_parameters() + self.create_and_verify_stack("single/basic_network_connector", parameters) + + # Verify the auto-generated OperatorRole exists and has correct trust policy + role_name = self.get_physical_id_by_logical_id("MyNetworkConnectorOperatorRole") + iam_client = self.client_provider.iam_client + role = iam_client.get_role(RoleName=role_name) + + trust_policy = role["Role"]["AssumeRolePolicyDocument"] + principals = [] + for stmt in trust_policy["Statement"]: + if stmt["Effect"] != "Allow": + continue + service = stmt["Principal"].get("Service", []) + if isinstance(service, str): + principals.append(service) + else: + principals.extend(service) + self.assertIn("lambda.amazonaws.com", principals) + + # Verify inline policy + role_policy = iam_client.get_role_policy(RoleName=role_name, PolicyName="NetworkConnectorOperatorPolicy") + statements = role_policy["PolicyDocument"]["Statement"] + all_actions = [s["Action"] for s in statements] + self.assertIn("ec2:CreateNetworkInterface", all_actions) + self.assertIn("ec2:CreateTags", all_actions) + + def test_network_connector_with_custom_role(self): + """ + Creates a NetworkConnector with customer-provided OperatorRole (no auto-generation) + """ + parameters = self.generate_nc_parameters() + self.create_and_verify_stack("single/basic_network_connector_with_role", parameters) + + stack_resources = self.get_stack_resources("AWS::IAM::Role") + role_logical_ids = [r["LogicalResourceId"] for r in stack_resources] + + self.assertIn("CustomOperatorRole", role_logical_ids) + self.assertNotIn( + "MyNetworkConnectorWithRoleOperatorRole", + role_logical_ids, + "Should NOT auto-generate OperatorRole when OperatorRole is provided", + ) diff --git a/samtranslator/__init__.py b/samtranslator/__init__.py index 88c2a43ca..ff02d400a 100644 --- a/samtranslator/__init__.py +++ b/samtranslator/__init__.py @@ -1 +1 @@ -__version__ = "1.110.0" +__version__ = "1.111.0" diff --git a/samtranslator/internal/schema_source/aws_serverless_microvmimage.py b/samtranslator/internal/schema_source/aws_serverless_microvmimage.py new file mode 100644 index 000000000..f095d7ce0 --- /dev/null +++ b/samtranslator/internal/schema_source/aws_serverless_microvmimage.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from typing import Literal + +from samtranslator.internal.schema_source.common import ( + BaseModel, + DictStrAny, + ResourceAttributes, + SamIntrinsicable, + get_prop, +) + +PROPERTIES_STEM = "sam-resource-microvmimage" +HOOKS_STEM = "sam-property-microvmimage-hooks" +MICROVM_HOOKS_STEM = "sam-property-microvmimage-microvmhooks" +MICROVM_IMAGE_HOOKS_STEM = "sam-property-microvmimage-microvmimagehooks" +RESOURCE_SPEC_STEM = "sam-property-microvmimage-resource" +CPU_CONFIGURATION_STEM = "sam-property-microvmimage-cpuconfiguration" +LOGGING_STEM = "sam-property-microvmimage-logging" +CLOUDWATCH_LOGGING_STEM = "sam-property-microvmimage-cloudwatchlogging" + +properties = get_prop(PROPERTIES_STEM) +hooks_props = get_prop(HOOKS_STEM) +microvm_hooks_props = get_prop(MICROVM_HOOKS_STEM) +microvm_image_hooks_props = get_prop(MICROVM_IMAGE_HOOKS_STEM) +resource_spec = get_prop(RESOURCE_SPEC_STEM) +cpu_configuration = get_prop(CPU_CONFIGURATION_STEM) +logging_props = get_prop(LOGGING_STEM) +cloudwatch_logging_props = get_prop(CLOUDWATCH_LOGGING_STEM) + +HookState = SamIntrinsicable[Literal["ENABLED", "DISABLED"]] + + +class ResourceSpec(BaseModel): + MinimumMemoryInMiB: SamIntrinsicable[int] = resource_spec("MinimumMemoryInMiB") + + +class CpuConfiguration(BaseModel): + Architecture: SamIntrinsicable[Literal["ARM_64"]] = cpu_configuration("Architecture") + + +class MicrovmHooks(BaseModel): + Run: HookState | None = microvm_hooks_props("Run") + RunTimeoutInSeconds: SamIntrinsicable[int] | None = microvm_hooks_props("RunTimeoutInSeconds") + Resume: HookState | None = microvm_hooks_props("Resume") + ResumeTimeoutInSeconds: SamIntrinsicable[int] | None = microvm_hooks_props("ResumeTimeoutInSeconds") + Suspend: HookState | None = microvm_hooks_props("Suspend") + SuspendTimeoutInSeconds: SamIntrinsicable[int] | None = microvm_hooks_props("SuspendTimeoutInSeconds") + Terminate: HookState | None = microvm_hooks_props("Terminate") + TerminateTimeoutInSeconds: SamIntrinsicable[int] | None = microvm_hooks_props("TerminateTimeoutInSeconds") + + +class MicrovmImageHooks(BaseModel): + Ready: HookState | None = microvm_image_hooks_props("Ready") + ReadyTimeoutInSeconds: SamIntrinsicable[int] | None = microvm_image_hooks_props("ReadyTimeoutInSeconds") + Validate: HookState | None = microvm_image_hooks_props("Validate") + ValidateTimeoutInSeconds: SamIntrinsicable[int] | None = microvm_image_hooks_props("ValidateTimeoutInSeconds") + + +class Hooks(BaseModel): + Port: SamIntrinsicable[int] | None = hooks_props("Port") + MicrovmHooks: MicrovmHooks | None = hooks_props("MicrovmHooks") + MicrovmImageHooks: MicrovmImageHooks | None = hooks_props("MicrovmImageHooks") + + +class CloudWatchLogging(BaseModel): + LogGroup: SamIntrinsicable[str] | None = cloudwatch_logging_props("LogGroup") + LogStream: SamIntrinsicable[str] | None = cloudwatch_logging_props("LogStream") + + +class Logging(BaseModel): + Disabled: bool | None = logging_props("Disabled") + CloudWatch: CloudWatchLogging | None = logging_props("CloudWatch") + + +class Properties(BaseModel): + Name: SamIntrinsicable[str] = properties("Name") + CodeUri: SamIntrinsicable[str] = properties("CodeUri") + BaseImageArn: SamIntrinsicable[str] = properties("BaseImageArn") + BaseImageVersion: SamIntrinsicable[str] = properties("BaseImageVersion") + BuildRoleArn: SamIntrinsicable[str] | None = properties("BuildRoleArn") + Description: SamIntrinsicable[str] | None = properties("Description") + Tags: DictStrAny | None = properties("Tags") + Logging: Logging | None = properties("Logging") + EgressNetworkConnectors: list[SamIntrinsicable[str]] | None = properties("EgressNetworkConnectors") + CpuConfigurations: list[CpuConfiguration] | None = properties("CpuConfigurations") + Resources: list[ResourceSpec] | None = properties("Resources") + AdditionalOsCapabilities: list[SamIntrinsicable[Literal["ALL"]]] | None = properties("AdditionalOsCapabilities") + Hooks: Hooks | None = properties("Hooks") + EnvironmentVariables: DictStrAny | None = properties("EnvironmentVariables") + PropagateTags: bool | None = properties("PropagateTags") + + +class Globals(BaseModel): + BuildRoleArn: SamIntrinsicable[str] | None = properties("BuildRoleArn") + BaseImageArn: SamIntrinsicable[str] | None = properties("BaseImageArn") + BaseImageVersion: SamIntrinsicable[str] | None = properties("BaseImageVersion") + Logging: Logging | None = properties("Logging") + EgressNetworkConnectors: list[SamIntrinsicable[str]] | None = properties("EgressNetworkConnectors") + CpuConfigurations: list[CpuConfiguration] | None = properties("CpuConfigurations") + Resources: list[ResourceSpec] | None = properties("Resources") + AdditionalOsCapabilities: list[SamIntrinsicable[Literal["ALL"]]] | None = properties("AdditionalOsCapabilities") + Hooks: Hooks | None = properties("Hooks") + EnvironmentVariables: DictStrAny | None = properties("EnvironmentVariables") + Tags: DictStrAny | None = properties("Tags") + PropagateTags: bool | None = properties("PropagateTags") + + +class Resource(ResourceAttributes): + Type: Literal["AWS::Serverless::MicrovmImage"] + Properties: Properties diff --git a/samtranslator/internal/schema_source/aws_serverless_networkconnector.py b/samtranslator/internal/schema_source/aws_serverless_networkconnector.py new file mode 100644 index 000000000..4e3585fd4 --- /dev/null +++ b/samtranslator/internal/schema_source/aws_serverless_networkconnector.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from typing import Literal + +from samtranslator.internal.schema_source.common import ( + BaseModel, + DictStrAny, + ResourceAttributes, + SamIntrinsicable, + get_prop, +) + +PROPERTIES_STEM = "sam-resource-networkconnector" +VPC_CONFIG_STEM = "sam-property-networkconnector-vpcconfig" + +properties = get_prop(PROPERTIES_STEM) +vpc_config_props = get_prop(VPC_CONFIG_STEM) + + +class VpcConfig(BaseModel): + SubnetIds: list[SamIntrinsicable[str]] = vpc_config_props("SubnetIds") + SecurityGroupIds: list[SamIntrinsicable[str]] = vpc_config_props("SecurityGroupIds") + NetworkProtocol: SamIntrinsicable[Literal["IPv4", "DualStack"]] = vpc_config_props("NetworkProtocol") + + +class Properties(BaseModel): + Name: SamIntrinsicable[str] | None = properties("Name") + VpcConfig: VpcConfig = properties("VpcConfig") + OperatorRole: SamIntrinsicable[str] | None = properties("OperatorRole") + Tags: DictStrAny | None = properties("Tags") + PropagateTags: bool | None = properties("PropagateTags") + + +class Globals(BaseModel): + OperatorRole: SamIntrinsicable[str] | None = properties("OperatorRole") + Tags: DictStrAny | None = properties("Tags") + PropagateTags: bool | None = properties("PropagateTags") + + +class Resource(ResourceAttributes): + Type: Literal["AWS::Serverless::NetworkConnector"] + Properties: Properties diff --git a/samtranslator/internal/schema_source/sam-docs.json b/samtranslator/internal/schema_source/sam-docs.json index 3d062da0b..e0db02d26 100644 --- a/samtranslator/internal/schema_source/sam-docs.json +++ b/samtranslator/internal/schema_source/sam-docs.json @@ -783,6 +783,58 @@ "Tags": "A map of key-value pairs to apply to the capacity provider and its associated resources. \n*Type*: Map \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`Tags`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-tags) property of an `AWS::Lambda::CapacityProvider` resource. The `Tags` property in AWS SAM consists of key-value pairs (whereas in CloudFormation this property consists of a list of Tag objects). Also, AWS SAM automatically adds a `lambda:createdBy:SAM` tag to this Lambda function, and to the default roles generated for this function.", "VpcConfig": "The VPC configuration for the capacity provider. Specifies the VPC subnets and security groups where Amazon EC2 instances will be launched. \n*Type*: [VpcConfig](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-capacityprovider-vpcconfig.html) \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource." }, + "sam-resource-microvmimage": { + "Name": "TODO", + "CodeUri": "TODO", + "BaseImageArn": "TODO", + "BuildRoleArn": "TODO", + "BaseImageVersion": "TODO", + "Description": "TODO", + "Tags": "TODO", + "Logging": "TODO", + "EgressNetworkConnectors": "TODO", + "CpuConfigurations": "TODO", + "Resources": "TODO", + "AdditionalOsCapabilities": "TODO", + "Hooks": "TODO", + "EnvironmentVariables": "TODO", + "PropagateTags": "TODO" + }, + "sam-property-microvmimage-hooks": { + "Port": "TODO", + "MicrovmHooks": "TODO", + "MicrovmImageHooks": "TODO" + }, + "sam-property-microvmimage-microvmhooks": { + "Run": "TODO", + "RunTimeoutInSeconds": "TODO", + "Resume": "TODO", + "ResumeTimeoutInSeconds": "TODO", + "Suspend": "TODO", + "SuspendTimeoutInSeconds": "TODO", + "Terminate": "TODO", + "TerminateTimeoutInSeconds": "TODO" + }, + "sam-property-microvmimage-microvmimagehooks": { + "Ready": "TODO", + "ReadyTimeoutInSeconds": "TODO", + "Validate": "TODO", + "ValidateTimeoutInSeconds": "TODO" + }, + "sam-property-microvmimage-logging": { + "Disabled": "TODO", + "CloudWatch": "TODO" + }, + "sam-property-microvmimage-cloudwatchlogging": { + "LogGroup": "TODO", + "LogStream": "TODO" + }, + "sam-property-microvmimage-resource": { + "MinimumMemoryInMiB": "TODO" + }, + "sam-property-microvmimage-cpuconfiguration": { + "Architecture": "TODO" + }, "sam-resource-connector": { "Destination": "The destination resource. \n*Type*: [ ResourceReference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-connector-resourcereference.html) \\$1 List of [ResourceReference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-connector-resourcereference.html) \n*Required*: Yes \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", "Permissions": "The permission type that the source resource is allowed to perform on the destination resource. \n`Read` includes AWS Identity and Access Management (https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/IAM.html) actions that allow reading data from the resource. \n`Write` inclues https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/IAM.html actions that allow initiating and writing data to a resource. \n*Valid values*: `Read` or `Write` \n*Type*: List \n*Required*: Yes \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", @@ -930,6 +982,18 @@ "StageName": "TODO", "StageVariables": "TODO", "Tags": "TODO" + }, + "sam-resource-networkconnector": { + "Name": "TODO", + "VpcConfig": "TODO", + "OperatorRole": "TODO", + "Tags": "TODO", + "PropagateTags": "TODO" + }, + "sam-property-networkconnector-vpcconfig": { + "SubnetIds": "TODO", + "SecurityGroupIds": "TODO", + "NetworkProtocol": "TODO" } } } \ No newline at end of file diff --git a/samtranslator/internal/schema_source/schema.py b/samtranslator/internal/schema_source/schema.py index 3cf05c30e..cdf8a14b4 100644 --- a/samtranslator/internal/schema_source/schema.py +++ b/samtranslator/internal/schema_source/schema.py @@ -18,6 +18,8 @@ aws_serverless_graphqlapi, aws_serverless_httpapi, aws_serverless_layerversion, + aws_serverless_microvmimage, + aws_serverless_networkconnector, aws_serverless_simpletable, aws_serverless_statemachine, aws_serverless_websocketapi, @@ -31,15 +33,18 @@ class Globals(BaseModel): HttpApi: aws_serverless_httpapi.Globals | None WebSocketApi: aws_serverless_websocketapi.Globals | None SimpleTable: aws_serverless_simpletable.Globals | None + NetworkConnector: aws_serverless_networkconnector.Globals | None StateMachine: aws_serverless_statemachine.Globals | None LayerVersion: aws_serverless_layerversion.Globals | None CapacityProvider: aws_serverless_capacity_provider.Globals | None + MicrovmImage: aws_serverless_microvmimage.Globals | None Resources = Union[ aws_serverless_connector.Resource, aws_serverless_function.Resource, aws_serverless_simpletable.Resource, + aws_serverless_networkconnector.Resource, aws_serverless_statemachine.Resource, aws_serverless_layerversion.Resource, aws_serverless_api.Resource, @@ -48,6 +53,7 @@ class Globals(BaseModel): aws_serverless_application.Resource, aws_serverless_graphqlapi.Resource, aws_serverless_capacity_provider.Resource, + aws_serverless_microvmimage.Resource, ] diff --git a/samtranslator/model/microvm_image/__init__.py b/samtranslator/model/microvm_image/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/samtranslator/model/microvm_image/__init__.py @@ -0,0 +1 @@ + diff --git a/samtranslator/model/microvm_image/generators.py b/samtranslator/model/microvm_image/generators.py new file mode 100644 index 000000000..1c1b11b80 --- /dev/null +++ b/samtranslator/model/microvm_image/generators.py @@ -0,0 +1,193 @@ +""" +AWS::Serverless::MicroVMImage resource transformer +""" + +from typing import Any + +from samtranslator.intrinsics.resolver import IntrinsicsResolver +from samtranslator.model import Resource +from samtranslator.model.exceptions import InvalidResourceException +from samtranslator.model.iam import IAMRole, IAMRolePolicies +from samtranslator.model.intrinsics import fnGetAtt +from samtranslator.model.microvm_image.resources import LambdaMicroVMImage +from samtranslator.model.tags.resource_tagging import get_tag_list + +MICROVM_BUILD_SERVICE_PRINCIPAL = "lambda.amazonaws.com" + + +class MicroVMImageGenerator: + """ + Generator for Lambda MicroVMImage resources + """ + + def __init__( # noqa: PLR0913 + self, + logical_id: str, + name: Any, + code_uri: Any, + base_image_arn: Any, + intrinsics_resolver: IntrinsicsResolver | None = None, + build_role_arn: Any | None = None, + base_image_version: Any | None = None, + description: Any | None = None, + tags: dict[str, Any] | None = None, + logging: dict[str, Any] | None = None, + egress_network_connectors: list[Any] | None = None, + cpu_configurations: list[dict[str, Any]] | None = None, + resources: list[dict[str, Any]] | None = None, + additional_os_capabilities: list[str] | None = None, + hooks: dict[str, Any] | None = None, + environment_variables: dict[str, Any] | None = None, + depends_on: list[str] | None = None, + resource_attributes: dict[str, Any] | None = None, + passthrough_resource_attributes: dict[str, Any] | None = None, + ) -> None: + self.logical_id = logical_id + self.name = name + self.code_uri = code_uri + self.base_image_arn = base_image_arn + self.intrinsics_resolver = intrinsics_resolver + self.build_role_arn = build_role_arn + self.base_image_version = base_image_version + self.description = description + self.tags = tags + self.logging = logging + self.egress_network_connectors = egress_network_connectors + self.cpu_configurations = cpu_configurations + self.resources = resources + self.additional_os_capabilities = additional_os_capabilities + self.hooks = hooks + self.environment_variables = environment_variables + self.depends_on = depends_on + self.resource_attributes = resource_attributes + self.passthrough_resource_attributes = passthrough_resource_attributes + + def to_cloudformation(self) -> list[Resource]: + resources: list[Resource] = [] + + if not self.build_role_arn: + build_role = self._create_build_role() + resources.append(build_role) + self.build_role_arn = fnGetAtt(build_role.logical_id, "Arn") + + microvm_image = self._create_microvm_image() + resources.append(microvm_image) + + return resources + + def _create_microvm_image(self) -> LambdaMicroVMImage: + microvm_image = LambdaMicroVMImage( + self.logical_id, depends_on=self.depends_on, attributes=self.resource_attributes + ) + + microvm_image.Name = self.name + microvm_image.CodeArtifact = {"Uri": self.code_uri} + microvm_image.BaseImageArn = self.base_image_arn + microvm_image.BuildRoleArn = self.build_role_arn + microvm_image.BaseImageVersion = self.base_image_version + + microvm_image.Description = self.description or "" + + microvm_image.Tags = self._transform_tags(self.tags) + + microvm_image.Logging = self.logging or {} + + # Flattened fields (all required in CFN, inject empty defaults if not provided) + microvm_image.EgressNetworkConnectors = self.egress_network_connectors or [] + microvm_image.CpuConfigurations = self.cpu_configurations or [] + microvm_image.Resources = self.resources or [] + microvm_image.AdditionalOsCapabilities = self.additional_os_capabilities or [] + microvm_image.Hooks = self.hooks or {} + microvm_image.EnvironmentVariables = self._transform_environment_variables(self.environment_variables) + + if self.passthrough_resource_attributes: + for attr_name, attr_value in self.passthrough_resource_attributes.items(): + microvm_image.set_resource_attribute(attr_name, attr_value) + + return microvm_image + + def _create_build_role(self) -> IAMRole: + role_logical_id = f"{self.logical_id}BuildRole" + + assume_role_policy = IAMRolePolicies.construct_assume_role_policy_for_service_principal( + MICROVM_BUILD_SERVICE_PRINCIPAL + ) + + build_role = IAMRole(role_logical_id, attributes=self.passthrough_resource_attributes) + build_role.AssumeRolePolicyDocument = assume_role_policy + build_role.Policies = [ + { + "PolicyName": "MicrovmImageBuildPolicy", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["s3:GetObject"], + "Resource": self._build_s3_resource_arn(), + }, + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Resource": "*", + }, + ], + }, + } + ] + + build_role.Tags = self._transform_tags() + + return build_role + + def _build_s3_resource_arn(self) -> Any: + """ + Build the S3 resource ARN for the policy statement. + 1. Try to resolve CodeUri via intrinsics_resolver to get a literal string + 2. If literal s3:// URI → parse bucket and return scoped ARN + 3. Otherwise → use Fn::Split + Fn::Select to let CFN resolve at deploy time + """ + # Try resolving intrinsics to get a literal value + resolved = self.code_uri + if self.intrinsics_resolver and isinstance(self.code_uri, dict): + resolved = self.intrinsics_resolver.resolve_parameter_refs(self.code_uri) + + # If resolved to a literal s3:// URI, parse the bucket + if isinstance(resolved, str) and resolved.startswith("s3://"): + parts = resolved[len("s3://") :].split("/", 1) + bucket = parts[0] + if bucket: + return {"Fn::Sub": f"arn:${{AWS::Partition}}:s3:::{bucket}/*"} + raise InvalidResourceException( + self.logical_id, "CodeUri must be a valid S3 URI with a bucket name (e.g. s3://bucket/key.zip)." + ) + + # Otherwise, use Fn::Split to extract bucket at deploy time + return { + "Fn::Sub": [ + "arn:${AWS::Partition}:s3:::${Bucket}/*", + { + "Bucket": { + "Fn::Select": [ + 2, + {"Fn::Split": ["/", self.code_uri]}, + ] + } + }, + ] + } + + def _transform_tags(self, tags: dict[str, Any] | None = None) -> list[dict[str, str]]: + tags_dict = (tags or {}).copy() + tags_dict["lambda:createdBy"] = "SAM" + return get_tag_list(tags_dict) + + def _transform_environment_variables(self, env_vars: dict[str, Any] | None) -> list[dict[str, str]]: + """Convert EnvironmentVariables from map form to CFN array of {Key, Value}.""" + if not env_vars: + return [] + return [{"Key": k, "Value": v} for k, v in env_vars.items()] diff --git a/samtranslator/model/microvm_image/resources.py b/samtranslator/model/microvm_image/resources.py new file mode 100644 index 000000000..720fffa43 --- /dev/null +++ b/samtranslator/model/microvm_image/resources.py @@ -0,0 +1,47 @@ +""" +AWS::Lambda::MicrovmImage resource for SAM +""" + +from typing import Any + +from samtranslator.model import GeneratedProperty, Resource +from samtranslator.utils.types import Intrinsicable + + +class LambdaMicroVMImage(Resource): + """ + AWS::Lambda::MicrovmImage resource + """ + + resource_type = "AWS::Lambda::MicrovmImage" + property_types = { + "Name": GeneratedProperty(), + "CodeArtifact": GeneratedProperty(), + "BaseImageArn": GeneratedProperty(), + "BuildRoleArn": GeneratedProperty(), + "BaseImageVersion": GeneratedProperty(), + "Description": GeneratedProperty(), + "Tags": GeneratedProperty(), + "Logging": GeneratedProperty(), + "EgressNetworkConnectors": GeneratedProperty(), + "CpuConfigurations": GeneratedProperty(), + "Resources": GeneratedProperty(), + "AdditionalOsCapabilities": GeneratedProperty(), + "Hooks": GeneratedProperty(), + "EnvironmentVariables": GeneratedProperty(), + } + + Name: Intrinsicable[str] + CodeArtifact: dict[str, Any] + BaseImageArn: Intrinsicable[str] + BuildRoleArn: Intrinsicable[str] | None + BaseImageVersion: Intrinsicable[str] | None + Description: Intrinsicable[str] | None + Tags: list[dict[str, Any]] | None + Logging: dict[str, Any] | None + EgressNetworkConnectors: list[Any] | None + CpuConfigurations: list[dict[str, Any]] | None + Resources: list[dict[str, Any]] | None + AdditionalOsCapabilities: list[str] | None + Hooks: dict[str, Any] | None + EnvironmentVariables: list[dict[str, Any]] | None diff --git a/samtranslator/model/network_connector/__init__.py b/samtranslator/model/network_connector/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/samtranslator/model/network_connector/__init__.py @@ -0,0 +1 @@ + diff --git a/samtranslator/model/network_connector/generators.py b/samtranslator/model/network_connector/generators.py new file mode 100644 index 000000000..546de6b0e --- /dev/null +++ b/samtranslator/model/network_connector/generators.py @@ -0,0 +1,138 @@ +""" +AWS::Serverless::NetworkConnector resource transformer +""" + +from typing import Any + +from samtranslator.model import Resource +from samtranslator.model.iam import IAMRole, IAMRolePolicies +from samtranslator.model.intrinsics import fnGetAtt +from samtranslator.model.network_connector.resources import LambdaNetworkConnector +from samtranslator.model.tags.resource_tagging import get_tag_list + + +class NetworkConnectorGenerator: + """ + Generator for Lambda NetworkConnector resources + """ + + def __init__( # noqa: PLR0913 + self, + logical_id: str, + vpc_config: dict[str, Any], + name: Any | None = None, + operator_role: Any | None = None, + tags: dict[str, Any] | None = None, + depends_on: list[str] | None = None, + resource_attributes: dict[str, Any] | None = None, + passthrough_resource_attributes: dict[str, Any] | None = None, + ) -> None: + self.logical_id = logical_id + self.name = name + self.vpc_config = vpc_config + self.operator_role = operator_role + self.tags = tags + self.depends_on = depends_on + self.resource_attributes = resource_attributes + self.passthrough_resource_attributes = passthrough_resource_attributes + + def to_cloudformation(self) -> list[Resource]: + resources: list[Resource] = [] + + if not self.operator_role: + role = self._create_operator_role() + resources.append(role) + self.operator_role = fnGetAtt(role.logical_id, "Arn") + + connector = self._create_network_connector() + resources.append(connector) + + return resources + + def _create_network_connector(self) -> LambdaNetworkConnector: + connector = LambdaNetworkConnector( + self.logical_id, depends_on=self.depends_on, attributes=self.resource_attributes + ) + + if self.name: + connector.Name = self.name + + connector.Configuration = { + "VpcEgressConfiguration": { + **self.vpc_config, + "AssociatedComputeResourceTypes": ["MicroVm"], + } + } + connector.OperatorRole = self.operator_role + connector.Tags = self._transform_tags(self.tags) + + if self.passthrough_resource_attributes: + for attr_name, attr_value in self.passthrough_resource_attributes.items(): + connector.set_resource_attribute(attr_name, attr_value) + + return connector + + def _create_operator_role(self) -> IAMRole: + role_logical_id = f"{self.logical_id}OperatorRole" + + assume_role_policy = IAMRolePolicies.construct_assume_role_policy_for_service_principal("lambda.amazonaws.com") + + role = IAMRole(role_logical_id, attributes=self.passthrough_resource_attributes) + role.AssumeRolePolicyDocument = assume_role_policy + role.Policies = [ + { + "PolicyName": "NetworkConnectorOperatorPolicy", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AllowCreateEniInAnySubnet", + "Effect": "Allow", + "Action": "ec2:CreateNetworkInterface", + "Resource": {"Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*"}, + }, + { + "Sid": "AllowCreateEniWithSecurityGroups", + "Effect": "Allow", + "Action": "ec2:CreateNetworkInterface", + "Resource": {"Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*"}, + }, + { + "Sid": "AllowCreateEniWithLambdaTagKeys", + "Effect": "Allow", + "Action": "ec2:CreateNetworkInterface", + "Resource": {"Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*"}, + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId", + ] + } + }, + }, + { + "Sid": "TagENIOnCreate", + "Effect": "Allow", + "Action": "ec2:CreateTags", + "Resource": {"Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*"}, + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com", + } + }, + }, + ], + }, + } + ] + + role.Tags = self._transform_tags() + + return role + + def _transform_tags(self, tags: dict[str, Any] | None = None) -> list[dict[str, str]]: + tags_dict = (tags or {}).copy() + tags_dict["lambda:createdBy"] = "SAM" + return get_tag_list(tags_dict) diff --git a/samtranslator/model/network_connector/resources.py b/samtranslator/model/network_connector/resources.py new file mode 100644 index 000000000..e9aae3430 --- /dev/null +++ b/samtranslator/model/network_connector/resources.py @@ -0,0 +1,27 @@ +""" +AWS::Lambda::NetworkConnector resource for SAM +""" + +from typing import Any + +from samtranslator.model import GeneratedProperty, Resource +from samtranslator.utils.types import Intrinsicable + + +class LambdaNetworkConnector(Resource): + """ + AWS::Lambda::NetworkConnector resource + """ + + resource_type = "AWS::Lambda::NetworkConnector" + property_types = { + "Name": GeneratedProperty(), + "Configuration": GeneratedProperty(), + "OperatorRole": GeneratedProperty(), + "Tags": GeneratedProperty(), + } + + Name: Intrinsicable[str] | None + Configuration: dict[str, Any] + OperatorRole: Intrinsicable[str] | None + Tags: list[dict[str, Any]] | None diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index e36f57097..14a9434bc 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -39,6 +39,8 @@ aws_serverless_capacity_provider, aws_serverless_function, aws_serverless_graphqlapi, + aws_serverless_microvmimage, + aws_serverless_networkconnector, ) from samtranslator.internal.schema_source.common import PermissionsType, SamIntrinsicable from samtranslator.internal.types import GetManagedPolicyMap @@ -142,6 +144,8 @@ from .api.api_generator import ApiGenerator from .api.http_api_generator import HttpApiGenerator from .api.websocket_api_generator import WebSocketApiGenerator +from .microvm_image.generators import MicroVMImageGenerator +from .network_connector.generators import NetworkConnectorGenerator from .packagetype import IMAGE, ZIP from .s3_utils.uri_parser import construct_image_code_object, construct_s3_location_object from .tags.resource_tagging import get_tag_list @@ -1620,6 +1624,125 @@ def to_cloudformation(self, **kwargs: Any) -> list[Resource]: return resources +class SamNetworkConnector(SamResourceMacro): + """SAM NetworkConnector resource transformer""" + + resource_type = "AWS::Serverless::NetworkConnector" + property_types = { + "Name": Property(False, one_of(IS_STR, IS_DICT)), + "VpcConfig": Property(True, IS_DICT), + "OperatorRole": Property(False, one_of(IS_STR, IS_DICT)), + "Tags": Property(False, IS_DICT), + "PropagateTags": Property(False, IS_BOOL), + } + + Name: Intrinsicable[str] | None + VpcConfig: dict[str, Any] + OperatorRole: Intrinsicable[str] | None + Tags: dict[str, Any] | None + PropagateTags: bool | None + + __validation_rules__: list[Any] = [] + + @cw_timer + def to_cloudformation(self, **kwargs: Any) -> list[Resource]: + self.validate_before_transform( + schema_class=aws_serverless_networkconnector.Properties, + collect_all_errors=True, + ) + + generator = NetworkConnectorGenerator( + logical_id=self.logical_id, + name=self.Name, + vpc_config=self.VpcConfig, + operator_role=self.OperatorRole, + tags=self.Tags, + depends_on=self.depends_on, + resource_attributes=self.resource_attributes, + passthrough_resource_attributes=self.get_passthrough_resource_attributes(), + ) + + resources = generator.to_cloudformation() + self.propagate_tags_combine(resources, self.Tags, self.PropagateTags) + return resources + + +class SamMicroVMImage(SamResourceMacro): + """SAM MicrovmImage resource transformer""" + + resource_type = "AWS::Serverless::MicrovmImage" + property_types = { + "Name": Property(True, one_of(IS_STR, IS_DICT)), + "CodeUri": Property(True, one_of(IS_STR, IS_DICT)), + "BaseImageArn": Property(True, one_of(IS_STR, IS_DICT)), + "BuildRoleArn": Property(False, one_of(IS_STR, IS_DICT)), + "BaseImageVersion": Property(True, one_of(IS_STR, IS_DICT)), + "Description": Property(False, one_of(IS_STR, IS_DICT)), + "Tags": Property(False, IS_DICT), + "Logging": Property(False, IS_DICT), + "EgressNetworkConnectors": Property(False, IS_LIST), + "CpuConfigurations": Property(False, IS_LIST), + "Resources": Property(False, IS_LIST), + "AdditionalOsCapabilities": Property(False, IS_LIST), + "Hooks": Property(False, IS_DICT), + "EnvironmentVariables": Property(False, IS_DICT), + "PropagateTags": Property(False, IS_BOOL), + } + + Name: Intrinsicable[str] + CodeUri: Intrinsicable[str] + BaseImageArn: Intrinsicable[str] + BuildRoleArn: Intrinsicable[str] | None + BaseImageVersion: Intrinsicable[str] + Description: Intrinsicable[str] | None + Tags: dict[str, Any] | None + Logging: dict[str, Any] | None + EgressNetworkConnectors: list[Any] | None + CpuConfigurations: list[dict[str, Any]] | None + Resources: list[dict[str, Any]] | None + AdditionalOsCapabilities: list[str] | None + Hooks: dict[str, Any] | None + EnvironmentVariables: dict[str, Any] | None + PropagateTags: bool | None + + __validation_rules__: list[Any] = [] + + @cw_timer + def to_cloudformation(self, **kwargs: Any) -> list[Resource]: + self.validate_before_transform( + schema_class=aws_serverless_microvmimage.Properties, + collect_all_errors=True, + ) + + intrinsics_resolver = kwargs.get("intrinsics_resolver") + + generator = MicroVMImageGenerator( + logical_id=self.logical_id, + name=self.Name, + code_uri=self.CodeUri, + base_image_arn=self.BaseImageArn, + intrinsics_resolver=intrinsics_resolver, + build_role_arn=self.BuildRoleArn, + base_image_version=self.BaseImageVersion, + description=self.Description, + tags=self.Tags, + logging=self.Logging, + egress_network_connectors=self.EgressNetworkConnectors, + cpu_configurations=self.CpuConfigurations, + resources=self.Resources, + additional_os_capabilities=self.AdditionalOsCapabilities, + hooks=self.Hooks, + environment_variables=self.EnvironmentVariables, + depends_on=self.depends_on, + resource_attributes=self.resource_attributes, + passthrough_resource_attributes=self.get_passthrough_resource_attributes(), + ) + + resources = generator.to_cloudformation() + self.propagate_tags_combine(resources, self.Tags, self.PropagateTags) + return resources + + class SamApi(SamResourceMacro): """SAM rest API macro.""" diff --git a/samtranslator/plugins/globals/globals.py b/samtranslator/plugins/globals/globals.py index bce449604..e1603e547 100644 --- a/samtranslator/plugins/globals/globals.py +++ b/samtranslator/plugins/globals/globals.py @@ -116,6 +116,25 @@ class Globals: "PropagateTags", "ManagedResourceTags", ], + SamResourceType.NetworkConnector.value: [ + "OperatorRole", + "Tags", + "PropagateTags", + ], + SamResourceType.MicroVMImage.value: [ + "BuildRoleArn", + "BaseImageArn", + "BaseImageVersion", + "Logging", + "EgressNetworkConnectors", + "CpuConfigurations", + "Resources", + "AdditionalOsCapabilities", + "Hooks", + "EnvironmentVariables", + "Tags", + "PropagateTags", + ], SamResourceType.WebSocketApi.value: [ "AccessLogSettings", "ApiKeySelectionExpression", diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index be0039ccb..8d359c70d 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -364917,6 +364917,37 @@ "title": "CapacityProviderConfig", "type": "object" }, + "CloudWatchLogging": { + "additionalProperties": false, + "properties": { + "LogGroup": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "LogGroup" + }, + "LogStream": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "LogStream" + } + }, + "title": "CloudWatchLogging", + "type": "object" + }, "CloudWatchLogsEvent": { "additionalProperties": false, "properties": { @@ -365210,6 +365241,31 @@ "title": "Cors", "type": "object" }, + "CpuConfiguration": { + "additionalProperties": false, + "properties": { + "Architecture": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ARM_64" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Architecture" + } + }, + "required": [ + "Architecture" + ], + "title": "CpuConfiguration", + "type": "object" + }, "CustomResource": { "additionalProperties": false, "properties": { @@ -365338,7 +365394,7 @@ "Hooks": { "allOf": [ { - "$ref": "#/definitions/Hooks" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_function__Hooks" } ], "markdownDescription": "Validation Lambda functions that are run before and after traffic shifting. \n*Type*: [Hooks](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-hooks.html) \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", @@ -366266,37 +366322,6 @@ "title": "FunctionUrlConfig", "type": "object" }, - "Hooks": { - "additionalProperties": false, - "properties": { - "PostTraffic": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ], - "markdownDescription": "Lambda function that is run after traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", - "title": "PostTraffic" - }, - "PreTraffic": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ], - "markdownDescription": "Lambda function that is run before traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", - "title": "PreTraffic" - } - }, - "title": "Hooks", - "type": "object" - }, "HttpApiAuth": { "additionalProperties": false, "properties": { @@ -367121,22 +367146,6 @@ "title": "Location", "type": "object" }, - "Logging": { - "additionalProperties": false, - "properties": { - "CloudWatchLogsRoleArn": { - "$ref": "#/definitions/PassThroughProp" - }, - "ExcludeVerboseContent": { - "$ref": "#/definitions/PassThroughProp" - }, - "FieldLogLevel": { - "$ref": "#/definitions/PassThroughProp" - } - }, - "title": "Logging", - "type": "object" - }, "MQEvent": { "additionalProperties": false, "properties": { @@ -367479,6 +367488,188 @@ "title": "ManagedResourceTags", "type": "object" }, + "MicrovmHooks": { + "additionalProperties": false, + "properties": { + "Resume": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Resume" + }, + "ResumeTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "ResumeTimeoutInSeconds" + }, + "Run": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Run" + }, + "RunTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "RunTimeoutInSeconds" + }, + "Suspend": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Suspend" + }, + "SuspendTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "SuspendTimeoutInSeconds" + }, + "Terminate": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Terminate" + }, + "TerminateTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "TerminateTimeoutInSeconds" + } + }, + "title": "MicrovmHooks", + "type": "object" + }, + "MicrovmImageHooks": { + "additionalProperties": false, + "properties": { + "Ready": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Ready" + }, + "ReadyTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "ReadyTimeoutInSeconds" + }, + "Validate": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Validate" + }, + "ValidateTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "ValidateTimeoutInSeconds" + } + }, + "title": "MicrovmImageHooks", + "type": "object" + }, "OAuth2Authorizer": { "additionalProperties": false, "properties": { @@ -367848,6 +368039,28 @@ "title": "ResourceReference", "type": "object" }, + "ResourceSpec": { + "additionalProperties": false, + "properties": { + "MinimumMemoryInMiB": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "MinimumMemoryInMiB" + } + }, + "required": [ + "MinimumMemoryInMiB" + ], + "title": "ResourceSpec", + "type": "object" + }, "Runtime": { "additionalProperties": false, "properties": { @@ -368679,61 +368892,7 @@ "title": "UserPoolConfig", "type": "object" }, - "VpcConfig": { - "additionalProperties": false, - "properties": { - "SecurityGroupIds": { - "anyOf": [ - { - "type": "object" - }, - { - "items": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ] - }, - "type": "array" - } - ], - "markdownDescription": "A list of security group IDs to associate with the EC2 instances. If not specified, the default security group for the VPC will be used. \n*Type*: List \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SecurityGroupIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-securitygroupids) property of [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", - "title": "SecurityGroupIds" - }, - "SubnetIds": { - "anyOf": [ - { - "type": "object" - }, - { - "items": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ] - }, - "type": "array" - } - ], - "markdownDescription": "A list of subnet IDs where EC2 instances will be launched. At least one subnet must be specified. \n*Type*: List \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`SubnetIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-subnetids) property of `[VpcConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) ` of an `AWS::Lambda::CapacityProvider` resource.", - "title": "SubnetIds" - } - }, - "required": [ - "SubnetIds" - ], - "title": "VpcConfig", - "type": "object" - }, - "WebSocketApiRoute": { + "WebSocketApiRoute": { "additionalProperties": false, "properties": { "ApiKeyRequired": { @@ -368836,6 +368995,12 @@ "LayerVersion": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_layerversion__Globals" }, + "MicrovmImage": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Globals" + }, + "NetworkConnector": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__Globals" + }, "SimpleTable": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Globals" }, @@ -369877,7 +370042,7 @@ "VpcConfig": { "allOf": [ { - "$ref": "#/definitions/VpcConfig" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_capacity_provider__VpcConfig" } ], "markdownDescription": "The VPC configuration for the capacity provider. Specifies the VPC subnets and security groups where Amazon EC2 instances will be launched. \n*Type*: [VpcConfig](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-capacityprovider-vpcconfig.html) \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", @@ -369949,7 +370114,7 @@ "VpcConfig": { "allOf": [ { - "$ref": "#/definitions/VpcConfig" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_capacity_provider__VpcConfig" } ], "markdownDescription": "The VPC configuration for the capacity provider. Specifies the VPC subnets and security groups where Amazon EC2 instances will be launched. \n*Type*: [VpcConfig](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-capacityprovider-vpcconfig.html) \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", @@ -370012,6 +370177,60 @@ "title": "Resource", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_capacity_provider__VpcConfig": { + "additionalProperties": false, + "properties": { + "SecurityGroupIds": { + "anyOf": [ + { + "type": "object" + }, + { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "type": "array" + } + ], + "markdownDescription": "A list of security group IDs to associate with the EC2 instances. If not specified, the default security group for the VPC will be used. \n*Type*: List \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SecurityGroupIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-securitygroupids) property of [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", + "title": "SecurityGroupIds" + }, + "SubnetIds": { + "anyOf": [ + { + "type": "object" + }, + { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "type": "array" + } + ], + "markdownDescription": "A list of subnet IDs where EC2 instances will be launched. At least one subnet must be specified. \n*Type*: List \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`SubnetIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-subnetids) property of `[VpcConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) ` of an `AWS::Lambda::CapacityProvider` resource.", + "title": "SubnetIds" + } + }, + "required": [ + "SubnetIds" + ], + "title": "VpcConfig", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_connector__Properties": { "additionalProperties": false, "properties": { @@ -370753,6 +370972,37 @@ "title": "Globals", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_function__Hooks": { + "additionalProperties": false, + "properties": { + "PostTraffic": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "Lambda function that is run after traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", + "title": "PostTraffic" + }, + "PreTraffic": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "Lambda function that is run before traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", + "title": "PreTraffic" + } + }, + "title": "Hooks", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_function__Properties": { "additionalProperties": false, "properties": { @@ -371678,6 +371928,22 @@ "title": "Auth", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Logging": { + "additionalProperties": false, + "properties": { + "CloudWatchLogsRoleArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "ExcludeVerboseContent": { + "$ref": "#/definitions/PassThroughProp" + }, + "FieldLogLevel": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "title": "Logging", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Properties": { "additionalProperties": false, "properties": { @@ -371739,7 +372005,7 @@ "Logging": { "anyOf": [ { - "$ref": "#/definitions/Logging" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Logging" }, { "type": "boolean" @@ -372467,96 +372733,686 @@ "title": "Resource", "type": "object" }, - "samtranslator__internal__schema_source__aws_serverless_simpletable__Globals": { - "additionalProperties": false, - "properties": { - "SSESpecification": { - "$ref": "#/definitions/AWS::DynamoDB::Table.SSESpecification", - "markdownDescription": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", - "title": "SSESpecification" - } - }, - "title": "Globals", - "type": "object" - }, - "samtranslator__internal__schema_source__aws_serverless_simpletable__Properties": { + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Globals": { "additionalProperties": false, "properties": { - "PointInTimeRecoverySpecification": { - "$ref": "#/definitions/AWS::DynamoDB::Table.PointInTimeRecoverySpecification", - "markdownDescription": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", - "title": "ProvisionedThroughput" + "AdditionalOsCapabilities": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ALL" + ], + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "AdditionalOsCapabilities", + "type": "array" }, - "PrimaryKey": { - "allOf": [ + "BaseImageArn": { + "anyOf": [ { - "$ref": "#/definitions/PrimaryKey" + "type": "object" + }, + { + "type": "string" } ], - "markdownDescription": "Attribute name and type to be used as the table's primary key. If not provided, the primary key will be a `String` with a value of `id`. \nThe value of this property cannot be modified after this resource is created.\n*Type*: [PrimaryKeyObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-primarykeyobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", - "title": "PrimaryKey" - }, - "ProvisionedThroughput": { - "$ref": "#/definitions/AWS::DynamoDB::Table.ProvisionedThroughput", - "markdownDescription": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", - "title": "ProvisionedThroughput" - }, - "SSESpecification": { - "$ref": "#/definitions/AWS::DynamoDB::Table.SSESpecification", - "markdownDescription": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", - "title": "SSESpecification" - }, - "TableName": { - "markdownDescription": "Name for the DynamoDB Table. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`TableName`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tablename) property of an `AWS::DynamoDB::Table` resource.", - "title": "TableName", - "type": "string" - }, - "Tags": { - "markdownDescription": "A map (string to string) that specifies the tags to be added to this SimpleTable. For details about valid keys and values for tags, see [Resource tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html) in the *AWS CloudFormation User Guide*. \n*Type*: Map \n*Required*: No \n*CloudFormation compatibility*: This property is similar to the [`Tags`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tags) property of an `AWS::DynamoDB::Table` resource. The Tags property in SAM consists of Key:Value pairs; in CloudFormation it consists of a list of Tag objects.", - "title": "Tags", - "type": "object" - } - }, - "title": "Properties", - "type": "object" - }, - "samtranslator__internal__schema_source__aws_serverless_simpletable__Resource": { - "additionalProperties": false, - "properties": { - "Condition": { - "$ref": "#/definitions/PassThroughProp" - }, - "Connectors": { - "additionalProperties": { - "$ref": "#/definitions/EmbeddedConnector" - }, - "title": "Connectors", - "type": "object" - }, - "DeletionPolicy": { - "$ref": "#/definitions/PassThroughProp" - }, - "DependsOn": { - "$ref": "#/definitions/PassThroughProp" + "markdownDescription": "TODO", + "title": "BaseImageArn" }, - "IgnoreGlobals": { + "BaseImageVersion": { "anyOf": [ { - "type": "string" + "type": "object" }, { - "items": { - "type": "string" - }, - "type": "array" + "type": "string" } ], - "title": "Ignoreglobals" + "markdownDescription": "TODO", + "title": "BaseImageVersion" }, - "Metadata": { - "$ref": "#/definitions/PassThroughProp" + "BuildRoleArn": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BuildRoleArn" }, - "Properties": { + "CpuConfigurations": { + "items": { + "$ref": "#/definitions/CpuConfiguration" + }, + "markdownDescription": "TODO", + "title": "CpuConfigurations", + "type": "array" + }, + "EgressNetworkConnectors": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "EgressNetworkConnectors", + "type": "array" + }, + "EnvironmentVariables": { + "markdownDescription": "TODO", + "title": "EnvironmentVariables", + "type": "object" + }, + "Hooks": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Hooks" + } + ], + "markdownDescription": "TODO", + "title": "Hooks" + }, + "Logging": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Logging" + } + ], + "markdownDescription": "TODO", + "title": "Logging" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Resources": { + "items": { + "$ref": "#/definitions/ResourceSpec" + }, + "markdownDescription": "TODO", + "title": "Resources", + "type": "array" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + } + }, + "title": "Globals", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Hooks": { + "additionalProperties": false, + "properties": { + "MicrovmHooks": { + "allOf": [ + { + "$ref": "#/definitions/MicrovmHooks" + } + ], + "markdownDescription": "TODO", + "title": "MicrovmHooks" + }, + "MicrovmImageHooks": { + "allOf": [ + { + "$ref": "#/definitions/MicrovmImageHooks" + } + ], + "markdownDescription": "TODO", + "title": "MicrovmImageHooks" + }, + "Port": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "Port" + } + }, + "title": "Hooks", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Logging": { + "additionalProperties": false, + "properties": { + "CloudWatch": { + "allOf": [ + { + "$ref": "#/definitions/CloudWatchLogging" + } + ], + "markdownDescription": "TODO", + "title": "CloudWatch" + }, + "Disabled": { + "markdownDescription": "TODO", + "title": "Disabled", + "type": "boolean" + } + }, + "title": "Logging", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Properties": { + "additionalProperties": false, + "properties": { + "AdditionalOsCapabilities": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ALL" + ], + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "AdditionalOsCapabilities", + "type": "array" + }, + "BaseImageArn": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BaseImageArn" + }, + "BaseImageVersion": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BaseImageVersion" + }, + "BuildRoleArn": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BuildRoleArn" + }, + "CodeUri": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "CodeUri" + }, + "CpuConfigurations": { + "items": { + "$ref": "#/definitions/CpuConfiguration" + }, + "markdownDescription": "TODO", + "title": "CpuConfigurations", + "type": "array" + }, + "Description": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Description" + }, + "EgressNetworkConnectors": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "EgressNetworkConnectors", + "type": "array" + }, + "EnvironmentVariables": { + "markdownDescription": "TODO", + "title": "EnvironmentVariables", + "type": "object" + }, + "Hooks": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Hooks" + } + ], + "markdownDescription": "TODO", + "title": "Hooks" + }, + "Logging": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Logging" + } + ], + "markdownDescription": "TODO", + "title": "Logging" + }, + "Name": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Name" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Resources": { + "items": { + "$ref": "#/definitions/ResourceSpec" + }, + "markdownDescription": "TODO", + "title": "Resources", + "type": "array" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + } + }, + "required": [ + "Name", + "CodeUri", + "BaseImageArn", + "BaseImageVersion" + ], + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Resource": { + "additionalProperties": false, + "properties": { + "Condition": { + "$ref": "#/definitions/PassThroughProp" + }, + "DeletionPolicy": { + "$ref": "#/definitions/PassThroughProp" + }, + "DependsOn": { + "$ref": "#/definitions/PassThroughProp" + }, + "IgnoreGlobals": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "title": "Ignoreglobals" + }, + "Metadata": { + "$ref": "#/definitions/PassThroughProp" + }, + "Properties": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Properties" + }, + "Type": { + "enum": [ + "AWS::Serverless::MicrovmImage" + ], + "title": "Type", + "type": "string" + }, + "UpdateReplacePolicy": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Type", + "Properties" + ], + "title": "Resource", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__Globals": { + "additionalProperties": false, + "properties": { + "OperatorRole": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "OperatorRole" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + } + }, + "title": "Globals", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__Properties": { + "additionalProperties": false, + "properties": { + "Name": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Name" + }, + "OperatorRole": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "OperatorRole" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + }, + "VpcConfig": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__VpcConfig" + } + ], + "markdownDescription": "TODO", + "title": "VpcConfig" + } + }, + "required": [ + "VpcConfig" + ], + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__Resource": { + "additionalProperties": false, + "properties": { + "Condition": { + "$ref": "#/definitions/PassThroughProp" + }, + "DeletionPolicy": { + "$ref": "#/definitions/PassThroughProp" + }, + "DependsOn": { + "$ref": "#/definitions/PassThroughProp" + }, + "IgnoreGlobals": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "title": "Ignoreglobals" + }, + "Metadata": { + "$ref": "#/definitions/PassThroughProp" + }, + "Properties": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__Properties" + }, + "Type": { + "enum": [ + "AWS::Serverless::NetworkConnector" + ], + "title": "Type", + "type": "string" + }, + "UpdateReplacePolicy": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Type", + "Properties" + ], + "title": "Resource", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__VpcConfig": { + "additionalProperties": false, + "properties": { + "NetworkProtocol": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "IPv4", + "DualStack" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "NetworkProtocol" + }, + "SecurityGroupIds": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "SecurityGroupIds", + "type": "array" + }, + "SubnetIds": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "SubnetIds", + "type": "array" + } + }, + "required": [ + "SubnetIds", + "SecurityGroupIds", + "NetworkProtocol" + ], + "title": "VpcConfig", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_simpletable__Globals": { + "additionalProperties": false, + "properties": { + "SSESpecification": { + "$ref": "#/definitions/AWS::DynamoDB::Table.SSESpecification", + "markdownDescription": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", + "title": "SSESpecification" + } + }, + "title": "Globals", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_simpletable__Properties": { + "additionalProperties": false, + "properties": { + "PointInTimeRecoverySpecification": { + "$ref": "#/definitions/AWS::DynamoDB::Table.PointInTimeRecoverySpecification", + "markdownDescription": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", + "title": "ProvisionedThroughput" + }, + "PrimaryKey": { + "allOf": [ + { + "$ref": "#/definitions/PrimaryKey" + } + ], + "markdownDescription": "Attribute name and type to be used as the table's primary key. If not provided, the primary key will be a `String` with a value of `id`. \nThe value of this property cannot be modified after this resource is created.\n*Type*: [PrimaryKeyObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-primarykeyobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", + "title": "PrimaryKey" + }, + "ProvisionedThroughput": { + "$ref": "#/definitions/AWS::DynamoDB::Table.ProvisionedThroughput", + "markdownDescription": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", + "title": "ProvisionedThroughput" + }, + "SSESpecification": { + "$ref": "#/definitions/AWS::DynamoDB::Table.SSESpecification", + "markdownDescription": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", + "title": "SSESpecification" + }, + "TableName": { + "markdownDescription": "Name for the DynamoDB Table. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`TableName`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tablename) property of an `AWS::DynamoDB::Table` resource.", + "title": "TableName", + "type": "string" + }, + "Tags": { + "markdownDescription": "A map (string to string) that specifies the tags to be added to this SimpleTable. For details about valid keys and values for tags, see [Resource tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html) in the *AWS CloudFormation User Guide*. \n*Type*: Map \n*Required*: No \n*CloudFormation compatibility*: This property is similar to the [`Tags`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tags) property of an `AWS::DynamoDB::Table` resource. The Tags property in SAM consists of Key:Value pairs; in CloudFormation it consists of a list of Tag objects.", + "title": "Tags", + "type": "object" + } + }, + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_simpletable__Resource": { + "additionalProperties": false, + "properties": { + "Condition": { + "$ref": "#/definitions/PassThroughProp" + }, + "Connectors": { + "additionalProperties": { + "$ref": "#/definitions/EmbeddedConnector" + }, + "title": "Connectors", + "type": "object" + }, + "DeletionPolicy": { + "$ref": "#/definitions/PassThroughProp" + }, + "DependsOn": { + "$ref": "#/definitions/PassThroughProp" + }, + "IgnoreGlobals": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "title": "Ignoreglobals" + }, + "Metadata": { + "$ref": "#/definitions/PassThroughProp" + }, + "Properties": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Properties" }, "Type": { @@ -374019,6 +374875,9 @@ { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Resource" }, + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__Resource" + }, { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_statemachine__Resource" }, @@ -374043,6 +374902,9 @@ { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_capacity_provider__Resource" }, + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Resource" + }, { "$ref": "#/definitions/AWS::ACMPCA::Certificate" }, diff --git a/samtranslator/sdk/resource.py b/samtranslator/sdk/resource.py index 4197a65d5..d61f2a05a 100644 --- a/samtranslator/sdk/resource.py +++ b/samtranslator/sdk/resource.py @@ -71,6 +71,8 @@ class SamResourceType(Enum): WebSocketApi = "AWS::Serverless::WebSocketApi" StateMachine = "AWS::Serverless::StateMachine" CapacityProvider = "AWS::Serverless::CapacityProvider" + MicroVMImage = "AWS::Serverless::MicrovmImage" + NetworkConnector = "AWS::Serverless::NetworkConnector" @classmethod def has_value(cls, value: str) -> bool: diff --git a/samtranslator/translator/verify_logical_id.py b/samtranslator/translator/verify_logical_id.py index 89177ea24..7da2c7911 100644 --- a/samtranslator/translator/verify_logical_id.py +++ b/samtranslator/translator/verify_logical_id.py @@ -7,6 +7,8 @@ "AWS::Lambda::Function": "AWS::Serverless::Function", "AWS::Lambda::LayerVersion": "AWS::Serverless::LayerVersion", "AWS::Lambda::CapacityProvider": "AWS::Serverless::CapacityProvider", + "AWS::Lambda::MicrovmImage": "AWS::Serverless::MicrovmImage", + "AWS::Lambda::NetworkConnector": "AWS::Serverless::NetworkConnector", "AWS::ApiGateway::RestApi": "AWS::Serverless::Api", "AWS::ApiGatewayV2::Api": ["AWS::Serverless::HttpApi", "AWS::Serverless::WebSocketApi"], "AWS::S3::Bucket": "AWS::S3::Bucket", diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index cdc270736..0070efa21 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -342,6 +342,37 @@ "title": "CapacityProviderConfig", "type": "object" }, + "CloudWatchLogging": { + "additionalProperties": false, + "properties": { + "LogGroup": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "LogGroup" + }, + "LogStream": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "LogStream" + } + }, + "title": "CloudWatchLogging", + "type": "object" + }, "CloudWatchLogsEvent": { "additionalProperties": false, "properties": { @@ -671,6 +702,31 @@ "title": "Cors", "type": "object" }, + "CpuConfiguration": { + "additionalProperties": false, + "properties": { + "Architecture": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ARM_64" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Architecture" + } + }, + "required": [ + "Architecture" + ], + "title": "CpuConfiguration", + "type": "object" + }, "DataSources": { "additionalProperties": false, "properties": { @@ -773,7 +829,7 @@ "Hooks": { "allOf": [ { - "$ref": "#/definitions/Hooks" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_function__Hooks" } ], "markdownDescription": "Validation Lambda functions that are run before and after traffic shifting. \n*Type*: [Hooks](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-hooks.html) \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", @@ -1758,37 +1814,6 @@ "title": "FunctionUrlConfig", "type": "object" }, - "Hooks": { - "additionalProperties": false, - "properties": { - "PostTraffic": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ], - "markdownDescription": "Lambda function that is run after traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", - "title": "PostTraffic" - }, - "PreTraffic": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ], - "markdownDescription": "Lambda function that is run before traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", - "title": "PreTraffic" - } - }, - "title": "Hooks", - "type": "object" - }, "HttpApiAuth": { "additionalProperties": false, "properties": { @@ -2627,22 +2652,6 @@ "title": "Location", "type": "object" }, - "Logging": { - "additionalProperties": false, - "properties": { - "CloudWatchLogsRoleArn": { - "$ref": "#/definitions/PassThroughProp" - }, - "ExcludeVerboseContent": { - "$ref": "#/definitions/PassThroughProp" - }, - "FieldLogLevel": { - "$ref": "#/definitions/PassThroughProp" - } - }, - "title": "Logging", - "type": "object" - }, "MQEvent": { "additionalProperties": false, "properties": { @@ -3041,6 +3050,188 @@ "title": "ManagedResourceTags", "type": "object" }, + "MicrovmHooks": { + "additionalProperties": false, + "properties": { + "Resume": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Resume" + }, + "ResumeTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "ResumeTimeoutInSeconds" + }, + "Run": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Run" + }, + "RunTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "RunTimeoutInSeconds" + }, + "Suspend": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Suspend" + }, + "SuspendTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "SuspendTimeoutInSeconds" + }, + "Terminate": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Terminate" + }, + "TerminateTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "TerminateTimeoutInSeconds" + } + }, + "title": "MicrovmHooks", + "type": "object" + }, + "MicrovmImageHooks": { + "additionalProperties": false, + "properties": { + "Ready": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Ready" + }, + "ReadyTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "ReadyTimeoutInSeconds" + }, + "Validate": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ENABLED", + "DISABLED" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Validate" + }, + "ValidateTimeoutInSeconds": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "ValidateTimeoutInSeconds" + } + }, + "title": "MicrovmImageHooks", + "type": "object" + }, "OAuth2Authorizer": { "additionalProperties": false, "properties": { @@ -3341,6 +3532,28 @@ "title": "ResourceReference", "type": "object" }, + "ResourceSpec": { + "additionalProperties": false, + "properties": { + "MinimumMemoryInMiB": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "MinimumMemoryInMiB" + } + }, + "required": [ + "MinimumMemoryInMiB" + ], + "title": "ResourceSpec", + "type": "object" + }, "Runtime": { "additionalProperties": false, "properties": { @@ -4196,65 +4409,11 @@ "title": "UserPoolConfig", "type": "object" }, - "VpcConfig": { + "WebSocketApiRoute": { "additionalProperties": false, "properties": { - "SecurityGroupIds": { - "anyOf": [ - { - "type": "object" - }, - { - "items": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ] - }, - "type": "array" - } - ], - "markdownDescription": "A list of security group IDs to associate with the EC2 instances. If not specified, the default security group for the VPC will be used. \n*Type*: List \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SecurityGroupIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-securitygroupids) property of [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", - "title": "SecurityGroupIds" - }, - "SubnetIds": { - "anyOf": [ - { - "type": "object" - }, - { - "items": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ] - }, - "type": "array" - } - ], - "markdownDescription": "A list of subnet IDs where EC2 instances will be launched. At least one subnet must be specified. \n*Type*: List \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`SubnetIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-subnetids) property of `[VpcConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) ` of an `AWS::Lambda::CapacityProvider` resource.", - "title": "SubnetIds" - } - }, - "required": [ - "SubnetIds" - ], - "title": "VpcConfig", - "type": "object" - }, - "WebSocketApiRoute": { - "additionalProperties": false, - "properties": { - "ApiKeyRequired": { - "allOf": [ + "ApiKeyRequired": { + "allOf": [ { "$ref": "#/definitions/PassThroughProp" } @@ -4353,6 +4512,12 @@ "LayerVersion": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_layerversion__Globals" }, + "MicrovmImage": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Globals" + }, + "NetworkConnector": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__Globals" + }, "SimpleTable": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Globals" }, @@ -6006,7 +6171,7 @@ "VpcConfig": { "allOf": [ { - "$ref": "#/definitions/VpcConfig" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_capacity_provider__VpcConfig" } ], "markdownDescription": "The VPC configuration for the capacity provider. Specifies the VPC subnets and security groups where Amazon EC2 instances will be launched. \n*Type*: [VpcConfig](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-capacityprovider-vpcconfig.html) \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", @@ -6106,7 +6271,7 @@ "VpcConfig": { "allOf": [ { - "$ref": "#/definitions/VpcConfig" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_capacity_provider__VpcConfig" } ], "markdownDescription": "The VPC configuration for the capacity provider. Specifies the VPC subnets and security groups where Amazon EC2 instances will be launched. \n*Type*: [VpcConfig](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-capacityprovider-vpcconfig.html) \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", @@ -6169,6 +6334,60 @@ "title": "Resource", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_capacity_provider__VpcConfig": { + "additionalProperties": false, + "properties": { + "SecurityGroupIds": { + "anyOf": [ + { + "type": "object" + }, + { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "type": "array" + } + ], + "markdownDescription": "A list of security group IDs to associate with the EC2 instances. If not specified, the default security group for the VPC will be used. \n*Type*: List \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SecurityGroupIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-securitygroupids) property of [`VpcConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) property of an `AWS::Lambda::CapacityProvider` resource.", + "title": "SecurityGroupIds" + }, + "SubnetIds": { + "anyOf": [ + { + "type": "object" + }, + { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "type": "array" + } + ], + "markdownDescription": "A list of subnet IDs where EC2 instances will be launched. At least one subnet must be specified. \n*Type*: List \n*Required*: Yes \n*CloudFormation compatibility*: This property is passed directly to the [`SubnetIds`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-capacityprovider-capacityprovidervpcconfig.html#cfn-lambda-capacityprovider-capacityprovidervpcconfig-subnetids) property of `[VpcConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-capacityprovider.html#cfn-lambda-capacityprovider-vpcconfig) ` of an `AWS::Lambda::CapacityProvider` resource.", + "title": "SubnetIds" + } + }, + "required": [ + "SubnetIds" + ], + "title": "VpcConfig", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_connector__Properties": { "additionalProperties": false, "properties": { @@ -7113,6 +7332,37 @@ "title": "Globals", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_function__Hooks": { + "additionalProperties": false, + "properties": { + "PostTraffic": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "Lambda function that is run after traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", + "title": "PostTraffic" + }, + "PreTraffic": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "Lambda function that is run before traffic shifting. \n*Type*: String \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", + "title": "PreTraffic" + } + }, + "title": "Hooks", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_function__Properties": { "additionalProperties": false, "properties": { @@ -8325,6 +8575,22 @@ "title": "Auth", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Logging": { + "additionalProperties": false, + "properties": { + "CloudWatchLogsRoleArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "ExcludeVerboseContent": { + "$ref": "#/definitions/PassThroughProp" + }, + "FieldLogLevel": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "title": "Logging", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Properties": { "additionalProperties": false, "properties": { @@ -8386,7 +8652,7 @@ "Logging": { "anyOf": [ { - "$ref": "#/definitions/Logging" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Logging" }, { "type": "boolean" @@ -9164,82 +9430,672 @@ "title": "Resource", "type": "object" }, - "samtranslator__internal__schema_source__aws_serverless_simpletable__Globals": { + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Globals": { "additionalProperties": false, "properties": { - "SSESpecification": { - "__samPassThrough": { - "markdownDescriptionOverride": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", - "schemaPath": [ - "definitions", - "AWS::DynamoDB::Table", - "properties", - "Properties", - "properties", - "SSESpecification" + "AdditionalOsCapabilities": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ALL" + ], + "type": "string" + } ] }, - "allOf": [ + "markdownDescription": "TODO", + "title": "AdditionalOsCapabilities", + "type": "array" + }, + "BaseImageArn": { + "anyOf": [ { - "$ref": "#/definitions/PassThroughProp" + "type": "object" + }, + { + "type": "string" } ], - "title": "SSESpecification" - } - }, - "title": "Globals", - "type": "object" - }, - "samtranslator__internal__schema_source__aws_serverless_simpletable__Properties": { - "additionalProperties": false, - "properties": { - "PointInTimeRecoverySpecification": { - "__samPassThrough": { - "markdownDescriptionOverride": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", - "schemaPath": [ - "definitions", - "AWS::DynamoDB::Table", - "properties", - "Properties", - "properties", - "PointInTimeRecoverySpecification" - ] - }, - "allOf": [ + "markdownDescription": "TODO", + "title": "BaseImageArn" + }, + "BaseImageVersion": { + "anyOf": [ { - "$ref": "#/definitions/PassThroughProp" + "type": "object" + }, + { + "type": "string" } ], - "title": "ProvisionedThroughput" + "markdownDescription": "TODO", + "title": "BaseImageVersion" }, - "PrimaryKey": { - "allOf": [ + "BuildRoleArn": { + "anyOf": [ { - "$ref": "#/definitions/PrimaryKey" + "type": "object" + }, + { + "type": "string" } ], - "markdownDescription": "Attribute name and type to be used as the table's primary key. If not provided, the primary key will be a `String` with a value of `id`. \nThe value of this property cannot be modified after this resource is created.\n*Type*: [PrimaryKeyObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-primarykeyobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", - "title": "PrimaryKey" + "markdownDescription": "TODO", + "title": "BuildRoleArn" }, - "ProvisionedThroughput": { - "__samPassThrough": { - "markdownDescriptionOverride": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", - "schemaPath": [ - "definitions", - "AWS::DynamoDB::Table", - "properties", - "Properties", - "properties", - "ProvisionedThroughput" + "CpuConfigurations": { + "items": { + "$ref": "#/definitions/CpuConfiguration" + }, + "markdownDescription": "TODO", + "title": "CpuConfigurations", + "type": "array" + }, + "EgressNetworkConnectors": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } ] }, + "markdownDescription": "TODO", + "title": "EgressNetworkConnectors", + "type": "array" + }, + "EnvironmentVariables": { + "markdownDescription": "TODO", + "title": "EnvironmentVariables", + "type": "object" + }, + "Hooks": { "allOf": [ { - "$ref": "#/definitions/PassThroughProp" + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Hooks" } ], - "title": "ProvisionedThroughput" - }, + "markdownDescription": "TODO", + "title": "Hooks" + }, + "Logging": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Logging" + } + ], + "markdownDescription": "TODO", + "title": "Logging" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Resources": { + "items": { + "$ref": "#/definitions/ResourceSpec" + }, + "markdownDescription": "TODO", + "title": "Resources", + "type": "array" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + } + }, + "title": "Globals", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Hooks": { + "additionalProperties": false, + "properties": { + "MicrovmHooks": { + "allOf": [ + { + "$ref": "#/definitions/MicrovmHooks" + } + ], + "markdownDescription": "TODO", + "title": "MicrovmHooks" + }, + "MicrovmImageHooks": { + "allOf": [ + { + "$ref": "#/definitions/MicrovmImageHooks" + } + ], + "markdownDescription": "TODO", + "title": "MicrovmImageHooks" + }, + "Port": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "integer" + } + ], + "markdownDescription": "TODO", + "title": "Port" + } + }, + "title": "Hooks", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Logging": { + "additionalProperties": false, + "properties": { + "CloudWatch": { + "allOf": [ + { + "$ref": "#/definitions/CloudWatchLogging" + } + ], + "markdownDescription": "TODO", + "title": "CloudWatch" + }, + "Disabled": { + "markdownDescription": "TODO", + "title": "Disabled", + "type": "boolean" + } + }, + "title": "Logging", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Properties": { + "additionalProperties": false, + "properties": { + "AdditionalOsCapabilities": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "ALL" + ], + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "AdditionalOsCapabilities", + "type": "array" + }, + "BaseImageArn": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BaseImageArn" + }, + "BaseImageVersion": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BaseImageVersion" + }, + "BuildRoleArn": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "BuildRoleArn" + }, + "CodeUri": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "CodeUri" + }, + "CpuConfigurations": { + "items": { + "$ref": "#/definitions/CpuConfiguration" + }, + "markdownDescription": "TODO", + "title": "CpuConfigurations", + "type": "array" + }, + "Description": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Description" + }, + "EgressNetworkConnectors": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "EgressNetworkConnectors", + "type": "array" + }, + "EnvironmentVariables": { + "markdownDescription": "TODO", + "title": "EnvironmentVariables", + "type": "object" + }, + "Hooks": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Hooks" + } + ], + "markdownDescription": "TODO", + "title": "Hooks" + }, + "Logging": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Logging" + } + ], + "markdownDescription": "TODO", + "title": "Logging" + }, + "Name": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Name" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Resources": { + "items": { + "$ref": "#/definitions/ResourceSpec" + }, + "markdownDescription": "TODO", + "title": "Resources", + "type": "array" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + } + }, + "required": [ + "Name", + "CodeUri", + "BaseImageArn", + "BaseImageVersion" + ], + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_microvmimage__Resource": { + "additionalProperties": false, + "properties": { + "Condition": { + "$ref": "#/definitions/PassThroughProp" + }, + "DeletionPolicy": { + "$ref": "#/definitions/PassThroughProp" + }, + "DependsOn": { + "$ref": "#/definitions/PassThroughProp" + }, + "IgnoreGlobals": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "title": "Ignoreglobals" + }, + "Metadata": { + "$ref": "#/definitions/PassThroughProp" + }, + "Properties": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Properties" + }, + "Type": { + "enum": [ + "AWS::Serverless::MicrovmImage" + ], + "title": "Type", + "type": "string" + }, + "UpdateReplacePolicy": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Type", + "Properties" + ], + "title": "Resource", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__Globals": { + "additionalProperties": false, + "properties": { + "OperatorRole": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "OperatorRole" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + } + }, + "title": "Globals", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__Properties": { + "additionalProperties": false, + "properties": { + "Name": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "Name" + }, + "OperatorRole": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "OperatorRole" + }, + "PropagateTags": { + "markdownDescription": "TODO", + "title": "PropagateTags", + "type": "boolean" + }, + "Tags": { + "markdownDescription": "TODO", + "title": "Tags", + "type": "object" + }, + "VpcConfig": { + "allOf": [ + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__VpcConfig" + } + ], + "markdownDescription": "TODO", + "title": "VpcConfig" + } + }, + "required": [ + "VpcConfig" + ], + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__Resource": { + "additionalProperties": false, + "properties": { + "Condition": { + "$ref": "#/definitions/PassThroughProp" + }, + "DeletionPolicy": { + "$ref": "#/definitions/PassThroughProp" + }, + "DependsOn": { + "$ref": "#/definitions/PassThroughProp" + }, + "IgnoreGlobals": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "title": "Ignoreglobals" + }, + "Metadata": { + "$ref": "#/definitions/PassThroughProp" + }, + "Properties": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__Properties" + }, + "Type": { + "enum": [ + "AWS::Serverless::NetworkConnector" + ], + "title": "Type", + "type": "string" + }, + "UpdateReplacePolicy": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Type", + "Properties" + ], + "title": "Resource", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_networkconnector__VpcConfig": { + "additionalProperties": false, + "properties": { + "NetworkProtocol": { + "anyOf": [ + { + "type": "object" + }, + { + "enum": [ + "IPv4", + "DualStack" + ], + "type": "string" + } + ], + "markdownDescription": "TODO", + "title": "NetworkProtocol" + }, + "SecurityGroupIds": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "SecurityGroupIds", + "type": "array" + }, + "SubnetIds": { + "items": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "markdownDescription": "TODO", + "title": "SubnetIds", + "type": "array" + } + }, + "required": [ + "SubnetIds", + "SecurityGroupIds", + "NetworkProtocol" + ], + "title": "VpcConfig", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_simpletable__Globals": { + "additionalProperties": false, + "properties": { + "SSESpecification": { + "__samPassThrough": { + "markdownDescriptionOverride": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", + "schemaPath": [ + "definitions", + "AWS::DynamoDB::Table", + "properties", + "Properties", + "properties", + "SSESpecification" + ] + }, + "allOf": [ + { + "$ref": "#/definitions/PassThroughProp" + } + ], + "title": "SSESpecification" + } + }, + "title": "Globals", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_simpletable__Properties": { + "additionalProperties": false, + "properties": { + "PointInTimeRecoverySpecification": { + "__samPassThrough": { + "markdownDescriptionOverride": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", + "schemaPath": [ + "definitions", + "AWS::DynamoDB::Table", + "properties", + "Properties", + "properties", + "PointInTimeRecoverySpecification" + ] + }, + "allOf": [ + { + "$ref": "#/definitions/PassThroughProp" + } + ], + "title": "ProvisionedThroughput" + }, + "PrimaryKey": { + "allOf": [ + { + "$ref": "#/definitions/PrimaryKey" + } + ], + "markdownDescription": "Attribute name and type to be used as the table's primary key. If not provided, the primary key will be a `String` with a value of `id`. \nThe value of this property cannot be modified after this resource is created.\n*Type*: [PrimaryKeyObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-primarykeyobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an CloudFormation equivalent.", + "title": "PrimaryKey" + }, + "ProvisionedThroughput": { + "__samPassThrough": { + "markdownDescriptionOverride": "Read and write throughput provisioning information. \nIf `ProvisionedThroughput` is not specified `BillingMode` will be specified as `PAY_PER_REQUEST`. \n*Type*: [ProvisionedThroughputObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-simpletable-provisionedthroughputobject.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`ProvisionedThroughput`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html) property of an `AWS::DynamoDB::Table` resource.", + "schemaPath": [ + "definitions", + "AWS::DynamoDB::Table", + "properties", + "Properties", + "properties", + "ProvisionedThroughput" + ] + }, + "allOf": [ + { + "$ref": "#/definitions/PassThroughProp" + } + ], + "title": "ProvisionedThroughput" + }, "SSESpecification": { "__samPassThrough": { "markdownDescriptionOverride": "Specifies the settings to enable server-side encryption. \n*Type*: [SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) \n*Required*: No \n*CloudFormation compatibility*: This property is passed directly to the [`SSESpecification`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) property of an `AWS::DynamoDB::Table` resource.", @@ -10745,6 +11601,9 @@ { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Resource" }, + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_networkconnector__Resource" + }, { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_statemachine__Resource" }, @@ -10769,6 +11628,9 @@ { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_capacity_provider__Resource" }, + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_microvmimage__Resource" + }, { "$ref": "#/definitions/samtranslator__internal__schema_source__any_cfn_resource__Resource" } diff --git a/tests/model/microvm_image/__init__.py b/tests/model/microvm_image/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/model/microvm_image/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/model/microvm_image/test_generators.py b/tests/model/microvm_image/test_generators.py new file mode 100644 index 000000000..bae8ede0d --- /dev/null +++ b/tests/model/microvm_image/test_generators.py @@ -0,0 +1,193 @@ +"""Unit tests for MicroVMImage generator""" + +from samtranslator.intrinsics.resolver import IntrinsicsResolver +from samtranslator.model.microvm_image.generators import MicroVMImageGenerator + + +class TestMicroVMImageGenerator: + def test_to_cloudformation_auto_generates_build_role(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + ) + resources = gen.to_cloudformation() + + assert len(resources) == 2 + role = resources[0] + image = resources[1] + + assert role.logical_id == "MyAgentBuildRole" + assert role.resource_type == "AWS::IAM::Role" + assert image.logical_id == "MyAgent" + assert image.resource_type == "AWS::Lambda::MicrovmImage" + assert image.BuildRoleArn == {"Fn::GetAtt": ["MyAgentBuildRole", "Arn"]} + + def test_to_cloudformation_with_provided_build_role(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + build_role_arn="arn:aws:iam::123456789012:role/CustomRole", + ) + resources = gen.to_cloudformation() + + assert len(resources) == 1 + image = resources[0] + assert image.BuildRoleArn == "arn:aws:iam::123456789012:role/CustomRole" + + def test_code_uri_wraps_into_code_artifact(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + build_role_arn="arn:aws:iam::123456789012:role/Role", + ) + resources = gen.to_cloudformation() + image = resources[0] + + assert image.CodeArtifact == {"Uri": "s3://bucket/agent.zip"} + + def test_tags_converted_to_array_with_sam_tag(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + build_role_arn="arn:aws:iam::123456789012:role/Role", + tags={"Environment": "Production"}, + ) + resources = gen.to_cloudformation() + image = resources[0] + + assert {"Key": "Environment", "Value": "Production"} in image.Tags + assert {"Key": "lambda:createdBy", "Value": "SAM"} in image.Tags + + def test_environment_variables_converted_to_array(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + build_role_arn="arn:aws:iam::123456789012:role/Role", + environment_variables={"LOG_LEVEL": "info", "APP_ENV": "production"}, + ) + resources = gen.to_cloudformation() + image = resources[0] + + assert {"Key": "LOG_LEVEL", "Value": "info"} in image.EnvironmentVariables + assert {"Key": "APP_ENV", "Value": "production"} in image.EnvironmentVariables + + def test_passthrough_fields(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + build_role_arn="arn:aws:iam::123456789012:role/Role", + resources=[{"MinimumMemoryInMiB": 1024}], + cpu_configurations=[{"Architecture": "ARM_64"}], + egress_network_connectors=["arn:aws:lambda:::network-connector:INTERNET_EGRESS"], + additional_os_capabilities=["ALL"], + hooks={"Port": 9000, "MicrovmHooks": {"Run": "ENABLED"}}, + ) + resources = gen.to_cloudformation() + image = resources[0] + + assert image.Resources == [{"MinimumMemoryInMiB": 1024}] + assert image.CpuConfigurations == [{"Architecture": "ARM_64"}] + assert image.EgressNetworkConnectors == ["arn:aws:lambda:::network-connector:INTERNET_EGRESS"] + assert image.AdditionalOsCapabilities == ["ALL"] + assert image.Hooks == {"Port": 9000, "MicrovmHooks": {"Run": "ENABLED"}} + + def test_build_role_trust_policy(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + ) + resources = gen.to_cloudformation() + role = resources[0] + + statement = role.AssumeRolePolicyDocument["Statement"][0] + assert statement["Principal"]["Service"] == ["lambda.amazonaws.com"] + assert statement["Action"] == ["sts:AssumeRole"] + + def test_build_role_s3_scoped_literal_uri(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://my-bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + ) + resources = gen.to_cloudformation() + role = resources[0] + + statements = role.Policies[0]["PolicyDocument"]["Statement"] + s3_statement = statements[0] + logs_statement = statements[1] + + assert s3_statement["Action"] == ["s3:GetObject"] + assert s3_statement["Resource"] == {"Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*"} + + assert "logs:CreateLogGroup" in logs_statement["Action"] + assert logs_statement["Resource"] == "*" + + def test_build_role_s3_scoped_intrinsic_with_resolver(self): + resolver = IntrinsicsResolver({"CodeUriParam": "s3://resolved-bucket/app.zip"}) + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri={"Ref": "CodeUriParam"}, + base_image_arn="arn:aws:lambda:::microvm-image:base", + intrinsics_resolver=resolver, + ) + resources = gen.to_cloudformation() + role = resources[0] + + s3_statement = role.Policies[0]["PolicyDocument"]["Statement"][0] + assert s3_statement["Resource"] == {"Fn::Sub": "arn:${AWS::Partition}:s3:::resolved-bucket/*"} + + def test_build_role_s3_scoped_intrinsic_fallback_fn_split(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri={"Fn::ImportValue": "SharedBucketUri"}, + base_image_arn="arn:aws:lambda:::microvm-image:base", + ) + resources = gen.to_cloudformation() + role = resources[0] + + s3_statement = role.Policies[0]["PolicyDocument"]["Statement"][0] + resource = s3_statement["Resource"] + assert resource["Fn::Sub"][0] == "arn:${AWS::Partition}:s3:::${Bucket}/*" + assert resource["Fn::Sub"][1]["Bucket"]["Fn::Select"][0] == 2 + assert resource["Fn::Sub"][1]["Bucket"]["Fn::Select"][1]["Fn::Split"] == [ + "/", + {"Fn::ImportValue": "SharedBucketUri"}, + ] + + def test_empty_defaults_injected_when_omitted(self): + gen = MicroVMImageGenerator( + logical_id="MyAgent", + name="my-agent", + code_uri="s3://bucket/agent.zip", + base_image_arn="arn:aws:lambda:::microvm-image:base", + base_image_version="0.2", + build_role_arn="arn:aws:iam::123456789012:role/Role", + ) + resources = gen.to_cloudformation() + image = resources[0] + + assert image.Logging == {} + assert image.Description == "" + assert image.EgressNetworkConnectors == [] + assert image.CpuConfigurations == [] + assert image.Resources == [] + assert image.AdditionalOsCapabilities == [] + assert image.Hooks == {} + assert image.EnvironmentVariables == [] diff --git a/tests/model/network_connector/__init__.py b/tests/model/network_connector/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/model/network_connector/test_generators.py b/tests/model/network_connector/test_generators.py new file mode 100644 index 000000000..1fb1d8d93 --- /dev/null +++ b/tests/model/network_connector/test_generators.py @@ -0,0 +1,143 @@ +"""Unit tests for NetworkConnector generator""" + +from unittest import TestCase + +from samtranslator.model.network_connector.generators import NetworkConnectorGenerator + + +class TestNetworkConnectorGenerator(TestCase): + def test_auto_generates_operator_role(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + ) + resources = gen.to_cloudformation() + + self.assertEqual(len(resources), 2) + role = resources[0] + connector = resources[1] + + self.assertEqual(role.logical_id, "MyConnectorOperatorRole") + self.assertEqual(role.resource_type, "AWS::IAM::Role") + self.assertEqual(connector.logical_id, "MyConnector") + self.assertEqual(connector.resource_type, "AWS::Lambda::NetworkConnector") + self.assertEqual(connector.OperatorRole, {"Fn::GetAtt": ["MyConnectorOperatorRole", "Arn"]}) + + def test_with_provided_operator_role(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + operator_role="arn:aws:iam::123456789012:role/CustomRole", + ) + resources = gen.to_cloudformation() + + self.assertEqual(len(resources), 1) + connector = resources[0] + self.assertEqual(connector.OperatorRole, "arn:aws:iam::123456789012:role/CustomRole") + + def test_vpc_config_wrapped_into_configuration(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + operator_role="arn:aws:iam::123456789012:role/Role", + ) + resources = gen.to_cloudformation() + connector = resources[0] + + self.assertEqual( + connector.Configuration, + { + "VpcEgressConfiguration": { + "SubnetIds": ["subnet-abc"], + "SecurityGroupIds": ["sg-123"], + "NetworkProtocol": "IPv4", + "AssociatedComputeResourceTypes": ["MicroVm"], + } + }, + ) + + def test_name_optional(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + operator_role="arn:aws:iam::123456789012:role/Role", + ) + resources = gen.to_cloudformation() + connector = resources[0] + + output = connector.to_dict() + self.assertNotIn("Name", output["MyConnector"]["Properties"]) + + def test_name_provided(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + operator_role="arn:aws:iam::123456789012:role/Role", + name="prod-vpc", + ) + resources = gen.to_cloudformation() + connector = resources[0] + + self.assertEqual(connector.Name, "prod-vpc") + + def test_tags_converted_to_array_with_sam_tag(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + operator_role="arn:aws:iam::123456789012:role/Role", + tags={"Environment": "Production"}, + ) + resources = gen.to_cloudformation() + connector = resources[0] + + self.assertIn({"Key": "Environment", "Value": "Production"}, connector.Tags) + self.assertIn({"Key": "lambda:createdBy", "Value": "SAM"}, connector.Tags) + + def test_connector_tagged_without_user_tags(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + operator_role="arn:aws:iam::123456789012:role/Role", + ) + resources = gen.to_cloudformation() + connector = resources[0] + + self.assertIn({"Key": "lambda:createdBy", "Value": "SAM"}, connector.Tags) + + def test_operator_role_trust_policy(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + ) + resources = gen.to_cloudformation() + role = resources[0] + + statement = role.AssumeRolePolicyDocument["Statement"][0] + self.assertEqual(statement["Principal"]["Service"], ["lambda.amazonaws.com"]) + + def test_operator_role_policy(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + ) + resources = gen.to_cloudformation() + role = resources[0] + + policy = role.Policies[0] + self.assertEqual(policy["PolicyName"], "NetworkConnectorOperatorPolicy") + statements = policy["PolicyDocument"]["Statement"] + all_actions = [s["Action"] for s in statements] + self.assertIn("ec2:CreateNetworkInterface", all_actions) + self.assertIn("ec2:CreateTags", all_actions) + + def test_operator_role_has_sam_marker_tag(self): + gen = NetworkConnectorGenerator( + logical_id="MyConnector", + vpc_config={"SubnetIds": ["subnet-abc"], "SecurityGroupIds": ["sg-123"], "NetworkProtocol": "IPv4"}, + tags={"Team": "Platform"}, + ) + resources = gen.to_cloudformation() + role = resources[0] + + self.assertIsNotNone(role.Tags) + self.assertIn({"Key": "lambda:createdBy", "Value": "SAM"}, role.Tags) diff --git a/tests/model/network_connector/test_resources.py b/tests/model/network_connector/test_resources.py new file mode 100644 index 000000000..c20f3543d --- /dev/null +++ b/tests/model/network_connector/test_resources.py @@ -0,0 +1,34 @@ +from unittest import TestCase + +from samtranslator.model.network_connector.resources import LambdaNetworkConnector + + +class TestLambdaNetworkConnector(TestCase): + def test_resource_type(self): + connector = LambdaNetworkConnector("MyConnector") + self.assertEqual(connector.resource_type, "AWS::Lambda::NetworkConnector") + + def test_properties(self): + connector = LambdaNetworkConnector("MyConnector") + + connector.Name = "prod-vpc" + connector.Configuration = { + "VpcEgressConfiguration": { + "SubnetIds": ["subnet-abc"], + "SecurityGroupIds": ["sg-123"], + "NetworkProtocol": "IPv4", + "AssociatedComputeResourceTypes": ["MicroVm"], + } + } + connector.OperatorRole = "arn:aws:iam::123456789012:role/OperatorRole" + connector.Tags = [ + {"Key": "lambda:createdBy", "Value": "SAM"}, + {"Key": "Environment", "Value": "Production"}, + ] + + self.assertEqual(connector.Name, "prod-vpc") + self.assertEqual( + connector.Configuration["VpcEgressConfiguration"]["AssociatedComputeResourceTypes"], ["MicroVm"] + ) + self.assertEqual(connector.OperatorRole, "arn:aws:iam::123456789012:role/OperatorRole") + self.assertEqual(len(connector.Tags), 2) diff --git a/tests/schema/test_validate_schema.py b/tests/schema/test_validate_schema.py index a6b3b7d04..771823aaf 100644 --- a/tests/schema/test_validate_schema.py +++ b/tests/schema/test_validate_schema.py @@ -59,6 +59,7 @@ "api_with_custom_base_path", "function_with_tracing", # TODO: intentionally skip this tests to cover incorrect scenarios "capacity_provider_global_with_functions", # Skip for Global case since customers can define partial field for global + "microvm_image_globals", # Skip for Global case since BaseImageArn/BaseImageVersion come from Globals ] diff --git a/tests/translator/input/error_microvm_image_invalid_enums.yaml b/tests/translator/input/error_microvm_image_invalid_enums.yaml new file mode 100644 index 000000000..75f056593 --- /dev/null +++ b/tests/translator/input/error_microvm_image_invalid_enums.yaml @@ -0,0 +1,18 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test invalid enum values for Architecture and hook state + +Resources: + MicrovmImageWithInvalidEnums: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: my-agent + CodeUri: s3://bucket/agent.zip + BaseImageArn: arn:aws:lambda:::microvm-image:base + BaseImageVersion: '0.4' + CpuConfigurations: + - Architecture: INVALID_ARCH + Hooks: + Port: 9000 + MicrovmHooks: + Run: INVALID_STATE diff --git a/tests/translator/input/error_microvm_image_invalid_tags.yaml b/tests/translator/input/error_microvm_image_invalid_tags.yaml new file mode 100644 index 000000000..e3836250b --- /dev/null +++ b/tests/translator/input/error_microvm_image_invalid_tags.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test invalid Tags shape (list instead of map) + +Resources: + MicroVmImageWithInvalidTags: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: my-agent + CodeUri: s3://bucket/agent.zip + BaseImageArn: arn:aws:lambda:::microvm-image:base + BaseImageVersion: '0' + Tags: + - Key: Environment + Value: Production diff --git a/tests/translator/input/error_microvm_image_missing_required.yaml b/tests/translator/input/error_microvm_image_missing_required.yaml new file mode 100644 index 000000000..385149ca9 --- /dev/null +++ b/tests/translator/input/error_microvm_image_missing_required.yaml @@ -0,0 +1,9 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test missing required properties for MicroVMImage + +Resources: + MicroVmImageMissingRequired: + Type: AWS::Serverless::MicrovmImage + Properties: + Description: Missing Name, CodeUri, and BaseImageArn diff --git a/tests/translator/input/error_network_connector_invalid_protocol.yaml b/tests/translator/input/error_network_connector_invalid_protocol.yaml new file mode 100644 index 000000000..48a126979 --- /dev/null +++ b/tests/translator/input/error_network_connector_invalid_protocol.yaml @@ -0,0 +1,19 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + Test invalid NetworkProtocol enum value. + Note: error message says "not a valid dict" due to SamIntrinsicable union type + matching - Pydantic reports the dict branch failure rather than the Literal mismatch. + This is a known limitation of the SAM validation framework. + +Resources: + NetworkConnectorInvalidProtocol: + Type: AWS::Serverless::NetworkConnector + Properties: + Name: my-connector + VpcConfig: + SubnetIds: + - subnet-abc + SecurityGroupIds: + - sg-123 + NetworkProtocol: IPv6 diff --git a/tests/translator/input/error_network_connector_invalid_tags.yaml b/tests/translator/input/error_network_connector_invalid_tags.yaml new file mode 100644 index 000000000..44074d09f --- /dev/null +++ b/tests/translator/input/error_network_connector_invalid_tags.yaml @@ -0,0 +1,17 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test Tags as list instead of map + +Resources: + NetworkConnectorInvalidTags: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - subnet-abc + SecurityGroupIds: + - sg-123 + NetworkProtocol: IPv4 + Tags: + - Key: Environment + Value: Production diff --git a/tests/translator/input/error_network_connector_missing_vpc_config.yaml b/tests/translator/input/error_network_connector_missing_vpc_config.yaml new file mode 100644 index 000000000..371703c9b --- /dev/null +++ b/tests/translator/input/error_network_connector_missing_vpc_config.yaml @@ -0,0 +1,11 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test missing required VpcConfig for NetworkConnector + +Resources: + NetworkConnectorMissingVpcConfig: + Type: AWS::Serverless::NetworkConnector + Properties: + Name: my-connector + Tags: + Environment: Test diff --git a/tests/translator/input/error_network_connector_missing_vpc_fields.yaml b/tests/translator/input/error_network_connector_missing_vpc_fields.yaml new file mode 100644 index 000000000..5c883aa40 --- /dev/null +++ b/tests/translator/input/error_network_connector_missing_vpc_fields.yaml @@ -0,0 +1,11 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test missing required fields in VpcConfig + +Resources: + NetworkConnectorMissingVpcFields: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - subnet-abc diff --git a/tests/translator/input/error_network_connector_unknown_vpc_field.yaml b/tests/translator/input/error_network_connector_unknown_vpc_field.yaml new file mode 100644 index 000000000..6c6abb00f --- /dev/null +++ b/tests/translator/input/error_network_connector_unknown_vpc_field.yaml @@ -0,0 +1,16 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test unknown property in VpcConfig (extra=forbid) + +Resources: + NetworkConnectorUnknownVpcField: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - subnet-abc + SecurityGroupIds: + - sg-123 + NetworkProtocol: IPv4 + AssociatedComputeResourceTypes: + - MICROVMS diff --git a/tests/translator/input/microvm_image_full.yaml b/tests/translator/input/microvm_image_full.yaml new file mode 100644 index 000000000..07d6b166c --- /dev/null +++ b/tests/translator/input/microvm_image_full.yaml @@ -0,0 +1,39 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: MicrovmImage with all properties, BuildRoleArn omitted (auto-generated) + +Resources: + MyAgent: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: my-agent + CodeUri: s3://my-bucket/agent.zip + BaseImageArn: arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2 + BaseImageVersion: '2.0' + Description: My production agent + EgressNetworkConnectors: + - arn:aws:lambda:::network-connector:aws-network-connector:INTERNET_EGRESS + CpuConfigurations: + - Architecture: ARM_64 + Resources: + - MinimumMemoryInMiB: 1024 + AdditionalOsCapabilities: + - ALL + Hooks: + Port: 9000 + MicrovmHooks: + Run: ENABLED + RunTimeoutInSeconds: 30 + Suspend: ENABLED + Resume: ENABLED + MicrovmImageHooks: + Ready: ENABLED + EnvironmentVariables: + LOG_LEVEL: info + APP_ENV: production + Logging: + CloudWatch: + LogGroup: /aws/lambda-microvms/my-agent + Tags: + Environment: Production + Team: Platform diff --git a/tests/translator/input/microvm_image_globals.yaml b/tests/translator/input/microvm_image_globals.yaml new file mode 100644 index 000000000..16304fddf --- /dev/null +++ b/tests/translator/input/microvm_image_globals.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test MicrovmImage with Globals support + +Globals: + MicrovmImage: + BaseImageArn: arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2 + BaseImageVersion: '0.4' + Tags: + Team: Platform + ManagedBy: SAM + Resources: + - MinimumMemoryInMiB: 512 + +Resources: + AgentOne: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: agent-one + CodeUri: s3://bucket/agent-one.zip + Tags: + Environment: Production + + AgentTwo: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: agent-two + CodeUri: s3://bucket/agent-two.zip + CpuConfigurations: + - Architecture: ARM_64 + Tags: + Environment: Staging diff --git a/tests/translator/input/microvm_image_minimal.yaml b/tests/translator/input/microvm_image_minimal.yaml new file mode 100644 index 000000000..7e2b9cfcd --- /dev/null +++ b/tests/translator/input/microvm_image_minimal.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: MicrovmImage with only required fields - all optional fields auto-injected + as empty defaults + +Resources: + MyAgent: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: my-agent + CodeUri: s3://my-bucket/agent.zip + BaseImageArn: arn:aws:lambda:::microvm-image:al2023-0 + BaseImageVersion: '0.2' diff --git a/tests/translator/input/microvm_image_with_build_role.yaml b/tests/translator/input/microvm_image_with_build_role.yaml new file mode 100644 index 000000000..56fd38635 --- /dev/null +++ b/tests/translator/input/microvm_image_with_build_role.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: MicrovmImage with BuildRoleArn provided (no auto-generation) + +Resources: + MyAgent: + Type: AWS::Serverless::MicrovmImage + Properties: + Name: my-agent + CodeUri: s3://my-bucket/agent.zip + BaseImageArn: arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2 + BaseImageVersion: '0.4' + BuildRoleArn: arn:aws:iam::123456789012:role/MyCustomBuildRole + Tags: + Environment: Production diff --git a/tests/translator/input/network_connector.yaml b/tests/translator/input/network_connector.yaml new file mode 100644 index 000000000..c843f29c8 --- /dev/null +++ b/tests/translator/input/network_connector.yaml @@ -0,0 +1,18 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Basic NetworkConnector with auto-generated OperatorRole + +Resources: + MyNetworkConnector: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - subnet-0abc123 + - subnet-0def456 + SecurityGroupIds: + - sg-0abcd0ef + NetworkProtocol: IPv4 + Tags: + Environment: Production + Team: Platform diff --git a/tests/translator/input/network_connector_globals.yaml b/tests/translator/input/network_connector_globals.yaml new file mode 100644 index 000000000..f7aa5ef51 --- /dev/null +++ b/tests/translator/input/network_connector_globals.yaml @@ -0,0 +1,37 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Test NetworkConnector with Globals support + +Globals: + NetworkConnector: + OperatorRole: arn:aws:iam::123456789012:role/SharedOperatorRole + Tags: + Team: Platform + ManagedBy: SAM + +Resources: + ConnectorOne: + Type: AWS::Serverless::NetworkConnector + Properties: + Name: connector-one + VpcConfig: + SubnetIds: + - subnet-abc + SecurityGroupIds: + - sg-0abcd012 + NetworkProtocol: IPv4 + Tags: + Environment: Production + + ConnectorTwo: + Type: AWS::Serverless::NetworkConnector + Properties: + Name: connector-two + VpcConfig: + SubnetIds: + - subnet-def + SecurityGroupIds: + - sg-0abcd456 + NetworkProtocol: DualStack + Tags: + Environment: Staging diff --git a/tests/translator/input/network_connector_with_intrinsics.yaml b/tests/translator/input/network_connector_with_intrinsics.yaml new file mode 100644 index 000000000..e50f032be --- /dev/null +++ b/tests/translator/input/network_connector_with_intrinsics.yaml @@ -0,0 +1,20 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: NetworkConnector with intrinsic functions in VpcConfig + +Parameters: + SubnetId: + Type: String + SecurityGroupId: + Type: String + +Resources: + MyNetworkConnector: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - !Ref SubnetId + SecurityGroupIds: + - !Ref SecurityGroupId + NetworkProtocol: IPv4 diff --git a/tests/translator/input/network_connector_with_operator_role.yaml b/tests/translator/input/network_connector_with_operator_role.yaml new file mode 100644 index 000000000..f83cf5d7a --- /dev/null +++ b/tests/translator/input/network_connector_with_operator_role.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: NetworkConnector with user-provided OperatorRole + +Resources: + MyNetworkConnector: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - subnet-0abc123 + SecurityGroupIds: + - sg-0abcd0ef + NetworkProtocol: DualStack + OperatorRole: arn:aws:iam::123456789012:role/CustomOperatorRole diff --git a/tests/translator/input/network_connector_with_propagate_tags.yaml b/tests/translator/input/network_connector_with_propagate_tags.yaml new file mode 100644 index 000000000..95aa8e927 --- /dev/null +++ b/tests/translator/input/network_connector_with_propagate_tags.yaml @@ -0,0 +1,18 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: NetworkConnector with PropagateTags flowing tags to auto-generated role + +Resources: + MyNetworkConnector: + Type: AWS::Serverless::NetworkConnector + Properties: + VpcConfig: + SubnetIds: + - subnet-0abc123 + SecurityGroupIds: + - sg-0abcd0ef + NetworkProtocol: IPv4 + Tags: + Environment: Production + Team: Platform + PropagateTags: true diff --git a/tests/translator/output/aws-cn/microvm_image_full.json b/tests/translator/output/aws-cn/microvm_image_full.json new file mode 100644 index 000000000..3a6c24623 --- /dev/null +++ b/tests/translator/output/aws-cn/microvm_image_full.json @@ -0,0 +1,136 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with all properties, BuildRoleArn omitted (auto-generated)", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [ + "ALL" + ], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "2.0", + "BuildRoleArn": { + "Fn::GetAtt": [ + "MyAgentBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [ + { + "Architecture": "ARM_64" + } + ], + "Description": "My production agent", + "EgressNetworkConnectors": [ + "arn:aws:lambda:::network-connector:aws-network-connector:INTERNET_EGRESS" + ], + "EnvironmentVariables": [ + { + "Key": "LOG_LEVEL", + "Value": "info" + }, + { + "Key": "APP_ENV", + "Value": "production" + } + ], + "Hooks": { + "MicrovmHooks": { + "Resume": "ENABLED", + "Run": "ENABLED", + "RunTimeoutInSeconds": 30, + "Suspend": "ENABLED" + }, + "MicrovmImageHooks": { + "Ready": "ENABLED" + }, + "Port": 9000 + }, + "Logging": { + "CloudWatch": { + "LogGroup": "/aws/lambda-microvms/my-agent" + } + }, + "Name": "my-agent", + "Resources": [ + { + "MinimumMemoryInMiB": 1024 + } + ], + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "MyAgentBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/microvm_image_globals.json b/tests/translator/output/aws-cn/microvm_image_globals.json new file mode 100644 index 000000000..6271bf80c --- /dev/null +++ b/tests/translator/output/aws-cn/microvm_image_globals.json @@ -0,0 +1,214 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Test MicrovmImage with Globals support", + "Resources": { + "AgentOne": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": { + "Fn::GetAtt": [ + "AgentOneBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://bucket/agent-one.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "agent-one", + "Resources": [ + { + "MinimumMemoryInMiB": 512 + } + ], + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "AgentOneBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "AgentTwo": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": { + "Fn::GetAtt": [ + "AgentTwoBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://bucket/agent-two.zip" + }, + "CpuConfigurations": [ + { + "Architecture": "ARM_64" + } + ], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "agent-two", + "Resources": [ + { + "MinimumMemoryInMiB": 512 + } + ], + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Staging" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "AgentTwoBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/microvm_image_minimal.json b/tests/translator/output/aws-cn/microvm_image_minimal.json new file mode 100644 index 000000000..37428c785 --- /dev/null +++ b/tests/translator/output/aws-cn/microvm_image_minimal.json @@ -0,0 +1,92 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with only required fields - all optional fields auto-injected as empty defaults", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:al2023-0", + "BaseImageVersion": "0.2", + "BuildRoleArn": { + "Fn::GetAtt": [ + "MyAgentBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "my-agent", + "Resources": [], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "MyAgentBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/microvm_image_with_build_role.json b/tests/translator/output/aws-cn/microvm_image_with_build_role.json new file mode 100644 index 000000000..e321da251 --- /dev/null +++ b/tests/translator/output/aws-cn/microvm_image_with_build_role.json @@ -0,0 +1,36 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with BuildRoleArn provided (no auto-generation)", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": "arn:aws:iam::123456789012:role/MyCustomBuildRole", + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "my-agent", + "Resources": [], + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + } + } +} diff --git a/tests/translator/output/aws-cn/network_connector.json b/tests/translator/output/aws-cn/network_connector.json new file mode 100644 index 000000000..5374eb6a9 --- /dev/null +++ b/tests/translator/output/aws-cn/network_connector.json @@ -0,0 +1,129 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Basic NetworkConnector with auto-generated OperatorRole", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123", + "subnet-0def456" + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/network_connector_globals.json b/tests/translator/output/aws-cn/network_connector_globals.json new file mode 100644 index 000000000..bbb57e0b5 --- /dev/null +++ b/tests/translator/output/aws-cn/network_connector_globals.json @@ -0,0 +1,84 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Test NetworkConnector with Globals support", + "Resources": { + "ConnectorOne": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd012" + ], + "SubnetIds": [ + "subnet-abc" + ] + } + }, + "Name": "connector-one", + "OperatorRole": "arn:aws:iam::123456789012:role/SharedOperatorRole", + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "ConnectorTwo": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "DualStack", + "SecurityGroupIds": [ + "sg-0abcd456" + ], + "SubnetIds": [ + "subnet-def" + ] + } + }, + "Name": "connector-two", + "OperatorRole": "arn:aws:iam::123456789012:role/SharedOperatorRole", + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Staging" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + } + } +} diff --git a/tests/translator/output/aws-cn/network_connector_with_intrinsics.json b/tests/translator/output/aws-cn/network_connector_with_intrinsics.json new file mode 100644 index 000000000..b498977c5 --- /dev/null +++ b/tests/translator/output/aws-cn/network_connector_with_intrinsics.json @@ -0,0 +1,132 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with intrinsic functions in VpcConfig", + "Parameters": { + "SecurityGroupId": { + "Type": "String" + }, + "SubnetId": { + "Type": "String" + } + }, + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + { + "Ref": "SecurityGroupId" + } + ], + "SubnetIds": [ + { + "Ref": "SubnetId" + } + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/network_connector_with_operator_role.json b/tests/translator/output/aws-cn/network_connector_with_operator_role.json new file mode 100644 index 000000000..32465310e --- /dev/null +++ b/tests/translator/output/aws-cn/network_connector_with_operator_role.json @@ -0,0 +1,32 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with user-provided OperatorRole", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "DualStack", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123" + ] + } + }, + "OperatorRole": "arn:aws:iam::123456789012:role/CustomOperatorRole", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + } + } +} diff --git a/tests/translator/output/aws-cn/network_connector_with_propagate_tags.json b/tests/translator/output/aws-cn/network_connector_with_propagate_tags.json new file mode 100644 index 000000000..8a5f2456d --- /dev/null +++ b/tests/translator/output/aws-cn/network_connector_with_propagate_tags.json @@ -0,0 +1,136 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with PropagateTags flowing tags to auto-generated role", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123" + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/microvm_image_full.json b/tests/translator/output/aws-us-gov/microvm_image_full.json new file mode 100644 index 000000000..3a6c24623 --- /dev/null +++ b/tests/translator/output/aws-us-gov/microvm_image_full.json @@ -0,0 +1,136 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with all properties, BuildRoleArn omitted (auto-generated)", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [ + "ALL" + ], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "2.0", + "BuildRoleArn": { + "Fn::GetAtt": [ + "MyAgentBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [ + { + "Architecture": "ARM_64" + } + ], + "Description": "My production agent", + "EgressNetworkConnectors": [ + "arn:aws:lambda:::network-connector:aws-network-connector:INTERNET_EGRESS" + ], + "EnvironmentVariables": [ + { + "Key": "LOG_LEVEL", + "Value": "info" + }, + { + "Key": "APP_ENV", + "Value": "production" + } + ], + "Hooks": { + "MicrovmHooks": { + "Resume": "ENABLED", + "Run": "ENABLED", + "RunTimeoutInSeconds": 30, + "Suspend": "ENABLED" + }, + "MicrovmImageHooks": { + "Ready": "ENABLED" + }, + "Port": 9000 + }, + "Logging": { + "CloudWatch": { + "LogGroup": "/aws/lambda-microvms/my-agent" + } + }, + "Name": "my-agent", + "Resources": [ + { + "MinimumMemoryInMiB": 1024 + } + ], + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "MyAgentBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/microvm_image_globals.json b/tests/translator/output/aws-us-gov/microvm_image_globals.json new file mode 100644 index 000000000..6271bf80c --- /dev/null +++ b/tests/translator/output/aws-us-gov/microvm_image_globals.json @@ -0,0 +1,214 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Test MicrovmImage with Globals support", + "Resources": { + "AgentOne": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": { + "Fn::GetAtt": [ + "AgentOneBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://bucket/agent-one.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "agent-one", + "Resources": [ + { + "MinimumMemoryInMiB": 512 + } + ], + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "AgentOneBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "AgentTwo": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": { + "Fn::GetAtt": [ + "AgentTwoBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://bucket/agent-two.zip" + }, + "CpuConfigurations": [ + { + "Architecture": "ARM_64" + } + ], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "agent-two", + "Resources": [ + { + "MinimumMemoryInMiB": 512 + } + ], + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Staging" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "AgentTwoBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/microvm_image_minimal.json b/tests/translator/output/aws-us-gov/microvm_image_minimal.json new file mode 100644 index 000000000..37428c785 --- /dev/null +++ b/tests/translator/output/aws-us-gov/microvm_image_minimal.json @@ -0,0 +1,92 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with only required fields - all optional fields auto-injected as empty defaults", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:al2023-0", + "BaseImageVersion": "0.2", + "BuildRoleArn": { + "Fn::GetAtt": [ + "MyAgentBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "my-agent", + "Resources": [], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "MyAgentBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/microvm_image_with_build_role.json b/tests/translator/output/aws-us-gov/microvm_image_with_build_role.json new file mode 100644 index 000000000..e321da251 --- /dev/null +++ b/tests/translator/output/aws-us-gov/microvm_image_with_build_role.json @@ -0,0 +1,36 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with BuildRoleArn provided (no auto-generation)", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": "arn:aws:iam::123456789012:role/MyCustomBuildRole", + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "my-agent", + "Resources": [], + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + } + } +} diff --git a/tests/translator/output/aws-us-gov/network_connector.json b/tests/translator/output/aws-us-gov/network_connector.json new file mode 100644 index 000000000..5374eb6a9 --- /dev/null +++ b/tests/translator/output/aws-us-gov/network_connector.json @@ -0,0 +1,129 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Basic NetworkConnector with auto-generated OperatorRole", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123", + "subnet-0def456" + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/network_connector_globals.json b/tests/translator/output/aws-us-gov/network_connector_globals.json new file mode 100644 index 000000000..bbb57e0b5 --- /dev/null +++ b/tests/translator/output/aws-us-gov/network_connector_globals.json @@ -0,0 +1,84 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Test NetworkConnector with Globals support", + "Resources": { + "ConnectorOne": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd012" + ], + "SubnetIds": [ + "subnet-abc" + ] + } + }, + "Name": "connector-one", + "OperatorRole": "arn:aws:iam::123456789012:role/SharedOperatorRole", + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "ConnectorTwo": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "DualStack", + "SecurityGroupIds": [ + "sg-0abcd456" + ], + "SubnetIds": [ + "subnet-def" + ] + } + }, + "Name": "connector-two", + "OperatorRole": "arn:aws:iam::123456789012:role/SharedOperatorRole", + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Staging" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + } + } +} diff --git a/tests/translator/output/aws-us-gov/network_connector_with_intrinsics.json b/tests/translator/output/aws-us-gov/network_connector_with_intrinsics.json new file mode 100644 index 000000000..b498977c5 --- /dev/null +++ b/tests/translator/output/aws-us-gov/network_connector_with_intrinsics.json @@ -0,0 +1,132 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with intrinsic functions in VpcConfig", + "Parameters": { + "SecurityGroupId": { + "Type": "String" + }, + "SubnetId": { + "Type": "String" + } + }, + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + { + "Ref": "SecurityGroupId" + } + ], + "SubnetIds": [ + { + "Ref": "SubnetId" + } + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/network_connector_with_operator_role.json b/tests/translator/output/aws-us-gov/network_connector_with_operator_role.json new file mode 100644 index 000000000..32465310e --- /dev/null +++ b/tests/translator/output/aws-us-gov/network_connector_with_operator_role.json @@ -0,0 +1,32 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with user-provided OperatorRole", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "DualStack", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123" + ] + } + }, + "OperatorRole": "arn:aws:iam::123456789012:role/CustomOperatorRole", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + } + } +} diff --git a/tests/translator/output/aws-us-gov/network_connector_with_propagate_tags.json b/tests/translator/output/aws-us-gov/network_connector_with_propagate_tags.json new file mode 100644 index 000000000..8a5f2456d --- /dev/null +++ b/tests/translator/output/aws-us-gov/network_connector_with_propagate_tags.json @@ -0,0 +1,136 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with PropagateTags flowing tags to auto-generated role", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123" + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/error_globals_unsupported_type.json b/tests/translator/output/error_globals_unsupported_type.json index 778590823..39bf5cf14 100644 --- a/tests/translator/output/error_globals_unsupported_type.json +++ b/tests/translator/output/error_globals_unsupported_type.json @@ -4,12 +4,12 @@ "Number of errors found: 1. ", "'Globals' section is invalid. ", "'NewType' is not supported. ", - "Must be one of the following values - ['Api', 'CapacityProvider', 'Function', 'HttpApi', 'LayerVersion', 'SimpleTable', 'StateMachine', 'WebSocketApi']" + "Must be one of the following values - ['Api', 'CapacityProvider', 'Function', 'HttpApi', 'LayerVersion', 'MicrovmImage', 'NetworkConnector', 'SimpleTable', 'StateMachine', 'WebSocketApi']" ], - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Api', 'CapacityProvider', 'Function', 'HttpApi', 'LayerVersion', 'SimpleTable', 'StateMachine', 'WebSocketApi']", + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Api', 'CapacityProvider', 'Function', 'HttpApi', 'LayerVersion', 'MicrovmImage', 'NetworkConnector', 'SimpleTable', 'StateMachine', 'WebSocketApi']", "errors": [ { - "errorMessage": "'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Api', 'CapacityProvider', 'Function', 'HttpApi', 'LayerVersion', 'SimpleTable', 'StateMachine', 'WebSocketApi']" + "errorMessage": "'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Api', 'CapacityProvider', 'Function', 'HttpApi', 'LayerVersion', 'MicrovmImage', 'NetworkConnector', 'SimpleTable', 'StateMachine', 'WebSocketApi']" } ] } diff --git a/tests/translator/output/error_microvm_image_invalid_enums.json b/tests/translator/output/error_microvm_image_invalid_enums.json new file mode 100644 index 000000000..9ee0fcae5 --- /dev/null +++ b/tests/translator/output/error_microvm_image_invalid_enums.json @@ -0,0 +1,15 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [MicrovmImageWithInvalidEnums] is invalid. ", + "Property 'CpuConfigurations.0.Architecture' value is not a valid dict. ", + "Property 'Hooks.MicrovmHooks.Run' value is not a valid dict." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [MicrovmImageWithInvalidEnums] is invalid. Property 'CpuConfigurations.0.Architecture' value is not a valid dict. Property 'Hooks.MicrovmHooks.Run' value is not a valid dict.", + "errors": [ + { + "errorMessage": "Resource with id [MicrovmImageWithInvalidEnums] is invalid. Property 'CpuConfigurations.0.Architecture' value is not a valid dict. Property 'Hooks.MicrovmHooks.Run' value is not a valid dict." + } + ] +} diff --git a/tests/translator/output/error_microvm_image_invalid_tags.json b/tests/translator/output/error_microvm_image_invalid_tags.json new file mode 100644 index 000000000..3eb6eedd1 --- /dev/null +++ b/tests/translator/output/error_microvm_image_invalid_tags.json @@ -0,0 +1,14 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [MicroVmImageWithInvalidTags] is invalid. ", + "Property 'Tags' should be a map." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [MicroVmImageWithInvalidTags] is invalid. Property 'Tags' should be a map.", + "errors": [ + { + "errorMessage": "Resource with id [MicroVmImageWithInvalidTags] is invalid. Property 'Tags' should be a map." + } + ] +} diff --git a/tests/translator/output/error_microvm_image_missing_required.json b/tests/translator/output/error_microvm_image_missing_required.json new file mode 100644 index 000000000..4de02aa95 --- /dev/null +++ b/tests/translator/output/error_microvm_image_missing_required.json @@ -0,0 +1,14 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [MicroVmImageMissingRequired] is invalid. ", + "Missing required property 'Name'." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [MicroVmImageMissingRequired] is invalid. Missing required property 'Name'.", + "errors": [ + { + "errorMessage": "Resource with id [MicroVmImageMissingRequired] is invalid. Missing required property 'Name'." + } + ] +} diff --git a/tests/translator/output/error_network_connector_invalid_protocol.json b/tests/translator/output/error_network_connector_invalid_protocol.json new file mode 100644 index 000000000..709fb392f --- /dev/null +++ b/tests/translator/output/error_network_connector_invalid_protocol.json @@ -0,0 +1,14 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [NetworkConnectorInvalidProtocol] is invalid. ", + "Property 'VpcConfig.NetworkProtocol' value is not a valid dict." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [NetworkConnectorInvalidProtocol] is invalid. Property 'VpcConfig.NetworkProtocol' value is not a valid dict.", + "errors": [ + { + "errorMessage": "Resource with id [NetworkConnectorInvalidProtocol] is invalid. Property 'VpcConfig.NetworkProtocol' value is not a valid dict." + } + ] +} diff --git a/tests/translator/output/error_network_connector_invalid_tags.json b/tests/translator/output/error_network_connector_invalid_tags.json new file mode 100644 index 000000000..3a0d3535a --- /dev/null +++ b/tests/translator/output/error_network_connector_invalid_tags.json @@ -0,0 +1,14 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [NetworkConnectorInvalidTags] is invalid. ", + "Property 'Tags' should be a map." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [NetworkConnectorInvalidTags] is invalid. Property 'Tags' should be a map.", + "errors": [ + { + "errorMessage": "Resource with id [NetworkConnectorInvalidTags] is invalid. Property 'Tags' should be a map." + } + ] +} diff --git a/tests/translator/output/error_network_connector_missing_vpc_config.json b/tests/translator/output/error_network_connector_missing_vpc_config.json new file mode 100644 index 000000000..72ff8a134 --- /dev/null +++ b/tests/translator/output/error_network_connector_missing_vpc_config.json @@ -0,0 +1,14 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [NetworkConnectorMissingVpcConfig] is invalid. ", + "Missing required property 'VpcConfig'." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [NetworkConnectorMissingVpcConfig] is invalid. Missing required property 'VpcConfig'.", + "errors": [ + { + "errorMessage": "Resource with id [NetworkConnectorMissingVpcConfig] is invalid. Missing required property 'VpcConfig'." + } + ] +} diff --git a/tests/translator/output/error_network_connector_missing_vpc_fields.json b/tests/translator/output/error_network_connector_missing_vpc_fields.json new file mode 100644 index 000000000..667cca9d7 --- /dev/null +++ b/tests/translator/output/error_network_connector_missing_vpc_fields.json @@ -0,0 +1,15 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [NetworkConnectorMissingVpcFields] is invalid. ", + "Property 'VpcConfig.SecurityGroupIds' is required. ", + "Property 'VpcConfig.NetworkProtocol' is required." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [NetworkConnectorMissingVpcFields] is invalid. Property 'VpcConfig.SecurityGroupIds' is required. Property 'VpcConfig.NetworkProtocol' is required.", + "errors": [ + { + "errorMessage": "Resource with id [NetworkConnectorMissingVpcFields] is invalid. Property 'VpcConfig.SecurityGroupIds' is required. Property 'VpcConfig.NetworkProtocol' is required." + } + ] +} diff --git a/tests/translator/output/error_network_connector_unknown_vpc_field.json b/tests/translator/output/error_network_connector_unknown_vpc_field.json new file mode 100644 index 000000000..2013be17c --- /dev/null +++ b/tests/translator/output/error_network_connector_unknown_vpc_field.json @@ -0,0 +1,14 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [NetworkConnectorUnknownVpcField] is invalid. ", + "Property 'VpcConfig.AssociatedComputeResourceTypes' is an invalid property." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [NetworkConnectorUnknownVpcField] is invalid. Property 'VpcConfig.AssociatedComputeResourceTypes' is an invalid property.", + "errors": [ + { + "errorMessage": "Resource with id [NetworkConnectorUnknownVpcField] is invalid. Property 'VpcConfig.AssociatedComputeResourceTypes' is an invalid property." + } + ] +} diff --git a/tests/translator/output/microvm_image_full.json b/tests/translator/output/microvm_image_full.json new file mode 100644 index 000000000..3a6c24623 --- /dev/null +++ b/tests/translator/output/microvm_image_full.json @@ -0,0 +1,136 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with all properties, BuildRoleArn omitted (auto-generated)", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [ + "ALL" + ], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "2.0", + "BuildRoleArn": { + "Fn::GetAtt": [ + "MyAgentBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [ + { + "Architecture": "ARM_64" + } + ], + "Description": "My production agent", + "EgressNetworkConnectors": [ + "arn:aws:lambda:::network-connector:aws-network-connector:INTERNET_EGRESS" + ], + "EnvironmentVariables": [ + { + "Key": "LOG_LEVEL", + "Value": "info" + }, + { + "Key": "APP_ENV", + "Value": "production" + } + ], + "Hooks": { + "MicrovmHooks": { + "Resume": "ENABLED", + "Run": "ENABLED", + "RunTimeoutInSeconds": 30, + "Suspend": "ENABLED" + }, + "MicrovmImageHooks": { + "Ready": "ENABLED" + }, + "Port": 9000 + }, + "Logging": { + "CloudWatch": { + "LogGroup": "/aws/lambda-microvms/my-agent" + } + }, + "Name": "my-agent", + "Resources": [ + { + "MinimumMemoryInMiB": 1024 + } + ], + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "MyAgentBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/microvm_image_globals.json b/tests/translator/output/microvm_image_globals.json new file mode 100644 index 000000000..6271bf80c --- /dev/null +++ b/tests/translator/output/microvm_image_globals.json @@ -0,0 +1,214 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Test MicrovmImage with Globals support", + "Resources": { + "AgentOne": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": { + "Fn::GetAtt": [ + "AgentOneBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://bucket/agent-one.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "agent-one", + "Resources": [ + { + "MinimumMemoryInMiB": 512 + } + ], + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "AgentOneBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "AgentTwo": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": { + "Fn::GetAtt": [ + "AgentTwoBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://bucket/agent-two.zip" + }, + "CpuConfigurations": [ + { + "Architecture": "ARM_64" + } + ], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "agent-two", + "Resources": [ + { + "MinimumMemoryInMiB": 512 + } + ], + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Staging" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "AgentTwoBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/microvm_image_minimal.json b/tests/translator/output/microvm_image_minimal.json new file mode 100644 index 000000000..37428c785 --- /dev/null +++ b/tests/translator/output/microvm_image_minimal.json @@ -0,0 +1,92 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with only required fields - all optional fields auto-injected as empty defaults", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:al2023-0", + "BaseImageVersion": "0.2", + "BuildRoleArn": { + "Fn::GetAtt": [ + "MyAgentBuildRole", + "Arn" + ] + }, + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "my-agent", + "Resources": [], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + }, + "MyAgentBuildRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:s3:::my-bucket/*" + } + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MicrovmImageBuildPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/microvm_image_with_build_role.json b/tests/translator/output/microvm_image_with_build_role.json new file mode 100644 index 000000000..e321da251 --- /dev/null +++ b/tests/translator/output/microvm_image_with_build_role.json @@ -0,0 +1,36 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MicrovmImage with BuildRoleArn provided (no auto-generation)", + "Resources": { + "MyAgent": { + "Properties": { + "AdditionalOsCapabilities": [], + "BaseImageArn": "arn:aws:lambda:::microvm-image:lambda-microvms-al2023-2", + "BaseImageVersion": "0.4", + "BuildRoleArn": "arn:aws:iam::123456789012:role/MyCustomBuildRole", + "CodeArtifact": { + "Uri": "s3://my-bucket/agent.zip" + }, + "CpuConfigurations": [], + "Description": "", + "EgressNetworkConnectors": [], + "EnvironmentVariables": [], + "Hooks": {}, + "Logging": {}, + "Name": "my-agent", + "Resources": [], + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::MicrovmImage" + } + } +} diff --git a/tests/translator/output/network_connector.json b/tests/translator/output/network_connector.json new file mode 100644 index 000000000..5374eb6a9 --- /dev/null +++ b/tests/translator/output/network_connector.json @@ -0,0 +1,129 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Basic NetworkConnector with auto-generated OperatorRole", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123", + "subnet-0def456" + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/network_connector_globals.json b/tests/translator/output/network_connector_globals.json new file mode 100644 index 000000000..bbb57e0b5 --- /dev/null +++ b/tests/translator/output/network_connector_globals.json @@ -0,0 +1,84 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Test NetworkConnector with Globals support", + "Resources": { + "ConnectorOne": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd012" + ], + "SubnetIds": [ + "subnet-abc" + ] + } + }, + "Name": "connector-one", + "OperatorRole": "arn:aws:iam::123456789012:role/SharedOperatorRole", + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "ConnectorTwo": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "DualStack", + "SecurityGroupIds": [ + "sg-0abcd456" + ], + "SubnetIds": [ + "subnet-def" + ] + } + }, + "Name": "connector-two", + "OperatorRole": "arn:aws:iam::123456789012:role/SharedOperatorRole", + "Tags": [ + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "ManagedBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Staging" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + } + } +} diff --git a/tests/translator/output/network_connector_with_intrinsics.json b/tests/translator/output/network_connector_with_intrinsics.json new file mode 100644 index 000000000..b498977c5 --- /dev/null +++ b/tests/translator/output/network_connector_with_intrinsics.json @@ -0,0 +1,132 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with intrinsic functions in VpcConfig", + "Parameters": { + "SecurityGroupId": { + "Type": "String" + }, + "SubnetId": { + "Type": "String" + } + }, + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + { + "Ref": "SecurityGroupId" + } + ], + "SubnetIds": [ + { + "Ref": "SubnetId" + } + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/network_connector_with_operator_role.json b/tests/translator/output/network_connector_with_operator_role.json new file mode 100644 index 000000000..32465310e --- /dev/null +++ b/tests/translator/output/network_connector_with_operator_role.json @@ -0,0 +1,32 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with user-provided OperatorRole", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "DualStack", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123" + ] + } + }, + "OperatorRole": "arn:aws:iam::123456789012:role/CustomOperatorRole", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + } + } +} diff --git a/tests/translator/output/network_connector_with_propagate_tags.json b/tests/translator/output/network_connector_with_propagate_tags.json new file mode 100644 index 000000000..8a5f2456d --- /dev/null +++ b/tests/translator/output/network_connector_with_propagate_tags.json @@ -0,0 +1,136 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "NetworkConnector with PropagateTags flowing tags to auto-generated role", + "Resources": { + "MyNetworkConnector": { + "Properties": { + "Configuration": { + "VpcEgressConfiguration": { + "AssociatedComputeResourceTypes": [ + "MicroVm" + ], + "NetworkProtocol": "IPv4", + "SecurityGroupIds": [ + "sg-0abcd0ef" + ], + "SubnetIds": [ + "subnet-0abc123" + ] + } + }, + "OperatorRole": { + "Fn::GetAtt": [ + "MyNetworkConnectorOperatorRole", + "Arn" + ] + }, + "Tags": [ + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + }, + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::NetworkConnector" + }, + "MyNetworkConnectorOperatorRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:subnet/*" + }, + "Sid": "AllowCreateEniInAnySubnet" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:security-group/*" + }, + "Sid": "AllowCreateEniWithSecurityGroups" + }, + { + "Action": "ec2:CreateNetworkInterface", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:lambda:networkConnectorName", + "aws:lambda:networkConnectorId" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "AllowCreateEniWithLambdaTagKeys" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "StringEquals": { + "ec2:CreateAction": "CreateNetworkInterface", + "ec2:ManagedResourceOperator": "network-connectors.lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:network-interface/*" + }, + "Sid": "TagENIOnCreate" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "NetworkConnectorOperatorPolicy" + } + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + }, + { + "Key": "Environment", + "Value": "Production" + }, + { + "Key": "Team", + "Value": "Platform" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +}