Miserlou / Zappa

Serverless Python
https://blog.zappa.io/
MIT License
11.89k stars 1.21k forks source link

Custom CloudFormation resources // Add "template" command #634

Open kadrach opened 7 years ago

kadrach commented 7 years ago

Is there a facility to include custom CloudFormation resources in the generated CF stack? My APIs often require some kind of data source, e.g. a DynamoDB table.

The template is already generated via troposphere, it'd be nice to hook into this and add a resource. (And wishful thinking - Zappa to translate Ref where required).

Also, the CF stack does not generate outputs (or I can't see the switch to enable them), so the stack cannot be reused in a nested template.

Miserlou commented 7 years ago

More than willing to entertain this idea.

My initial thought was that Zappa would be the one spitting out the template, but also would be willing to go the other way. Propose an interface?

kadrach commented 7 years ago

The other way around is feasible too - probably easier to integrate with existing toolchains. I'm not sure what the best solution would be.

Miserlou commented 7 years ago

Seeking in put on a template command from @collingreen @mathom @bjinwright and others

What are the users-stories around this? Is it okay for template to deploy to S3? The issue I see is that it requires an exiting Lambda ARN..

mathom commented 7 years ago

In my original PR I had more of Zappa templated, but the problem is you have to maintain a zip for lambda in s3 to be able to manage that bit. There are probably a few other gotchas related to how the other commands work as well.

geeknam commented 7 years ago

I'm at the moment using Zappa with Sceptre: https://github.com/cloudreach/sceptre to do this. Sceptre can also be invoked using python which is why it would be suitable for Zappa. I strongly recommend looking at sceptre rather than implementing own code to manage CF.

gmeans commented 7 years ago

Originally I was interested in this as well, but thinking more on it I'd say a good half step is simply using Outputs and Exporting the relevant Zappa bits. Especially the API Gateway URL.

Another thought might be looking at integrating Zappa with the aws CLIs package and deploy commands. In theory Zappa could package and prepare the app, then drop a CFN template referring to the package using a relative path.

The prepared Zappa template should have parameters that could be set for things.

Some advantages to this would be:

aehlke commented 7 years ago

Starting with Exports would be a huge help, as long as zappa works by changing the existing stack rather than deleting and recreating it (I haven't checked).

Another very nice use case would be to import values from other CloudFormation stacks within my zappa config. I often have to either hardcode these values from other stacks (and then manually update them later), or create an awkward deploy pipeline where I dynamically generate the zappa config file after querying CloudFormation for stack values. An example of this is VPC subnets, security groups. I'm actually not sure if there're other compelling use-cases for this... Maybe S3 buckets. Neither of these should change frequently unless we're maybe redeploying from scratch for blue/green reasons, or creating new regions, etc. so maybe this isn't a worthwhile feature.

Miserlou commented 7 years ago

Would love to see a proposal on an interface to some of these features..

gmeans commented 7 years ago

In regards to the outputs, I'd propose that any Zappa created resource (S3 bucket, IAM role, API Gateway, etc..) be made available for reference via exported outputs.

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html

I looked though, and I believe only the API Gateway pieces are build using a CF stack. Is that correct?

Exports must be globally unique across the AWS account, so a naming convention similar to how the stack name is created would be necessary. For this, though, I'd use CloudFormations convention for resources.

<ProjectName><StageName><Export>

MyZappaAppDevURL MyZappaAppDevS3Bucket

For generating the CF template, there is a related issue on troposphere's repo:

https://github.com/cloudtools/troposphere/issues/567

But my preference would be to have a generate command:

zappa generate <stage> --output-file=zappa_app.yaml

Without output-file the command generates to the console, with it the file extension is parsed for the format (YAML / JSON).

The template that gets output can be deployed on its own using aws cloudformation deploy or it can be referenced as a nested stack within a larger app template. All configuration variables are output as Parameters so that they can be overridden in a nested stack using CF's !Ref syntax.

I think something like this would require all resources to be provisioned using a CF template though. Not sure what the LOE on that would be.

aehlke commented 7 years ago

You can still declare exports in a CFN stack for resources created outside that stack, as a workaround. As long as Zappa provisions those resources simultaneously with creating the stack (and before creating the stack), it should be safe enough.

Decoupling stack deployment from everything else in Zappa would make this dangerous (i.e. your generate proposal) so I'd say having everything be provisioned by CloudFormation would be a blocker on that.

Miserlou commented 7 years ago

There is now a template command which spits out the simple CF template we use. I needed it for a thing.

I'm not really happy with it because it can't create other resources, so I'm leaving this ticket up open for now until I change my mind.

aehlke commented 7 years ago

I want to experiment next with using zappa package + managing the cloudformation template independently, deploying it via awscli or sceptre. This might be a learning opportunity to see how to best adapt Zappa. I wonder whether longer term it makes sense to narrow the scope of what Zappa itself provides, and integrate with more canonical tooling for other parts.

gmeans commented 7 years ago

I was able to deploy the results of zappa package using Amazon's SAM templates but ran into a couple of gaps.

That's as far as I took it, but I don't think its far off.

aehlke commented 7 years ago

Seems someone got binary support working in Cloudformation at the end here: https://forums.aws.amazon.com/thread.jspa?threadID=243438

gmeans commented 7 years ago

I tried this in a SAM template and it didn't work. It fails with an error stating that it isn't supported.

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  ApplicationLambda:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: handler.lambda_handler
      Runtime: python2.7
      CodeUri: ./src/server/app-prod-1493327007.zip
      MemorySize: 512
      Events:
        Root:
          Type: Api
          Properties:
            Path: /
            Method: any
        ApplicationResource:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: any
            x-amazon-apigateway-binary-media-types: "*/*"
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Transform AWS::Serverless-2016-10-31 failed with: Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [ApplicationLambdaApplicationResource] is invalid. property x-amazon-apigateway-binary-media-types not defined for resource of type Api
aehlke commented 7 years ago

Thanks! Next I'd be interested to try this with a non-SAM CloudFormation template.

Miserlou commented 7 years ago

I have a Terraform based one that is semi-working, but honestly it seems like Zappa is better at setting this stuff up itself than the other tools..

On Fri, Apr 28, 2017 at 12:44 PM, Alex Ehlke notifications@github.com wrote:

Thanks! Next I'd be interested to try this with a non-SAM CloudFormation template.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Miserlou/Zappa/issues/634#issuecomment-298048014, or mute the thread https://github.com/notifications/unsubscribe-auth/AAIi01sp0AW1fTzGNiUdSuZubRFSOg2uks5r0hdggaJpZM4Lw9c- .

gmeans commented 7 years ago

Ok, I ended up getting a response from AWS regarding the permissions issue and they said sometimes IAM roles can take longer to propagate than usual and that's why I had some issues. So, at the moment, this template works:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  ApplicationLambda:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: handler.lambda_handler
      Runtime: python2.7
      CodeUri: ./src/server/app-prod-1493327007.zip
      MemorySize: 512
      Policies:
        - AWSLambdaExecute
        - AWSLambdaFullAccess
      Events:
        Root:
          Type: Api
          Properties:
            Path: /
            Method: any
        ApplicationResource:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: any

I'm using AWS managed policies vs. the zappa created role and it looks to be working.

aehlke commented 7 years ago

I have a Terraform based one that is semi-working, but honestly it seems like Zappa is better at setting this stuff up itself than the other tools..

CloudFormation is particularly compelling for a few reasons:

That's what comes to mind from my own experiences.

gmeans commented 7 years ago

Jeff Barr just tweeted out this serverless plugin:

https://github.com/SAPessi/serverless-sam

It exports a SAM template that can be used via the AWS CLI.

marcinzaremba commented 7 years ago

What I see from this discussion Zappa is offering very wide feature set and it seems it is starting to be too opinionated and limiting when comes to parts other than Lambda <-> WSGI bridge + nice Lambda packaging utility (utilizing bridge mentioned). How about splitting the project to smaller pieces (starting from Lambda <-> WSGI bridge) while keeping framework (which Zappa is right now) as a recommended way of using it / quick start? What Zappa is trying to do right now:

It would definitely simplify things after split and get broader audience to adapt/utilize smaller parts currently needed.

milesgranger commented 3 years ago

I'd be quite satisfied if Zappa supported !ImportValue for things like security groups, or really anything that might go in a normal zappa config file that might reference some infrastructure resource.