@warpdreams/cloudatlas

0.2.1 • Public • Published

Cloudatlas

npm version

Overview

Cloudatlas is a CLI tool to produce, deploy and update AWS CloudFormation stacks.

The idea is to construct a comprehensive AWS CloudFormation stack with minimum scripting via Javascript, while shielding the user from boilerplate details and providing out-of-the-box best practises.

Install and Use Cloudatlas

You can find the complete source code for the example of this section at here

1. Requirements

To run the Cloudatlas CLI, you need to have node V8.0 or above.

2. Install Cloudatlas:

npm install --save-dev @warpdreams/cloudatlas

3. Update your package.json file

In your package.json, add section cloudatlas:

//file package.json

{   
  "cloudatlas": {
    "source": "hello-stack-cloudatlas",
    "stacks": [
      {
        "name": "hello-stack",
        "lambdaSourceFiles": [
          "hello-lambda.js",
          "node_modules/**/*"
        ]
      }
    ],

    "bucket": {
      "region": "ap-southeast-2",
      "name": "your-s3-bucket"
    }
  }
}

  

It's convienient to add a shortcut to the cloudatlas cli in your package.json file, under scripts

  "scripts": {
    "cloudatlas": "node ./node_modules/@warpdreams/cloudatlas/bin/cloudatlas.js"
  }

hello-stack-cloudatlas is the Cloudatlas stack assembly script you need to write (described in the below section).

bucket declares a utility AWS S3 bucket which you should have write access to. Cloudatlas will use this bucket to do bookkeepings.

4. Writing The Cloudformation Stack Script

The script is where you assemble your stack. The following code shows a simple Cloudformation stack that has a Lambda and an API Gateway component:

//File: hello-stack-cloudatlas.js

const assert = require('assert');

const {
  Lambda,
  ApiGateway
}
  = require('@warpdreams/cloudatlas');

//The swagger JSON file for API Gateway
const swagger = require('./hello-stack-api-swagger.json');

//Stack components
let helloLambda = null;
let helloAPIGateway = null;

//
//This is the callback function to implement for Cloudatlas
//
const wireStack = (name, stack) => {
  helloLambda = stack.createLambda('hello');
  helloLambda.setHandlerPath('hello-lambda.handler');
  helloAPIGateway = stack.createApiGateway('hello');
  helloAPIGateway.setSwagger(swagger);

  //Connect API Gateway to Lambda.
  //Specify the method via which the Lambda is invoked. 
  //Also provides automatic HTTP status code mapping via text pattern
  helloAPIGateway.attachLambda(helloLambda, '/hello', ['GET'], {
    '.*Invalid parameters.*': {
      statusCode: 400
    }
  });

  helloAPIGateway.setDeploymentStages(['alpha', 'beta']);
}

exports.wireStack = wireStack;

5. Setting the Environment Variables

Please make sure your AWS credential is defined as environment variables:

export AWS_REGION="ap-southeast-2"
export AWS_ACCESS_KEY_ID="YOUR_ AWS_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="YOUR_ AWS_SECRET_ACCESS_KEY"

Also make sure the above credential has write access to the utility S3 bucket your-s3-bucket.

Set the environment for the stack by doing:

export NODE_ENV=dev

Cloudatlas will deploy different copies of the stack depends on the value of NODE_ENV, thus it is recommended to always set NODE_ENV before deployment.

6. Deploying the Stack

If you added cloudatlas into scripts section of your package.json as shown previously, you can just do:

npm run cloudatlas -- deploy

The deploy command will do all the followings in one go:

  • Zip up the source codes for Lambda (if any) and save files locally at .cloudatlas of your project
  • Upload the package to the utility S3 bucket
  • Deploy the stack to Cloudformation

If you'd like to double check things before deployment, you can also run the following

# Zips up source codes and write CloudFormation template file to .cloudatlas
npm run cloudatlas -- package

# Upload the package to S3
npm run cloudatlas -- upload

For more debugging information, add flag -v or --verbose

