Экспорт с именем ExRole уже экспортирован стеком Root -role - PullRequest
0 голосов
/ 05 августа 2020

Я хочу повторно использовать этот шаблон, но когда я загружаю этот шаблон с использованием вложенного стека, он выдает ошибку Export with name ExRole is already exported by stack Root-role. Как я могу улучшить возможность повторного использования шаблона. Так что я могу развернуть тот же шаблон в Prod, dev и других средах. Я пробовал использовать переменную среды в именах роли, но как я могу использовать ее в выходных данных и если выходные данные будут использоваться в следующем шаблоне, каким должен быть синтаксис?

Роль:

---
AWSTemplateFormatVersion: 2010-09-09 
Parameters:
  Env:
    Type: String
Resources:
  ExRole:
      Type: 'AWS::IAM::Role'
      Properties:
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - ecs-tasks.amazonaws.com
              Action:
                - 'sts:AssumeRole'
        Path: /
        RoleName: !Sub "excutionrole-${Env}"
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
        Policies: 
          - PolicyName: AccessECR
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action: 
                    - ecr:BatchGetImage
                    - ecr:GetAuthorizationToken
                    - ecr:GetDownloadUrlForLayer 
                  Resource: '*'

  ContainerInstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'               
        Statement:
          - Effect: Allow
            Principal: 
                Service: 
                    - ec2.amazonaws.com
            Action: 
                - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      Path: '/'
      RoleName: !Sub "ContainerInstanceRole-${Env}"
  

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties: 
      Roles: 
        - !Ref ContainerInstanceRole      

Outputs:
  
  ExRole:
    Description: Task excution role
    Value: !Ref ExRole
    Export:
        Name: "ExRole"
  InstanceProfile:
    Description: profile for container instances
    Value: !Ref InstanceProfile
    Export:
        Name: "InstanceProfile"            

Задача:

---
AWSTemplateFormatVersion: 2010-09-09 
Parameters:
    ExRole:
      Type: String
    RDS:
      Type: String
 
    DBUSER:
      Type: String
      Default: mysqldb

    DBPASSWORD:
      Type: String
      Default: 1234123a 
    
    DBNAME:
      Type: String
      Default: mysqldb 
Resources:
    Task:
        Type: AWS::ECS::TaskDefinition
        Properties:
            Family: wordpress 
            Cpu: 1 vCPU
            ExecutionRoleArn: !Ref ExRole
            Memory: 1 GB
            NetworkMode: bridge
            RequiresCompatibilities:
                - EC2
            TaskRoleArn: !Ref ExRole
            ContainerDefinitions: 
              - Essential: true
                Image: wordpress:latest
                Name: wordpress
                PortMappings:  
                  - ContainerPort: 80
                    HostPort: 0
                    Protocol: tcp 
                Environment:
                  - Name: WORDPRESS_DB_HOST
                    Value: !Ref RDS 
                  - Name: WORDPRESS_DB_USER
                    Value: !Ref DBUSER 
                  - Name: WORDPRESS_DB_PASSWORD
                    Value: !Ref DBPASSWORD
                  - Name: WORDPRESS_DB_NAME
                    Value: !Ref DBNAME
    
Outputs:
  Task:
    Description: Contains all the task specifications
    Value: !Ref Task
    Export:
      Name: "Task"

Root:

Resources:
  Vpcstack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/vpc.yml"
      Parameters:  
        Env: !Ref Env
        Cidr: !Ref Cidr
        Publicsubnet1: !Ref Publicsubnet1
        Publicsubnet2: !Ref Publicsubnet2
        Privatesubnet1: !Ref Privatesubnet1
        Privatesubnet2: !Ref Privatesubnet2  

  role:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/role.yml"
      Parameters:  
        Env: !Ref Env

1 Ответ

1 голос
/ 05 августа 2020

Обычно, когда люди используют вывод, если шаблон используется несколько раз в одном родительском стеке, они добавляют к экспорту префикс переменной (например, имя стека), чтобы сделать его уникальным.

Это может выполняется с помощью функции sub intrinsi c , например, как в приведенном ниже примере

Outputs:
  ExRole:
    Description: Task excution role
    Value: !Ref ExRole
    Export:
        Name: !Sub "${AWS::StackName}-ExRole"
  InstanceProfile:
    Description: profile for container instances
    Value: !Ref InstanceProfile
    Export:
        Name: !Sub "${AWS::StackName}-InstanceProfile"

Затем вам нужно будет передать это значение идентификатора стека в качестве параметра во вложенный стек, который необходимо указать этот файл. Это снова будет использовать функцию sub intrinsi c для ссылки на имя экспорта.

Чтобы получить это значение в функции ImportValue intrinsi c, вы должны ссылаться на него, как показано ниже, для этого вам потребуется для передачи имени стека в качестве параметра в стек:

Fn::ImportValue: !Sub "${NestedStack}-ExRole"

Если вы вызываете другой стек из родительского стека, вы можете игнорировать экспорт и вместо этого передавать вывод в следующий стек с помощью встроенного GetAtt c вместо функции.

Resources:
  Vpcstack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/vpc.yml"
      Parameters:  
        Env: !Ref Env
        Cidr: !Ref Cidr
        Publicsubnet1: !Ref Publicsubnet1
        Publicsubnet2: !Ref Publicsubnet2
        Privatesubnet1: !Ref Privatesubnet1
        Privatesubnet2: !Ref Privatesubnet2  

  role:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/role.yml"
      Parameters:  
        Env: !Ref Env
        
  dbStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/db.yml"
      Parameters:  
        Role: !GetAtt role.Outputs.ExRole

Вы также можете использовать синтаксис Fn::GetAtt: [role, Outputs.ExRole] also valid syntax.

...