aws / copilot-cli

The AWS Copilot CLI is a tool for developers to build, release and operate production ready containerized applications on AWS App Runner or Amazon ECS on AWS Fargate.
https://aws.github.io/copilot-cli/
Apache License 2.0
3.51k stars 408 forks source link

Should I be using environment override or addon? #5908

Open proof-nicholas opened 2 months ago

proof-nicholas commented 2 months ago

Hi,

I have a use case where I want to add VPC endpoints to my environment. I initially tried adding them as addons but the interface endpoints have a dependency on the VPC and its subnets created in the environment stack, so I tried adding the following, as an example:

  ECRAPIInterfaceEndpoint:
    Type: "AWS::EC2::VPCEndpoint"
    Properties:
      VpcEndpointType: "Interface"
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.api"
      VpcId: !Ref VPC
      PrivateDnsEnabled: true
      SubnetIds:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      SecurityGroupIds:
        - !Ref vpcEndpointSecurityGroup

But wound up with the following error:

deploy environment pv-preview-vpc-endpoints: wait for creation of change set copilot-0022c201-6c92-47ef-accb-43c5c4e04625 for stack app-pv-preview-vpc-endpoints: ResourceNotReady: failed waiting for successful resource state: Template format error: Unresolved resource dependencies [PrivateSubnet1, PrivateSubnet2, VPC, PublicSubnet2, PublicSubnet1] in the Resources block of the template

I'm assuming this is because the addons are deployed as nested stacks before the environment stack and therefore the resources don't exist yet? For this use case, should I instead be using the override feature?

Thanks

proof-nicholas commented 2 months ago

Actually it looks like addons will work, missed this part in the documentation (although I do think it can be called out more prominently in the documentation):

"In your addons.parameters.yml, define the values of those additional parameters. They can refer to values from your environment stack."

proof-nicholas commented 2 months ago

Although I did just try it with addons.parameters.yml:

Parameters:
  VPC: !Ref VPC
  PrivateRouteTable1: !Ref PrivateRouteTable1
  PrivateRouteTable2: !Ref PrivateRouteTable2
  PrivateSubnet1: !Ref PrivateSubnet1
  PrivateSubnet2: !Ref PrivateSubnet2
  PublicSubnet1: !Ref PublicSubnet1
  PublicSubnet2: !Ref PublicSubnet2
  PublicRouteTable: !Ref PublicRouteTable

Still getting:

copilot env deploy --name pv-preview-vpc-endpoints
✔ Proposing infrastructure changes for the app-pv-preview-vpc-endpoints environment.
✘ deploy environment pv-preview-vpc-endpoints: check if changeset is empty: create change set copilot-45df89c2-90f2-455d-a021-f7070ba66439 for stack app-pv-preview-vpc-endpoints: ValidationError: Template format error: Unresolved resource dependencies [PrivateRouteTable2, PrivateRouteTable1] in the Resources block of the template
    status code: 400, request id: 1f787d39-b59c-4031-9153-0bc11fcac891: describe change set copilot-45df89c2-90f2-455d-a021-f7070ba66439 for stack app-pv-preview-vpc-endpoints: ChangeSetNotFound: ChangeSet [copilot-45df89c2-90f2-455d-a021-f7070ba66439] does not exist
    status code: 404, request id: c937ff85-acd3-4d0b-bcb6-8db8f0134858

And my addon manifest is as follows:

Parameters:
  App:
    Type: String
  Env:
    Type: String
  VPC:
    Type: String
  PrivateRouteTable1:
    Type: String
  PrivateRouteTable2:
    Type: String
  PrivateSubnet1:
    Type: String
  PrivateSubnet2:
    Type: String
  PublicSubnet1:
    Type: String
  PublicSubnet2:
    Type: String
  PublicRouteTable:
    Type: String

  S3VPCEndpoint:
    Type: "AWS::EC2::VPCEndpoint"
    Properties:
      VpcEndpointType: "Gateway"
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcId: !Ref VPC
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal: "*"
            Action:
              - "s3:GetObject"
            Resource:
              - !Sub "arn:aws:s3:::prod-${AWS::Region}-starport-layer-bucket/*"
      RouteTableIds:
        - !Ref PrivateRouteTable1
        - !Ref PrivateRouteTable2
        - !Ref PublicRouteTable
proof-nicholas commented 2 months ago

Scratch that, I see the problem: PrivateRouteTable2, PrivateRouteTable1 have conditions attached to their creation (on CreateNATGateways) and the condition is not fulfilled. I have to add the same to my addon.

proof-nicholas commented 2 months ago

It still didn't seem to work. It seems the addon is deployed as a nested stack and the VPC resources don't exist yet. I used the override capability and that seemed to work well.

proof-nicholas commented 1 month ago

Any comments?

Lou1415926 commented 1 month ago

It still didn't seem to work. It seems the addon is deployed as a nested stack and the VPC resources don't exist yet. I used the override capability and that seemed to work well.

The addon is indeed deployed as a nested stack, but what you specified in the addons.parameters.yml should introduce a dependency graph such that the addon resources are created after the VPC resources in the main stack.

I suspect that it is the CreateNATGateways condition, like you said, that's preventing you from deploying the addons.

If you are still interested in getting the addons to work, would you be able to share the error message after you fixed the condition?

And just to make sure - override is working for you right? I asked because this would potentially help me diagnose what's wrong with your addons.