Code Monkey home page Code Monkey logo

cdk-utils's Introduction

@vamship/cdk-utils

A library of utilities that will allow CDK projects to be composed from modular files

API Documentation

API documentation can be found here.

Motivation

AWS CDK provides a much needed improvement over hand crafted cloud formation scripts, by allowing the use of imperative statements to generate a declarative cloudformation json/yaml file.

However, this library is still limited by the fact that all of the cloud formation configuration for a stack resides in a single file, which can make the file verbose and hard to manage as the size of the stack grows.

This library attempts to address this limitation by providing a few utilities that allow:

  • Creation of stacks by loading resources defined within individual files instead of cramming multiple resource configurations into a single file.
  • The ability to use the organization of resource files on the file system to while configuring the resources. For example, resources that represent different API routes can be automatically configured based on the path to the resource.

While this project draws its inspiration from the now defunct wysknd-aws-cf-generator, it now leverages the CDK which is supported by AWS.

Installation

This package can be installed using npm:

npm install --save-dev @vamship/cdk-utils

Usage

This library exposes two key components that allow the development of CDK resources:

  • ConstructFactory: This is a class that serves as a lightweight wrapper around the initialization and configuration of CDK resources.
  • ConstructBuilder: This class recursively traverses the file system, and loads and initializes all resources found on the file system. Only resources of type ConstructFactory are loaded, and all other resources are ignored.

Example

File Organization

This example assumes the following file structure:

infra
├── constructs
│   ├── functions
│   │   └── hello-func.js
│   └── tables
│       ├── products-table.js
│       └── users-table.js
└── index.js

As seen above, the directory structure has a main entry point index.js, and a directory structure, where each file defines a single resource. The entrypoint defines an instance of the ConstructBuilder class, and uses it to traverse the directory structure under constructs. Each resource under constructs defines a resource (dynamodb table/lambda function/etc.) which is wrapped inside a ConstructFactory.

Entrypoint

The content of a simple entrypoint file is shown below:

#!/usr/bin/env node

const _path = require('path');

const { App } = require('@aws-cdk/core');
const { ConstructBuilder } = require('@vamship/cdk-utils');

const { Stack } = require('@aws-cdk/core');

// Initialize stacks
const app = new App();
const stack1 = new Stack(app, 'my-stack-1');
const stack2 = new Stack(app, 'my-stack-2');

// Build out stack using resources under the constructs directory
const rootDir = _path.join(__dirname, 'constructs');

// Initialize builder
const builder = new ConstructBuilder(rootDir);

// Build out the stacks using custom props if necessary
builder.build(stack2, { keyName: 'username' });
builder.build(stack1, { keyName: 'id' });

NOTE: The construct builder class exposes a prefetchConstructs() method that can be used to asynchronously load modules prior to building. If not invoked, the constructs will be loaded synchronously at build time.

Constructs

The contents of the users-table.js file is shown below:

'use strict';

const { ConstructFactory } = require('@vamship/cdk-utils');
const _dynamodb = require('@aws-cdk/aws-dynamodb');

const factory = new ConstructFactory('user-table');

factory._init = (scope, id, dirInfo, props) => {
    return new _dynamodb.Table(scope, 'UsersTable', {
        partitionKey: {
            name: props.keyName,
            type: _dynamodb.AttributeType.STRING,
        },
    });
};

factory._configure = () => {
    console.log('Configuring user table');
};

module.exports = factory;

Each resource is initialized by overriding the _init() method, and returning the initialized resource.

NOTE: The method to be overridden is _init(), not init(). Getting this wrong will cause unexpected problems. Also remember to return the initialized construct from within the method

The _configure() method is intended for configuration of the resource after all resources have been initialized. This method can be used to set up relationships between resources (granting a function permissions on a table, for example).

NOTE: The method to be overridden is _configure(), not configure(). Getting this wrong will cause unexpected problems.

The following is an example of the use of the _configure() method to setup permissions, in the hello-func.js file:

'use strict';

const { ConstructFactory } = require('@vamship/cdk-utils');
const _lambda = require('@aws-cdk/aws-lambda');
const _path = require('path');

const userTableConstruct = require('../tables/users-table');

const factory = new ConstructFactory('hello-func');

const handlerPath = _path.resolve(__dirname, '../../../src/');
console.log(handlerPath);

factory._init = (scope, id, dirInfo, props) => {
    return new _lambda.Function(scope, id, {
        runtime: _lambda.Runtime.NODEJS_10_X,
        handler: 'index.handler',
        code: _lambda.Code.fromAsset(handlerPath),
    });
};

// Here, the parameter "construct" is a reference to the construct created
// in the _init() method.
factory._configure = (construct, scope, dirInfo, props) => {
    // Get a reference to the initialized table construct.
    const userTable = userTableConstruct.getInstance(scope);

    // Allow the function to access the userTable
    userTable.grantFullAccess(construct);
};

module.exports = factory;

Contributing

Before submitting pull requests, please make sure to run through automated pre commit tests/linting checks/formatting by running:

grunt all

cdk-utils's People

Contributors

vamship avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.