Getting started
Getting started
Configuring AWS
Prerequisites
To work with Myrmex and its main plugins, you should to have some notions about:
- AWS IAM
- AWS Lambda
- Amazon API Gateway
- OpenAPI (aka Swagger) specification
- Node.js
Myrmex aims to experiment quickly, but to really be efficient, it is necessary to know the AWS services that works with Myrmex.
Permissions needed to deploy the project in AWS
Myrmex plugins that manage AWS resources need to have permissions to execute commands that communicate with the AWS API.
To begin to work with Myrmex, the following policies can be used:
IAMFullAccess
AWSLambdaFullAccess
AmazonAPIGatewayAdministrator
The AWS credentials can be set following the documentation from the AWS SDK for Node.js
Installation
Prerequisites: node
(version 4 minimum) must be installed.
Installing the Myrmex command line
The myrmex
command line has its own npm module. Install it globally.
npm install -g myrmex
We can check that the myrmex
command line is correctly installed.
# This command will show the available options and sub-commands
myrmex -h
At this point, there is only one sub-command available: myrmex new
. When creating a project, other subcommands will be
provided by Myrmex plugins. For every subcommand, every option that is not provided via the command line will provide a
prompt to set its value. This way, every Myrmex command can be scripted and is completely interactive at the same time.
Creating a new project
myrmex new
is the command that creates new projects. If it is called without argument and/or option, it will provide a prompt
to define the configuration of the project.
# Using the command without option and argument,
# the user will be prompted to give information about the project configuration
myrmex new
The prompt will ask to choose a project name and to select the plugins to install among @myrmex/iam
, @myrmex/lambda
and
@myrmex/api-gateway
. The plugin selection depend on the project. It is easy to install a plugin later if it is not done at
this step (see next section).
myrmex new
will perform 3 operations:
- create a project folder
- install the latest version of Myrmex and the project's plugins
- create a
myrmex.json
configuration file
Once the project is created we can enter its folder. Using myrmex -h
we can see that new myrmex
sub-commands are available.
They are provided by plugins that have been installed in the project.
Installing plugins
myrmex new
propose a selection of plugins to install but it is possible to install them or other plugins separately. Myrmex
plugins are npm packages. So the following command will install the plugin @myrmex/api-gateway
:
npm install @myrmex/api-gateway --save-dev
To be loaded by Myrmex, the plugin needs to be referenced in the myrmex.json
file, in the plugins
section:
{
"name": "my-serverless-application",
"plugins": [
"@myrmex/api-gateway"
]
}
It is possible to disable a plugin by removing it from the myrmex.json
file.
Project configuration
Myrmex can be configured in different ways.
The myrmex.json
file
In the root directory of a Myrmex project, there is a myrmex.json
file that contains the configuration of the project.
A myrmex.json
file looks like this:
{
"name": "my-serverless-application",
"plugins": [
"@myrmex/iam",
"@myrmex/api-gateway",
"@myrmex/lambda"
],
"config": {
"myConfigKey": "my-config-value",
"myNestedConfig": {
"level1": 42,
"level2": {
"key1": true,
"key2": false
}
}
}
}
name
: the identifier of the project.plugins
: the list of plugins that Myrmex has to register. A Myrmex plugin can be a node module installed via npm or defined in the project. A plugin installed via npm but specified here will not be registered by Myrmex.config
: the configuration of the project. Each plugin can use the it and inject default values in it.
The command myrmex show-config
allows to see the current configuration of a project. This is the response of this command for
the previous myrmex.json
file.
"myConfigKey": "my-config-value",
"myNestedConfig": {
"level1": 42,
"level2": {
"key1": true,
"key2": false
}
},
"iam": {
"policiesPath": "iam/policies",
"rolesPath": "iam/roles"
},
"apiGateway": {
"apisPath": "api-gateway/apis",
"endpointsPath": "api-gateway/endpoints",
"modelsPath": "api-gateway/models"
},
"lambda": {
"lambdasPath": "lambda/lambdas",
"modulesPath": "lambda/modules"
}
}
This example shows that the three plugins injected the configuration to define the location of the content that
they manage. It is possible to override this configuration in the myrmex.json
file.
Splitting the configuration into various files
If a project has a many configuration keys, it is possible to split the configuration object into various files in a folder
named config
.
For the previous example, to define the same configuration that in the previous example, the directory structure will look like this:
project-root
├── myrmex.json
└── config
└── myNestedConfig.json
The myrmex.json
file:
{
"name": "planet-express",
"plugins": [
"@myrmex/iam",
"@myrmex/api-gateway",
"@myrmex/lambda"
],
"config": {
"myConfigKey": "my-config-value"
}
}
The file config/myNestedConfig.json
:
{
"level1": 42,
"level2": {
"key1": true,
"key2": false
}
}
The command myrmex show-config
will give the same response:
"myConfigKey": "my-config-value",
"myNestedConfig": {
"level1": 42,
"level2": {
"key1": true,
"key2": false
}
},
"iam": {
"policiesPath": "iam/policies",
"rolesPath": "iam/roles"
},
"apiGateway": {
"apisPath": "api-gateway/apis",
"endpointsPath": "api-gateway/endpoints",
"modelsPath": "api-gateway/models"
},
"lambda": {
"lambdasPath": "lambda/lambdas",
"modulesPath": "lambda/modules"
}
}
Using environment variables to override the configuration
It is also possible to define configuration via environment variables. Any environment variable that starts with MYRMEX_
is injected as a configuration key/value. An underscore is used to resolve nested keys.
Because
_
is used to resolve nested key, this technique cannot work with configuration keys containing a_
.
For example, the configuration of myNestedConfig.level1
can be overrided using the environment variable
MYRMEX_myNestedConfig_level1
:
export MYRMEX_myNestedConfig_level1=43
myrmex show-config
Result:
{
"myConfigKey": "my-config-value",
"myNestedConfig": {
"level1": "43",
"level2": {
"key1": true,
"key2": false
}
},
"iam": {
"policiesPath": "iam/policies",
"rolesPath": "iam/roles"
},
"apiGateway": {
"apisPath": "api-gateway/apis",
"endpointsPath": "api-gateway/endpoints",
"modelsPath": "api-gateway/models"
},
"lambda": {
"lambdasPath": "lambda/lambdas",
"modulesPath": "lambda/modules"
}
}
Configuration values defined via an environment variable are always of type
String
Defining the configuration programmatically
All json configuration files in Myrmex are loaded using the Node.js require()
function. This means that they all can be
replaced by a javascript file that exposes the desired configuration.
For example, the previous myrmex.json
file can be replaced by this myrmex.js
file:
module.exports = {
name: 'planet-express',
plugins: [
'@myrmex/iam',
'@myrmex/api-gateway',
'@myrmex/lambda'
],
config: {
myConfigKey: process.env.MY_ENVIRONMENT_VARIABLE || 'my-default-value'
}
}
IAM plugin
IAM plugin
The @myrmex/iam
plugin allows to define and deploy AWS policies and roles. It can be used to avoid referencing IAM
roles ARNs and simplify the configuration of other plugins.
Prerequisites
To use the @myrmex/iam
plugin, it is necessary to have a minimal knowledge about AWS Identity and Access Management.
An AWS user or role that uses the plugin @myrmex/iam
must have access to IAM administration. The AWS policy IAMFullAccess
gives all necessary permissions.
Installation
Install the npm module in a Myrmex project:
npm install @myrmex/iam --save-dev
Then enable the plugin in the myrmex.json
file:
{
"name": "my-app",
"plugins": [
"@myrmex/iam"
]
}
Commands
create-policy
Usage:
create-policy [identifier]
Create a new IAM policy in iam/policies/<identifier>.json
. The command does not configure the policy but just prepare the
file in the right place. By default it is iam/policies/<identifier>.json
.
create-role
Usage:
create-role [options] [identifier]
Options:
-m, --model <model-identifier> select a model to quickly create the role configuration
-p, --policies <policy-identifiers> select the policies to attach to the role
Create a new IAM role. By default the location of roles is iam/roles/<identifier>.json
.
Two predefined role configuration are available:
APIGatewayLambdaInvocation
: The AWS policyAWSLambdaRole
is attached to it and it can be associated to API Gateway endpoints.LambdaBasicExecutionRole
: The AWS policyAWSLambdaBasicExecutionRole
is attached to it and it can be associated to Lambda functions.
It is possible to define custom policies and trust-relationship
configuration. Is is also possible to reference
policies from the Myrmex project.
Roles can be referenced by other plugins to facilitate the deployment of Myrmex applications: by defining roles in the Myrmex project, deploying some resources like Lambda functions or API definitions can be done on various environments without needing to define specific configuration to reference different roles ARN.
deploy-policies
Usage:
deploy-policies [options] [policy-identifiers]
Options:
-e, --environment [environment] An environment identifier that will be used as a prefix
-s, --stage [stage] A stage identifier that will be used as a suffix
Deploy one or more policies in AWS. The --environment
option is used as a prefix and the --stage
option as a suffix.
deploy-roles
Usage:
deploy-roles [options] [role-identifiers]
Options:
-e, --environment [environment] An environment identifier that will be used as a prefix
-s, --stage [stage] A stage identifier that will be used as a suffix
Deploy one or more roles in AWS. The environment
option is used as a prefix and the stage
option as a suffix.
Definition of IAM policies
The policies managed by Myrmex are nothing more than IAM policy definitions stored as JSON file. This allows to manage the permissions needed by an application alongside the code.
Every time Myrmex has to deploy a policy, it checks if it needs to be created or updated and perform the appropriate action if needed. If a policy already has 5 version (the maximum allowed by AWS), the oldest one will be deleted (unless it as been defined as the default one).
Definition of IAM roles
AWS roles can be configured with JSON files with @myrmex/iam
. The structure looks like this:
{
"description": "Description of the role",
"managed-policies": [
"<policy-identifier>"
],
"inline-policies": [
"<policy-definition>"
],
"trust-relationship": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "<service-identifier>"
},
"Action": "sts:AssumeRole"
}]
}
}
The managed-policies section contains a list of identifiers of IAM policies already deployed in AWS associated to the role. During the deployment of a role, Myrmex will look for policies matching the identifiers in managed-policies, trying combinations with the environment and the stage options:
<environment>_<identifier>_<stage>
<environment>_<identifier>
<identifier>
The inline-policies section contains a list of AIM policy definitions associated to the role.
The trust-relationship section contains the policy that describe the trusted entities that can assume the role
Integration with @myrmex/api-gateway
@myrmex/iam
add some functionalities to @myrmex/api-gateway
when both are installed in the same project.
Simplify the association of an API endpoint with its invocation role
In the spec.json
file that describes an endpoint, the invocation
role is configured via the [API Gateway extension to Swagger]
(http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html) using the
property credentials
. It accepts the ARN of an IAM role. Using @myrmex/iam
, it is also possible configure this property
using the identifier of a role defined in the Myrmex project or the name of a role deployed in AWS.
New behavior for the option --role <role>
of myrmex create-endpoint
This option normally accepts the ARN of a role. With the plugin @myrmex/iam
, it also accepts the identifier of an role
defined in the Myrmex project or the name of a role deployed in AWS.
If the option is not provided in the command line, a prompt will propose three option to set the value:
- Select a role managed by the plugin @myrmex/iam
- Select a role in your AWS account
- Enter the value manually
Integration with @myrmex/lambda
@myrmex/iam
add some functionalities to @myrmex/lambda
when both are installed in the same project.
Simplify the association of a Lambda with its execution role
In the config.json
file that describes the
configuration of a Lambda, the invocation role is configured via the using the property params.role
. It accepts the ARN of
an IAM role. Using @myrmex/iam
, it is also possible configure this property using the identifier of a role defined in the
Myrmex project or the name of a role deployed in AWS.
New behavior for the option --role <role>
of myrmex create-lambda
This option normally accepts the ARN of a role. With the plugin @myrmex/iam
, it also accepts the identifier of an role
defined in the Myrmex project or the name of a role deployed in AWS.
If the option is not provided in the command line, a prompt will propose three option to set the value:
- Select a role managed by the plugin @myrmex/iam
- Select a role in your AWS account
- Enter the value manually
Hooks and extensions
Hooks
beforePoliciesLoad()
beforePolicyLoad(definitionFilePath, name)
afterPolicyLoad(policy)
afterPoliciesLoad(policies)
beforeRolesLoad()
beforeRoleLoad(definitionFilePath, name)
afterRoleLoad(role)
afterRolesLoad(roles)
beforeDeployPolicy(policy)
beforeDeployRole(role)
Extensions
myrmex.call('iam:getRoles')
returns the roles managed in the current Myrmex project.
myrmex.call('iam:getAWSRole')
returns the roles available in AWS.
myrmex.call('iam:retrieveRoleArn', identifier, context)
retrieve the ARN of an IAM role using its identifier. Tries
combinations with the environment
and the stage
properties of the context
parameter in this order:
<environment>_<identifier>_<stage>
<environment>_<identifier>
<identifier>
.
Lambda plugin
Lambda plugin
The @myrmex/lambda
plugin allows to define and deploy Lambdas. It should work with any runtime but has been tested mostly with
Node.js and secondly with Python.
Prerequisites
To use the @myrmex/lambda
plugin, it is necessary to have a minimal knowledge about
AWS Lambda.
An AWS user or role that uses the plugin @myrmex/lambda
must have access to Lambda administration. The AWS policy
AWSLambdaFullAccess
gives all necessary permissions.
Installation
Install the npm module in a Myrmex project:
npm install @myrmex/lambda
Then enable the plugin in the myrmex.json
file:
{
"name": "my-app",
"plugins": [
"@myrmex/lambda"
]
}
Once the plugin is installed and enabled in the project, the myrmex
command line will provide new sub-commands to
manage and deploy Lambdas.
Project anatomy
By default, the content managed by the Lambda plugin is located in an lambda
directory in the root directory of the
project.
Out of the box, for the Node.js runtime, the Lambda plugin allows to separate the definition of Lambdas from the logic
of the application by providing a specific place to write node modules but it is not mandatory to use it.
@myrmex/lambda
helps to define and deploy Lambdas but the developer is responsible of the implementation of the
application. Other plugins built on top of the Lambda plugin may be more opinionated.
The directory lambda/lambdas
contains the Lambdas definitions. For each of its sub-directory is considered as a
Lambda definition. It must contains a config.json
file and the code of the Lambda. The name of the subdirectory is
used as the Lambda identifier.
The config.json
file allows to define the runtime, the timeout, the memory, the role and other properties of the
Lambda. The content of the params
property is used as the argument of the following methods from the AWS SDK:
Example of config.json
file:
{
"params": {
"Timeout": 10,
"MemorySize": "256",
"Runtime": "nodejs6.10",
"Handler": "index.handler",
"Role": "arn:aws:iam::012345678901:role/LambdaBasicExecution"
}
}
By default, for the Node.js runtime, the directory lambda/modules
contains the node modules of the project. For
example, some of these modules could be named log
, or data-access
or authorization
etc...
Each module should have a clear responsibility so that each Lambda can embed only the code it needs. This is a recommendation but the developer is free to organize the code as he want. The Lambda plugin does not force you to use a specific project organization.
This is what a project structure could look like:
lambda
├── lambdas The Lambdas defined by the application
| ├── my-nodejs-lambda The name of this directory is the identifier of a Lambda
| | ├── config.json The configuration of the Lambda (runtime, memory, timeout, execution role...)
| | ├── index.js A node module that exposes the handler
| | └── package.json It is possible to install the dependencies of the Lambda here
| └── my-python-lambda Several runtimes can coexist in a project
| ├── config.json
| └── lambda_function.py
└── modules The node modules of the application - they can be added as a dependency of a Lambda in its
| package.json file
├── authorization The name of this directory is the identifier of a module
| ├── package.json Package file of the module
| ├── index.js Main file of the module
| └── test If you wish, you can write the code to test the module in this directory
├── data-access
| ├── package.json
| └── index.js
└── log
├── package.json
└── index.js
Example of config.json
file:
{
"params": {
"Timeout": 30,
"MemorySize": 256,
"Role": "arn:aws:iam::123456789012:role/MyRole",
"Runtime": "nodejs6.10",
"Handler": "index.handler"
}
}
The package.json
of a module or a Lambda can declare dependencies with other modules using file paths in the
dependencies
property:
{
"name": "data-access",
"version": "0.0.0",
"dependencies": {
"log": "../log"
}
}
In this case, require('log')
will load the module log
installed in lambda/modules/data-access/node_modules/log
.
It is recommended to use relative paths for portability.
It is recommended to use a recent version of npm
to minimize the size of the Lambda packages and facilitate the
configuration of nested dependencies. Indeed, npm@2
can behave in an unexpected manner with nested dependencies when
using relative file paths.
Configuration
These are Myrmex configuration keys specific to to
the @myrmex/lambda
plugin.
Default values
Using myrmex show-config
after installing the plugin, we can see the default configuration:
{
"lambda": {
"lambdasPath": "lambda/lambdas",
"modulesPath": "lambda/modules"
}
}
lambda.lambdasPath
Path to the folder that contains Lambdas. Default value: lambda/lambdas
.
lambda.modulesPath
Path to the folder that contains modules for Node.js Lambdas. Default value: lambda/modules
.
lambda.alias
Set the alias applied when deploying Lambdas.
By setting this configuration, the --alias
option of the myrmex deploy-lambdas
command does not
prompt when not provided via the command line and the configured value is used as the default value.
Setting lambda.alias
to an empty string disables the creation/update of an alias and the new version of the Lambda
will only be available as LATEST
.
Example
Using the myrmex.json
file, the plugin configuration can be defined like this:
{
"name": "A Myrmex project",
"plugins": [
"@myrmex/lambda"
],
"config": {
"lambda": {
"lambdasPath": "lambdas",
"modulesPath": "modules",
"alias": ""
}
}
}
Commands
create-lambda
create-lambda [options] [identifier]
Options:
-r, --runtime <nodejs|nodejs4.3|nodejs6.10|python2.7|python3.6> select the runtime
-t, --timeout <timeout> select the timeout (in seconds)
-m, --memory <memory> select the memory (in MB)
-d --dependencies <modules-names> select the project modules that must be included in the Lambda (only for nodejs runtimes)
--role <role> select the execution role (enter the ARN)
Create a new Lambda. By default the location of Lambdas is lambda/lambdas/<identifier>/
.
create-node-module
For the Node.js runtime only.
create-node-module [options] [name]
Options:
-d, --dependencies <dependent-modules> select the node modules that are dependencies of this new one
Prepare a new Node.js module. By default the location of modules is lambda/modules/<name>/
.
The creation of nodes modules is just a suggestion to organize the code of a project. The idea is to maintain each component of the application in its own node module to select only relevant components when deploying Lambdas.
Every Lambda can declare its modules dependencies using
local paths in its package.json
file. Every module can also
declare dependencies to other modules that way.
When Myrmex deploys a Lambda, it executes npm install
and the dependencies are installed in the node_modules
folder.
deploy-lambdas
deploy-lambdas [options] [lambda-identifiers...]
Options:
--all deploy all lambdas of the project
-r, --region <region> select the AWS region
-e, --environment <environment> select the environment
-a, --alias <alias> select the alias to apply
Deploy one or more Lambdas in AWS. The --environment
option is used as a prefix. The --alias
option will publish a
version in Amazon Lambda and apply an alias. Setting the option to an empty string (--alias ""
) will skip this.
When deploying Node.js Lambdas, it is recommended to use npm4 to optimize the size of the packages and avoid the resolution of local dependencies with symbolic links (behavior of npm5).
When deploying Lambdas with C/C++ bindings and/or to be sure to create packages with the correct runtime, use the plugin
@myrmex/packager
install-lambdas-locally
install-lambdas-locally [lambda-identifiers...]
Deletes the node_modules
folder of one or several lambda and runs npm install
to re-install it.
test-lambda-locally
test-lambda-locally [options] [lambda-identifier]
Options:
-e, --event <event-name> Event example to use
Executes a Lambda locally. The event option allows to select the example object that will be passed as the first
argument. Example objects are defined in json files in lambda/lambdas/<identifier>/events/<event-name>.json
. A mock
of the conshell object is passed as the second argument.
test-lambda
test-lambda [options] [lambda-identifier]
Options:
--event <event-name> Event example to use
-r, --region <region> select the AWS region
-e, --environment <environment> select the environment
-a, --alias <alias> select the alias to test
Executes a Lambda deployed in AWS. The event option allows to select the example object that will be passed as the first
argument. Example objects are defined in json files in lambda/lambdas/<identifier>/events/<event-name>.json
. A mock
of the conshell object is passed as the second argument.
Setting the option --alias
to an empty string (--alias ""
) will invoke the LATEST
version of the Lambda.
Integration with @myrmex/api-gateway
@myrmex/lambda
add some functionalities to @myrmex/api-gateway
when both are installed in the same project.
Associate a Lambda with an API endpoint
In the spec.json
file that describes an endpoint, a new
extension to Swagger is available to select a Lambda that must be used for the endpoint integration.
{
"x-myrmex": {
"apis": [],
"lambda": "lambda-identifier"
}
... rest of the endpoint specification
}
New option for myrmex create-endpoint
When calling myrmex create-endpoint
, a new option
--lambda <lambda-identifier>
is available. This option accepts the identifier of a Lambda managed by @myrmex/lambda
.
If the option is not provided in the command line and the option --integration
is set to lambda
or lambda-proxy
, a
prompt will propose to select the appropriate Lambda in a list.
The value of --lambda <lambda-identifier>
will be set in extension to Swagger described above.
New options for myrmex deploy-apis
When calling myrmex create-endpoint
, two new options are
available:
--deploy-lambdas <all|partial|none>
The option --deploy-lambdas <all|partial|none>
accepts three possible values:
all
will perform the deployment of all Lambdas defined in the Myrmex project before deploying the APIs.partial
will perform the deployment of all Lambdas that are associated to deployed endpoints before deploying the APIs.none
will not deploy any Lambda, but it will retrieve the ARNs of all Lambdas that are associated to deployed endpoints. So these Lambda have to be already deployed with the appropriate alias.
--alias <alias>
The option --alias <alias>
allows to select the Lambda alias that will be integrated with endpoints.
If the lambda.alias
configuration is set and the option is not provided via the command line, no
prompt will appear to set the value the configured value is used as the default value.
API Gateway Plugin
API Gateway Plugin
Prerequisites
To use the @myrmex/api-gateway
plugin, it is necessary to have a minimal knowledge about Amazon API
Gateway and the Swagger v2.0 specification.
@myrmex/api-gateway
uses the API Gateway Import API feature.
Installation
Install the npm module in a Myrmex project:
npm install @myrmex/api-gateway
Then enable the plugin in the myrmex.json
file:
{
"name": "my-app",
"plugins": [
"@myrmex/api-gateway"
]
}
Once the plugin is installed and enabled, the myrmex
command line will provide new sub-commands to manage and deploy APIs.
Project anatomy
By default, the content managed by @myrmex/api-gateway
is located in an api-gateway
directory in the root directory of the
project.
A project configuration is composed of a list of APIs and a list of endpoints. Each endpoint specification contains the list
of APIs where it must be exposed. Therefore, an endpoint GET /my-resource/{id}
can be exposed by a mobile-app
API and a
back-office
API, while another endpoint PUT /my-resource
can be exposed by the back-office
API only. This allows to
create different APIs for different purposes while sharing some functionalities.
The directory api-gateway/apis
contains the API definitions. Each of its sub-directory has the name of an API identifier and
contains a Swagger specification file (without the endpoints definitions).
The directory api-gateway/endpoints
contains the endpoints definitions. The structure of its sub-directories represents url
paths and HTTP methods. Each HTTP method directory contains the definition of an endpoint. An endpoint definition is composed
of its Swagger specification in a spec.json
file.
As an example is more easy to understand, that is what a project structure could looks like:
api-gateway
├── apis The APIs defined by the application
| ├── back-office The name of this directory is the identifier of an API
| | └── spec.json The API's Swagger specification (without endpoints definitions)
| └── mobile-app
| └── spec.json
└── endpoints The endpoints defined by the application
├── resource-a Creates the path /resource-a
| ├── {id} Creates the path /resource-a/{id}
| | ├── GET Creates the HTTP method GET for the path /resource-a/{id}
| | | └── spec.json The Swagger specification of the endpoint GET /resource-a/{id}
| | └── PATCH
| | └── spec.json
| └── PUT
| └── spec.json
└── resource-b
├── GET
| └── spec.json
└── resource-c
└── GET
└── spec.json
This project contains 2 APIs:
back-office
mobile-app
5 endpoints are available:
GET /resource-a/{id}
PATCH /resource-a/{id}
PUT /resource-a
GET /resource-b
GET /resource-b/resource-c
To associate an endpoint to one or more APIs, it is possible to enrich the endpoint specification (spec.json
file) with a
list of API identifiers, in a Myrmex extension to Swagger.
{
"x-myrmex": {
"apis": [
"back-office",
"mobile-app"
]
}
... rest of the endpoint specification
}
@myrmex/api-gateway
uses the API Gateway Import API feature. Therefore, the configuration of AWS-specific authorization
and API Gateway-specific API integrations is done with the API Gateway extensions to
Swagger.
Commands
create-api
create-api [options] [api-identifier]
Options:
-t, --title <title> The title of the API
-d, --desc <description> A description of the API
Create a new API. By default the location of API definitions is api-gateway/apis/<api-dentifier>/
. The API definition is a
file named spec.json
that contains a Swagger object. The command line
will to create a simple base configuration. It is possible to write a full Swagger definition here, but the plugin
@myrmex/api-gateway
is designed to separate API definitions into pieces and generate full definitions when needed.
create-model
create-model [name]
Create a new model. By default the location of models is api-gateway/model/model.json
. Models can be referenced as input
or output of API endpoints but are not mandatory.
create-endpoint
create-endpoint [options] [resource-path] [http-method]
Options:
-a, --apis <api-identifiers> The identifiers of APIs that expose the endpoint separated by ","
-s, --summary <endpoint summary> A short summary of what the operation does
--auth <authentication-type> The type of authentication used to call the endpoint (aws_iam|none)
-i --integration <integration-type> The type of integration (lambda|http|mock|aws-service)
-r, --role <role> select the role to invoke integration
Create a new endpoint. By default the location of endpoints definitions is
api-gateway/endpoints/<resource-path>/<http-method>/
. The endpoint definition is a file named spec.json
that contains a
Swagger path item object. The command line will help to create a
simple base configuration. Then, the developer can complete the definition using the Swagger specification and the API
Gateway extentions to Swagger.
The definition of an endpoint can be added to one or more APIs using a Myrmex extention to Swagger:
{
"x-myrmex": {
"apis": [
"<api-identifier-a>",
"<api-identifier-b>"
]
}
... rest of the endpoint specification
}
inspect-api
inspect-api [options] [api-identifier]
Options:
-c, --colors highlight output
-s, --spec-version <version> select the type of specification to retrieve: doc|aws|complete
Generate the Swagger definition of an API and print it. There are three different versions of the specification:
- The
doc
version only contains parts of the definitions that belong to the Swagger specification. - The
aws
version is the definition that is sent to AWS API gateway when performing a deployment. - The
complete
version contains everything that is defined in the project, including the Myrmex extensions to Swagger.
inspect-endpoint
inspect-endpoint [options] [resource-path] [http-method]
Options:
-c, --colors highlight output
-s, --spec-version <version> select the type of specification to retrieve: doc|aws|complete
Generate the Swagger definition of an endpoint and print it. There are three different versions of the specification:
- The
doc
version only contains parts of the definitions that belong to the Swagger specification. - The
aws
version is the definition that is sent to AWS API gateway when performing a deployment. - The
complete
version contains everything that is defined in the project, including the Myrmex extensions to Swagger.
deploy-apis
deploy-apis [options] [api-identifiers...]
Options:
-r, --region <region> select the AWS region
-e, --environment <environment> select the environment
-s, --stage <stage> select the API stage
Deploy one or more APIs in API Gateway. The --environment
option is used as a prefix to the API name in API Gateway. It can
be useful to deploy APIs several time in the same AWS account. Values for --environment
could be PROD
or DEV
or JOHN
to be able to deploy the API for production, development or a developer environment.
The use of
--environment
can seem redundant with--stage
, but when deploying an API Gateway stage, it is not to possible to access to the testing tools of the AWS console. These tools are available only for the ultimate version of the API. Using--environment
can allow several developers to use the testing tools of the AWS console simultaneously.--environment
also allows to use--stage
for other purposes like API versioning (with values likev1
,v2
,2017-01-01
...).
CORS Plugin
CORS Plugin
Prerequisites
The @myrmex/cors
plugin gives the possibility to easily define CORS configuration for the @myrmex/api-gateway
plugin.
Installation
Install the npm module in a Myrmex project:
npm install @myrmex/cors
Then enable the plugin in the myrmex.json
file:
{
"name": "my-app",
"plugins": [
"@myrmex/api-gateway",
"@myrmex/cors"
]
}
The plugin does not provide new, commands but it allows to define CORS configuration at various levels in the project.
Principle
The plugin @myrmex/cors
aims to simplify the configuration of CORS by consuming simple configuration files and
automatically creating OPTIONS http methods for APIs and adding http headers to endpoints.
@myrmex/cors
supports the pseudo http method ANY
available in API Gateway to define DELETE, GET, HEAD, PATCH, POST and PUT
method with a single configuration. @myrmex/cors
uses it to apply the configuration correctly but it will not be present in
http responses.
Configuration
There are four possible levels of configuration in this order of precedence:
- Global configuration
- API level configuration
- Resource path level configuration
- API resource path level configuration
Global configuration
The global configuration applies by default for all endpoints of all APIs.
Using myrmex show-config
, it is possible to see the default values:
{
"apiGateway": {
"apisPath": "api-gateway/apis",
"endpointsPath": "api-gateway/endpoints",
"modelsPath": "api-gateway/models"
},
"cors": {
"Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,ANY",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "*"
}
}
By default, all methods, all origins and all headers are allowed. This configuration allows to quickly experiment, but it
can be overwritten to restrict the access to the maximum. For example, to allow the access to the APIs only for the domain
www.example.com
, it is possible to set this configuration in the file myrmex.json
at the root of the project:
{
"name": "my-app",
"plugins": [
"@myrmex/api-gateway",
"@myrmex/cors"
],
"config": {
"cors": {
"Access-Control-Allow-Origin": "https://www.example.com"
}
}
}
There are several ways to set this kind of configuration in Myrmex.
The command myrmex show-config
shows the new configuration:
{
"apiGateway": {
"apisPath": "api-gateway/apis",
"endpointsPath": "api-gateway/endpoints",
"modelsPath": "api-gateway/models"
},
"cors": {
"Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,ANY",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "https://www.example.com"
}
}
API level configuration
To override the global configuration for a specific API, it is possible to use a Myrmex extension to Swagger in the
spec.json
file of the API. If we want to configure an API that has the identifier back-office
to accept request only from
https://admin.example.com, we can complete the file /api-gateway/apis/back-office/spec.json
like this:
{
"x-myrmex": {
"cors": {
"Access-Control-Allow-Origin": "https://admin.example.com"
}
},
"swagger": "2.0",
"info": {
"title": "my-api",
"description": "An API built with Myrmex"
},
}
This configuration will apply to all resource paths of the API.
Resource path level configuration
To define a specific configuration for a resource path, it is possible to create to create a cors.json
file in the resource
path.
To forbid the access to all http methods of the resource path /my/resource/path
, we can create a file
/api-gateway/endpoints/my/resource/path/cors.json
with the following content:
{
"default": {
"Access-Control-Allow-Methods": ""
}
}
API resource path level configuration
The cors.json
file at the resource path level accepts API specific configurations. Following the previous example, if we
want the API that has the identifier back-office
to allow GET
and POST
request from https://admin.example.com, we can
complete the file /api-gateway/endpoints/my/resource/path/cors.json
like this:
{
"default": {
"Access-Control-Allow-Methods": ""
},
"back-office": {
"Access-Control-Allow-Methods": "GET,POST",
"Access-Control-Allow-Origin": "https://admin.example.com"
}
}
Packager plugin
Packager plugin
Why ?
When installing Node.js and python dependencies to create a package for Lambda, some modules may not be compatible with
the execution environment of Amazon Lambda, because of differences of version of Node.js, python or GCC when modules
have C++ bindings. The @myrmex/packager
plugin helps to prevent this problem.
How it works
A common solution to this problem is to create the packages on a EC2 instance using an Amazon Linux AMI. To avoid
having to use a server to deploy serverless application, @myrmex/packager
uses the Docker image
myrmex/lambda-packager
based on the
Amazon Linux image. The image myrmex/lambda-packager
comes with all Node.js
and python runtimes supported by Amazon Lambda and GCC.
When the plugin @myrmex/lambda
deploys a Lambda, @myrmex/packager
takes in charge the creation of the package by
executing docker run myrmex/lambda-packager
with appropriates parameters.
Prerequisites
To use the @myrmex/packager
plugin, it is necessary to have Docker installed on the
environment that perform the deployment of Lambdas.
Installation
Install the npm module in a Myrmex project:
npm install @myrmex/packager
Then enable the plugin in the myrmex.json
file:
{
"name": "my-app",
"plugins": [
"@myrmex/lambda"
"@myrmex/packager"
]
}
Once the plugin is installed and enabled in the project, the @myrmex/lambda
plugin will use it to create packages
when deploying Node.js and python Lambdas.
Configuration
These are Myrmex configuration keys specific to to
the @myrmex/packager
plugin.
Default values
Using myrmex show-config
after installing the plugin, we can see the default configuration:
{
"packager": {
"bucket": null,
"docker": {
"useSudo": false,
"showStdout": false
}
}
}
packager.bucket
Name of the S3 bucket where the packages will be uploaded. If it does not exists, @myrmex/packager
will try to create
it. If this configuration key is not provided, @myrmex/packager
will directly upload the packages to Lambda without
using S3.
packager.docker.useSudo
If set to true
, @myrmex/packager
will use sudo
to execute docker run
. Alternatively, it is possible to
manage Docker as a non-root user using a group.
packager.docker.showStdout
It set to true
, the output of docker run
will be diplayed in the terminal.
Creating plugins
Creating plugins
Plugin definition
The Myrmex core is the node module @myrmex/core
. It exports an object (referred as the Myrmex instance) that is based on
Pebo that is a kind of event emitter.
Myrmex plugins use the Myrmex instance to interact with each other. A Myrmex plugin can be published on npm to be used by anyone, or it can be a project specific plugin.
Myrmex plugins can make use of the following functionalities:
- Listen for events fired by other plugins
- Fire events that can be listened by other plugins
- Attach functions to the Myrmex instance (refered as extensions)
Anatomy of a plugin
A plugin is node module that exports an object that has to respect a specific structure to be used by the Myrmex instance.
Here is a quick overview of an object exported by a Myrmex plugin.
{
// An unique identifier that should be carefully chosen to not enter in conflict with other plugins
name: `my-plugin-identifier`,
version: `0.0.0`,
// If the plugin is configurable, this place is suggested to define default values
// This configuration can be overwritten for a project in the file
// `project-root/config/my-plugin-identifier.json`
config: { // These values will be accessible using
key1: 'defaultValue1', // `myrmex.getConfig("my-plugin-identifier.key1")`
key2: { // `myrmex.getConfig("my-plugin-identifier.key2")`
a: 'defaultValue2A', // `myrmex.getConfig("my-plugin-identifier.key2.a")`
b: 'defaultValue2B' // `myrmex.getConfig("my-plugin-identifier.key2.b")`
}
},
hooks: {
// These functions are event listeners that will be called
// when events "eventNameA" and "eventNameB" are fired by Myrmex
// More details about events below
eventNameA: function (argA, argB) {
return Promise.resolve()
},
eventNameB: function () {
return Promise.resolve()
}
],
extensions: {
// These functions will be registered in the Myrmex instance
// so they will be accessible by other plugins
// More details about extensions below
extensionNameA: function() {}
extensionNameB: function() {}
}
}
The Myrmex instance
Before describing events and extensions, we should have a quick overview about the initialization of the Myrmex instance and the registration of plugins.
Initialization by the Myrmex command line
When the Myrmex command line is called. It checks if it is called from a Myrmex project by searching for a package.json
file
containing a dependency to @myrmex/core
in the current path.
Once a @myrmex/core
module have been found, the Myrmex command line loads it and receives an object: the Myrmex instance.
The Myrmex command line then loads the project configuration (including the list of plugins) and applies it to the Myrmex instance. Each plugin is loaded and registered in the Myrmex instance.
Registration of plugins
When the Myrmex instance registers a plugin, it basically performs three operations:
- Checks if it there is a list of hooks and create the event listeners.
- Checks if it there are extensions and add them to the Myrmex instance.
- Create a reference of itself in a
myrmex
property that is added to the plugin.
So, once a plugin has been registered by the Myrmex instance, it has a new myrmex
property that contains the Myrmex
instance. It can be used to fire events or call extensions that have been provided by other plugins.
Events mecanism
The event mecanism of Myrmex is designed to allow code injection and works with asynchronous operations.
From the event emitter point of view, when the Myrmex instance fires an event, it returns a promise of an array containing the arguments of the event. These arguments have eventually been transformed by event listeners.
From the event listener point of view, when the listener function is called, it has the possibility to alter the parameters of the event. If the event listener has to perform asynchronous operations to alter theses parameters, it should return a Promise that resolves once the modification is done.
Therefore, an emitter can wait for all listeners to eventually alter the event parameters to continue its task.
Here is a dummy example:
// The Myrmex instance is accessible via the `myrmex` property of a plugin once it has been registered
const myrmex = require('./plugin-index.js').myrmex;
// Create an event listener
myrmex.when('MyEvent', (myArg1, myArg2) => {
myArg.propB += ' transformed by an event listener';
myArg.propC = 'property added by an event listener';
return Promise.resolve();
});
// We define two objects that will be passed as the event arguments
// Passing literals is not recommended because JavaScript will copy them when passing them as arguments
// Myrmex would not be able to retrieve modifications applied to them
const eventArg1 = {
propA: 'original property',
propB: 'original property'
}
const eventArg2 = {
propA: 'original property'
}
myrmex.fire('MyEvent', eventArg1, eventArg2)
.then(arg => {
console.log(arg[0]);
// {
// propA: 'original property',
// propB: 'original property transformed by an event listener',
// propC: 'property added by an event listener'
// }
console.log(arg[1]);
// {
// propA: 'original property'
// }
});
Using this mecanism, Myrmex plugins can create their own events and listen for other plugins events. Several plugins can listen for the same event and use and/or modify its arguments.
For example, before configuring the integration request of API endpoints, the
@myrmex/api-gateway
plugin fires and event that allows other plugins to be notified about it. Theses plugins have the opportunity to inject data in the event's argument so the plugin@myrmex/api-gateway
can generate a compete API specification.
Note that it is not recommended to call myrmex.when()
directly when writing a plugin. We prefer to use the hooks
property
of the object exported by the plugin to organize the code and be sure that the listeners are attached to the events during
the registration of the plugin.
Extensions
@todo
Deploying an Express application in Lambda
Deploying an Express application in Lambda
This tutorial uses
express-generator
to quickly create a sample application. This sample application is not an API and serves static content but we do not recommend to do that in a real case scenario. You should useExpress
with API Gateway and Lambda only for APIs.
Starting with an Express application
We will start by creating a basic Express application following the documentation.
# Installation of express-generator
npm install express-generator -g
# Creation of a basic application
express --view=pug express-app
# Installation of dependencies
cd express-app && npm install
We start the application locally to check that everything works correctly.
set DEBUG=express-app:* & npm start
Visit http://127.0.0.1:3000/ to check that the application runs correctly locally.
Adding Myrmex to the project
Be sure that the Myrmex cli is installed.
npm install -g myrmex
Install Myrmex in the Express project
# For the prompt "What is your project name?", leave it empty, so Myrmex will be installed in the same directory that Express
# We will need the plugins @myrmex/iam @myrmex/api-gateway and @myrmex/lambda
myrmex new
Myrmex and its plugins will be installed in the section devDependencies
of the file package.json
.
Creation of IAM roles
We create two IAM roles: one to allow Lambda to write in cloudwatch and the other to allow API Gateway to invoke Lambda.
myrmex create-role MyExpressAppLambdaExecution --model LambdaBasicExecutionRole
myrmex create-role MyExpressAppLambdaInvocation --model APIGatewayLambdaInvocation
Creation of the Lambda
We create a new Lambda managed by Myrmex.
myrmex create-lambda serverless-express --runtime nodejs6.10 --timeout 30 --memory 256 --role MyExpressAppLambdaExecution
We have to do a small alteration to the package.json
of the Express application to tell node that app.js
is the file that
has to be loaded when require()
is used.
// in /package.json
{
"name": "express-app",
"version": "0.0.0",
"main": "app.js",
...
}
In the package.json
of the Lambda, we define the Express application as a dependency
# in /lambda/lambdas/serverless-express
npm install ../../.. --save
aws-serverless-express is a npm package that wrap an Express application to process requests from API Gateway with Lambda integration. We add it as a dependency of our Lambda.
# in /lambda/lambdas/serverless-express
npm install aws-serverless-express --save
Then we can alter the code of index.js
from the Lambda to correctly expose the handler.
// in /lambda/lambdas/serverless-express/index.js
'use strict';
const awsServerlessExpress = require('aws-serverless-express');
const app = require('express-app');
const server = awsServerlessExpress.createServer(app);
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context);
Creation of the API
We create an API with two endpoints using ANY
method and Lambda proxy integration: one to handle the root url, and another
for the rest.
myrmex create-api serverless-express --title "Serverless Express" --desc "An Express application served by API Gateway and Lambda"
myrmex create-endpoint / ANY --apis serverless-express --summary "Proxy to Lambda" --auth none --integration lambda-proxy --lambda serverless-express --role MyExpressAppLambdaInvocation
myrmex create-endpoint /{proxy+} ANY --apis serverless-express --summary "Proxy to Lambda" --auth none --integration lambda-proxy --lambda serverless-express --role MyExpressAppLambdaInvocation
Deployment
myrmex deploy-apis serverless-express --region us-east-1 --environment DEV --stage v0 --deploy-lambdas all --alias ""
The deployment messages will give you the url of the application. It will have the form
https://{your-api-id}.execute-api.us-east-1.amazonaws.com/v0
.
You can test the root url and the url https://{your-api-id}.execute-api.us-east-1.amazonaws.com/v0/users
that is also
declared in the sample application generated by express-generator
. You can also test some bad urls and observe that you
receive an error 404.
Creating Lambdas to inspect their execution environment
Creating Lambdas to inspect their execution environment
Creation of three Lambdas sharing the same code
The code generated by this example is available here.
Lets create a new Myrmex project.
myrmex new lambda-profiling @myrmex/iam @myrmex/lambda
cd lambda-profiling
We create a simple execution role for our Lambdas.
myrmex create-role LambdaInspection --model LambdaBasicExecutionRole
We create a node module called inspection
. It will inspect its own execution environment.
myrmex create-node-module inspection
The inspection
module is created in lambda-profiling/lambda/modules/inspection
and only contain a package.json
file for now.
Lets create an index.js
file that exposes data from the os
native module and the process
global object in our module.
// lambda-profiling/lambda/modules/inspection/index.js
'use strict';
const os = require('os');
module.exports = () => {
return {
host: {
name: os.hostname(),
architecture: process.arch,
memory: os.totalmem(),
cpus: os.cpus()
},
os: {
platform: process.platform,
release: os.release(),
uptime: os.uptime()
},
user: {
uid: process.getuid(),
gid: process.getgid(),
groups: process.getgroups
},
process: {
command: process.argv,
execArgs: process.execArgv,
pid: process.pid,
uptime: process.uptime(),
memoryUsage: process.memoryUsage()
},
exec: {
env: process.env,
currentDirectory: process.cwd(),
// mainModule: process.mainModule,
config: process.config
}
};
};
Now we create three Lambdas that will use the inspection
module as a dependency. Their are configured with different memory values: 128MB, 512MB and 1536MB.
myrmex create-lambda config-128 --runtime nodejs6.10 --timeout 30 --memory 128 --dependencies inspection --role LambdaInspection
myrmex create-lambda config-512 --runtime nodejs6.10 --timeout 30 --memory 512 --dependencies inspection --role LambdaInspection
myrmex create-lambda config-1536 --runtime nodejs6.10 --timeout 30 --memory 1536 --dependencies inspection --role LambdaInspection
We alter the handler of the three Lambdas to call the inspection
module, log its output (it will be visible in cloudwatch) and return it.
// lambda-profiling/lambda/lambdas/config-128/index.js
// lambda-profiling/lambda/lambdas/config-512/index.js
// lambda-profiling/lambda/lambdas/config-1536/index.js
'use strict';
const inspection = require('inspection');
module.exports.handler = function(event, context, cb) {
const inspect = inspection();
console.log(JSON.stringify(inspect));
cb(null, inspect);
};
We can execute the lambdas locally to test them.
# Install dependencies of the Lambdas
myrmex install-lambdas-locally config-128 config-512 config-1536
# Execute Lambdas locally
myrmex test-lambda-locally config-128
myrmex test-lambda-locally config-512
myrmex test-lambda-locally config-1536
Testing the Lambdas in AWS
Lets deploy in AWS!
myrmex deploy-lambdas config-128 config-1536 config-512 --region us-east-1 --environment DEV --alias v0
Now we can execute the Lambdas in AWS using Myrmex, but you can also use the AWS console if you prefer.
myrmex test-lambda config-128 --region us-east-1 --environment DEV --alias v0
myrmex test-lambda config-512 --region us-east-1 --environment DEV --alias v0
myrmex test-lambda config-1536 --region us-east-1 --environment DEV --alias v0
Check the result of the functions to have insights about the execution environment of Lambdas. Observe the variations when calling several times the same function.
TODO: explain results and add a module to profile the use of require() with/without warm up of a Lambda.
Creating APIs for a space delivery company
Creating APIs for a space delivery company
The need: one application, several APIs exposing various functionalities
The code generated by this example is available here.
Planet Express is a space delivery company that have two types of customers :
- Senders like MomCorp and the Slurm factory that use Planet Express services to deliver products
- Recipients like the Luna Park or the Mars Vegas Casinos that receive these products
Planet Express, as a futurist company, wants to provide serverless APIs, web and mobile applications for their customers.
- Senders need an API to create and track deliveries
- Recipients need an API to track and validate the reception of deliveries
- Planet Express also needs an API for its Back Office application that manage all deliveries
Following REST principles, a simplified API implementing these functionalities should expose these endpoints :
PUT /delivery
to create of a new deliveryGET /delivery/{id}
to allow to track a deliveryPATCH /delivery/{id}
to modify a deliveryDELETE /delivery/{id}
to delete a delivery
We state that a sender cannot modify a delivery once created and a recipient deletes a delivery when it receives it.
Planet Express wants to provide an Swagger
specification to document the endpoints for development teams that integrate
the services.
To avoid exposing and documenting endpoints not needed by some API consumers, Planet Express wants a specific API for each
type of client application : sender
, recipient
and back-office
.
These three APIs belong to the same application and share the same code base. The back-office
API will provide access to
all functionalities while the consumers of the sender
and the recipient
APIs will only have access to endpoints that are
useful for them.
sender |
recipient |
back-office |
|
---|---|---|---|
POST /delivery |
X | X | |
GET /delivery/{id} |
X | X | X |
PATCH /delivery/{id} |
X | ||
DELETE /delivery/{id} |
X | X |
We will not see the implementation of authentication and authorization here. Neither will we see the implementation of the
data access. These are aspects of the application that do not rely on Myrmex. They are implemented in node.js
modules that
could run in any execution environment.
The creation of the application with Myrmex
For each command used in the following sections, it is possible to see its documentation using myrmex <command> -h
. Note
that the Myrmex cli itself only contains the command myrmex new
. Other commands are injected by Myrmex plugins when the
cli is executed in the project folder.
Initialization of the project
We create a new Myrmex project named planet-express
.
npm install -g @myrmex/cli
myrmex new planet-express @myrmex/iam @myrmex/api-gateway @myrmex/lambda
cd planet-express
Creation of the Lambda containing the application logic
We are free to use as many Lambdas as we want in a Myrmex project. For example, we could associate one specific Lambda for each endpoint. But the Planet Express development team choose to put all the logic of the application in one single Lambda. Parameters provided by API Gateway will allow the lambda to know which portions of code to execute.
The implementation of the Lambda and of the modules is out of the scope of this tutorial. We will create them and leave them empty. This will give an overview of the structure of a Myrmex project and show the integration of Lambdas with API Gateway. Myrmex helps you to organize and deploy serverless projects, but it does not interfere about how you write Node.js code.
Creation of the Lambda's execution role
The Lambda needs to be associated to an IAM role that defines its authorizations in AWS. It could be authorized to access DynamoDB, RDS or S3 depending on the implementation of the application. For now, we use a role that allows the Lambda to write logs in CloudWatch.
myrmex create-role PlanetExpressLambdaExecution --model LambdaBasicExecutionRole
Creation of node modules that can be packaged in the Lambda
Myrmex allows the creation of node modules that can be embedded in the package of the Lambda. The development team decided that they will need two modules:
- A logging module that should allow to write logs in various backends (Cloudfront, S3, a database, etc ...)
- A module that manage the access to the application data (DynamoDB, Sequelize, mongoose, etc ...)
The data access module uses the logging module. We indicate this dependency so that if a Lambda requires the data access module, it will include the logging module in its package too.
myrmex create-node-module log
myrmex create-node-module data-access --dependencies log
The implementation of the modules will not be detailed here, but they are "common" node.js
modules that could be used in any execution environment.
Creation of a Lambda
We create a Lambda, specifying its configuration and its dependencies.
myrmex create-lambda api-generic --runtime nodejs6.10 --timeout 20 --memory 256 --role PlanetExpressLambdaExecution --dependencies data-access,log
Creation of the endpoints and APIs
Now that we have a Lambda able to perform the operations needed by our application, we can define the endpoints that integrate with it and expose them in various APIs.
Creation of the APIs
We create one API for each type of client application.
myrmex create-api back-office --title "Back Office" --desc "Planet Express API for Back Office"
myrmex create-api sender --title "Sender" --desc "Planet Express API for sender application"
myrmex create-api recipient --title "Recipient" --desc "Planet Express API for recipient application"
Creation of the invocation role
The API endpoints need to be associated to an IAM role that allows to invoke the Lambda.
myrmex create-role PlanetExpressLambdaInvocation -m APIGatewayLambdaInvocation
Creation of the endpoints
We create the four endpoints and associate them to the APIs that have to expose them.
myrmex create-endpoint /delivery/{id} get --apis back-office,recipient,sender --summary "View a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} patch --apis back-office --summary "Update a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery post --apis back-office,sender --summary "Create a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} delete --apis back-office,recipient --summary "Delete a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
Deployment
We deploy the stage v0
of the three APIs on the DEV
environment.
myrmex deploy-apis back-office sender recipient --region us-east-1 --stage v0 --environment DEV --deploy-lambdas all --alias ""
Altogether
npm install -g @myrmex/cli
myrmex new planet-express @myrmex/iam @myrmex/api-gateway @myrmex/lambda
cd planet-express
myrmex create-role PlanetExpressLambdaExecution --model LambdaBasicExecutionRole
myrmex create-node-module log
myrmex create-node-module data-access --dependencies log
myrmex create-lambda api-generic --runtime nodejs6.10 --timeout 20 --memory 256 --role PlanetExpressLambdaExecution --dependencies data-access,log
myrmex create-api back-office --title "Back Office" --desc "Planet Express API for Back Office"
myrmex create-api sender --title "Sender" --desc "Planet Express API for sender application"
myrmex create-api recipient --title "Recipient" --desc "Planet Express API for recipient application"
myrmex create-role PlanetExpressLambdaInvocation -m APIGatewayLambdaInvocation
myrmex create-endpoint /delivery/{id} get --apis back-office,recipient,sender --summary "View a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} patch --apis back-office --summary "Update a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery post --apis back-office,sender --summary "Create a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} delete --apis back-office,recipient --summary "Delete a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex deploy-apis back-office sender recipient --region us-east-1 --stage v0 --environment DEV --deploy-lambdas all --alias ""