""" Companion stack template builder """ from typing import Dict, cast from samcli.lib.bootstrap.companion_stack.data_types import CompanionStack, ECRRepo from samcli.lib.bootstrap.stack_builder import AbstractStackBuilder class CompanionStackBuilder(AbstractStackBuilder): """ CFN template builder for the companion stack """ _parent_stack_name: str _companion_stack: CompanionStack _repo_mapping: Dict[str, ECRRepo] def __init__(self, companion_stack: CompanionStack) -> None: super().__init__("AWS SAM CLI Managed ECR Repo Stack") self._companion_stack = companion_stack self._repo_mapping: Dict[str, ECRRepo] = dict() self.add_metadata("CompanionStackname", self._companion_stack.stack_name) def add_function(self, function_logical_id: str) -> None: """ Add an ECR repo associated with the function to the companion stack template """ self._repo_mapping[function_logical_id] = ECRRepo(self._companion_stack, function_logical_id) def clear_functions(self) -> None: """ Remove all functions that need ECR repos """ self._repo_mapping = dict() def build(self) -> str: """ Build companion stack CFN template with current functions Returns ------- str CFN template for companions stack """ for _, ecr_repo in self._repo_mapping.items(): self.add_resource(cast(str, ecr_repo.logical_id), self._build_repo_dict(ecr_repo)) self.add_output(cast(str, ecr_repo.output_logical_id), CompanionStackBuilder._build_output_dict(ecr_repo)) return super().build() def _build_repo_dict(self, repo: ECRRepo) -> Dict: """ Build a single ECR repo resource dictionary Parameters ---------- repo ECR repo that will be turned into CFN resource Returns ------- dict ECR repo resource dictionary """ return { "Type": "AWS::ECR::Repository", "Properties": { "RepositoryName": repo.physical_id, "Tags": [ {"Key": "ManagedStackSource", "Value": "AwsSamCli"}, {"Key": "AwsSamCliCompanionStack", "Value": self._companion_stack.stack_name}, ], "RepositoryPolicyText": { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowLambdaSLR", "Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com"]}, "Action": ["ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:BatchGetImage"], } ], }, }, } @staticmethod def _build_output_dict(repo: ECRRepo) -> str: """ Build a single ECR repo output resource dictionary Parameters ---------- repo ECR repo that will be turned into CFN output resource Returns ------- dict ECR repo output resource dictionary """ return f"!Sub ${{AWS::AccountId}}.dkr.ecr.${{AWS::Region}}.${{AWS::URLSuffix}}/${{{repo.logical_id}}}" @property def repo_mapping(self) -> Dict[str, ECRRepo]: """ Repo mapping dictionary with key as function logical ID and value as ECRRepo object """ return self._repo_mapping