Currently Supported AWS Components

  • API Gateway
  • Lambda
  • Cognito User Pool
  • Coginito Identity Pool connecting to User Pool
  • DynamoDB
  • S3
  • GenericComponent for all other AWS components not listed above

Import them with the following clause:

const {
  CloudFormation,
  Lambda,
  Policy,
  ApiGateway,
  DynamoDbTable,
  CognitoUserPool,
  CognitoUserPoolAppClient,
  CognitoUserGroup,
  S3,
  GenericComponent
} = require('@warpdreams/cloudatlas');

To Use Other AWS Components

If the component you want to use is not listed above, you can always use a generic component provided by Cloudatlas:

const {
  GenericComponent
} = require('@warpdreams/cloudatlas');

Here is some sample code to write a Lambda with GenericComponent (Lambda is directly supported by Lambda class, but we pretend it isn't for the demoing purpose)

const stack = new CloudFormation('TheStack');
const lambda = stack.createGenericComponent('Lambda');

//This is the "Type" field of CloudFormation
lambda.type = "AWS::Lambda::Function";

const theProperties = {
  "Code": {
    "S3Bucket": "TestBucket",
    "S3Key": "Test.zip"
  },
  "Handler": "src/hander.js",
  "Runtime": "nodejs8.10",
  "Timeout": 10,
  "MemorySize": 128,


  // The role field will be automatically replaced 
  // if policyStatements and assumeRolePolicyDocument is set
  // "Role": null,
  "Description": "",
  "Environment": {
    "Variables": {}
  }
};
//This is the "Properties" field of CloudFormation
lambda.properties = theProperties;

lambda.assumeRolePolicyDocument = {
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }]
}

lambda.policyStatements = [{
    "Effect": "Allow",
    "Action": "logs:CreateLogGroup",
    "Resource": {
      "Fn::Join": [
        "", [
          "arn:aws:logs:",
          {
            "Ref": "AWS::Region"
          },
          ":",
          {
            "Ref": "AWS::AccountId"
          },
          ":*"
        ]
      ]
    }
  },
  {
    "Effect": "Allow",
    "Action": [
      "logs:CreateLogStream",
      "logs:PutLogEvents"
    ],
    "Resource": {
      "Fn::Join": [
        "", [
          "arn:aws:logs:",
          {
            "Ref": "AWS::Region"
          },
          ":",
          {
            "Ref": "AWS::AccountId"
          },
          ":log-group:*"
        ]
      ]
    }
  }
]

API Docs

Find it here

Using Cloudatlas With Serverless

Cloudatlas can generate a serverless.yml file for your stack. Just run:

npm run cloudatlas -- upload --gen-serverless-yml

You can then find serverless.yml under .cloudatlas with which you can use Serverless to manage.

Comparison to Alternative Options

Cloudatlas vs Writing CloudFormation JSON/YML Template File Directly

Needless to say, you need to manage every inch of details for CloudFormation.

Cloudatlas vs Serverless with AWS Plugins

You need to find plugins for different AWS components if you need more than the most basic usage of Lambda and API Gateway. Different plugins may not be compatible with each other and may not provide all the configuration options you need. Then you resort to writing resources section in serverless.yml which is essentially writing the CloudFormation template file.

Practical Examples

Here is a list of example projects that are more realistic than "Hello World".

Two Stacks

This project contains usage of following:

  • Uses AWS Cognito User Pool for user registration;
  • Uses AWS Coginito Identity Pool and IAM for access control;
  • Uses DynamoDB for data;
  • Uses S3 for static web site hosting;
  • Uses Lambda for server logic and API Gateway for endpoints;
  • API Gatway access is regulated via IAM;
  • DynamoDB access via Lambda is regulated via IAM;
  • S3 write access via Lambda is regulated via IAM

You can check the this example here

(more examples to follow)

Package Sidebar

Install

npm i @warpdreams/cloudatlas

Weekly Downloads

0

Version

0.2.1

License

MIT

Unpacked Size

153 kB

Total Files

43

Last publish

Collaborators

  • alienbat