Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/seikho/ship-it
Quick, dirty, and all batteries included AWS Lambda Deployment
https://github.com/seikho/ship-it
aws deployment lambda nodejs typescript
Last synced: 5 days ago
JSON representation
Quick, dirty, and all batteries included AWS Lambda Deployment
- Host: GitHub
- URL: https://github.com/seikho/ship-it
- Owner: Seikho
- Created: 2017-06-07T10:52:38.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2017-08-24T04:09:06.000Z (about 7 years ago)
- Last Synced: 2024-04-24T00:44:12.766Z (7 months ago)
- Topics: aws, deployment, lambda, nodejs, typescript
- Language: TypeScript
- Homepage:
- Size: 70.3 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Project SHIPIT: AWS REST Lambda Deployment
## Purpose
The purpose of this library is to create small projects or services that have their deployment configuration baked in.This is to minimise the configuration necessary on Continuous Integration (CI) platforms such as Jenkins,
but to still retain a sane deployment with staged environments.## How to include external dependencies
I recommend the use of `browserify`. Include it was a `devDependency` in your project
In `package.json` include a `bundle` script that looks like this:
```sh
"bundle": "browserify -e src/index.js -o bundle.js --standalone --bare -x aws-sdk"
```- `e src/index.js`: This is an example of providing the entry point to your Lambda
- `-o bundle.js`: This is an example of providing an output location for your bundle
- `--standalone`: Outputs a UMD module which will preserve your module exports for using by Lambda
- `--bare`: Will exclude Node standard libraries from the bundle
- `x aws-sdk`: Will exclude `aws-sdk` from the bundle as it is implicitly provided by the Lambda environmentIn your `.registerLambda()`.`files` property, provide `bundle.js` instead of all of the individual modules.
## Gotchas
### Names are Important
The names are important for maintaing the link between `Deployer` consumption and services on AWS.
If the Lambda function or API name are renamed, artifacts will remain on AWS that may be running that are not intended.
If this happens the services must be removed by using the AWS Console (user interface) or by other means.
### Lambdas / RestAPIs must not be shared between projects and `Deployer` instances
**Policies, permissions, and RestAPI resources are deleted during each `.deploy()` call**
**Ensure that RestAPIs (names) and Lambda (names) are not shared between projects and other instances of the `Deployer`.**
## Release Notes
#### v0.6.0
- [Feature] Support POST body
- See `LambdaEvent` type#### v0.5.0
- [Feature] Add support for Lambda VPC configuration#### v0.4.0
- [Feature] Add support for Lambda run-time environment variables#### v0.3.0
- [Breaking] Delete all APIGateway resources and Lambda policies at the beginning of each deploy#### v0.2.x
- [Bugfix] Fix config validation log messages
- [Bugfix] Fix CloudWatchEvent.putTargets call#### v0.2.0
- [Feature/Breaking] Make Lambdas re-usable between callers
- [Feature] Fallback to environment for Deployer config
- [Feature] Support CloudWatchEvents as callers
- [Breaking] Move Lambda registration to `Deployer.registerLambda()`
- [Breaking] Rename `Deployer.register()` to `Deployer.registerCaller()`## Usage
### Requirements
**Functional Requirements**
- AWS Account ID
- Found in AWS Console -> Support -> Support Center -> Top right corner
- AWS API Access
- AWS secret (Region, Access Key ID, Secret Access Key)
- AWS Role with full lambda access
- API Gateway name (User determined, Must be unique)
- Lambda Function names (User determined, Each must be unique)### API
**Example usage**
```js
import * as path from 'path'
import Deployer from 'ship-it'const deployer = new Deployer({
apiName: 'My Rest API',
accountId: '1234567890',
region: 'ap-southest-2',
accessKeyId: '....',
secretAccessKey: '....',
role: 'arn:aws:iam::1234567890:role/some-role-name'
})// This returns a RegisteredLambda object which can be re-used by callers
const lambda = deployer.registerLambda({
description: 'My Lambda Function',
files: [path.resolve(__dirname, 'handlers', 'index.js')],
functionName: 'My-Lambda-Function',
handler: 'index.handler'
})deployer.registerCaller({
kind: 'api',
lambda, // Needs to be a RegisteredLambda from .registerLambda
method: 'GET',
path: '/users/42',
contentType: 'application/json'
})deployer.registerCaller({
kind: 'event',
lambda,
name: 'event-name',
schedule: 'rate(1 minute)', // Is a Schedule expression, See: http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
description: 'Trigger my Lambda'
})// Is asynchronous
deployer.deploy()
```#### LambdaEvent
```ts
export type LambdaEvent = {
body: { [key: string]: any }
params: { [pathPart: string]: string }
query: {
[key: string]: string
}
header: {
[header: string]: string
}
method: string
}
```#### Deployer
Some configuration will coalesce to specific environment variables:
- `apiName` -> `process.env.AWS_API_NAME`
- `accountId` -> `process.env.AWS_ACCOUNT_ID`
- `region` -> `process.env.AWS_REGION`
- `accessKeyId` -> `process.env.AWS_ACCESS_KEY_ID`
- `secretAccessKey` -> `process.env.AWS_SECRET_ACCESS_KEY`
- `role` -> `process.env.AWS_ROLE````ts
interface ConstructorParams {// Must be unique
apiName: string// Found in AWS console
accountId: string// AWS Region
region: string// Provided by AWS when creating an API key pair
accesskeyId: string// Provided by AWS when creating an API key pair
secretAccessKey: string// Provided by AWS when creating an IAM role
role: string
}
constructor(params: ConstructorParams)
```#### Deployer.registerLambda
```ts
function registerLambda(lambda: Lambda): RegisteredLambda
``````ts
interface RegisteredLambda extends Lambda {
id: number
}type File =
| string
| { path: string, folder: string }interface Lambda {
/**
* Formal Lambda function name
* Must be unique
*/
functionName: string/**
* Human readable description of the Lambda function
*/
description: string/**
* [filename].[function].
* E.g. 'index.handler'
* Where:
* - 'index.js' is in the root of the archive
* - 'handler' is exported as 'export function handler(...)'
*/
handler: string// Defaults to 128
memorySize?: number// Defaults to 15
timeout?: number/**
* Environment variables for the Lambda function at run-time
*/
environment?: { [key: string]: string }/**
* Absolute paths to the files to be included in the zip file
*
* Or { path: string, folder: string } where folder is the destination inside the Lambda folder context
* This enables relative 'require()'s to help project structure not become one flat folder
* when working on multiple Lambdas in a single project
*/
files: File[]
}```
#### Deployer.registerCaller(caller: Caller)
```ts
function registerCaller(caller: Caller): void
``````ts
type Caller = APICaller | EventCaller
``````ts
interface APICaller {
// 'event' will be supported in the future
kind: 'api'// HTTP Method of the caller
// 'GET', 'PUT', 'POST', 'DELETE', ...
method: string// Route path of the resource
// E.g. /users
path: string// Return Content-Type of the Lambda
// E.g. application/json
contentType: string
}
```
```ts
interface EventCaller {
kind: 'event'/**
* Name of the event
* E.g. my-schedule-event
*/
name: string/**
* Human readable description of the event
* E.g. "Hourly update trigger"
*/
description: string/**
* Cron or Rate expression
* See: http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
*/
schedule: string
}
```