Skip to main content

Your First Mantil Project

If you prefer watching videos over reading tutorials, a detailed step-by-step guide is available on youtube.

Prerequisites

We assume that you are Go programmer so you have Go installed. After that you need to download Mantil cli and set up Mantil node on your AWS account.

Create new project

Create a new project with mantil new command. It just creates project structure locally.

➜ mantil new my-project

Your project is ready in ./my-project

➜ tree my-project
my-project
├── api
│   └── ping
│   ├── ping.go
│   └── ping_test.go
├── config
│   ├── environment.yml
│   └── state.yml
├── go.mod
├── go.sum
└── test
├── init.go
└── ping_test.go

4 directories, 8 files

API folder is most interesting. Each Go package in the API folder, after deployment, becomes part of you applications API interface.

All other project commands are intended to be used from somewhere in the project tree. So enter the project now cd my-project.

Project stage

One Mantil project can have multiple deployments, each called deployment stage. So we can have stage for development, staging, production and so on. Each stage requires some resources on AWS and each stage is completely isolated from all other stages.
Stage is created on the specified node (if you have just one node than you don't need to say on which node).

To create first stage, named development run:

➜ mantil stage new development

Creating stage development on node demo
...

Deploy successful!
Build time: 625ms, upload: 728ms (5.4 MiB), update: 28.573s

Stage development is ready!
Endpoint: https://lh5rfrc3gf.execute-api.eu-central-1.amazonaws.com

This operation usually takes less than a minute to complete. Upon completion we have fully functional API on the AWS infrastructure.

To see what resources is created run mantil aws resources --stage development.

Endpoint from the command output is the api URL. To test that API exists run:

➜ mantil invoke ping
200 OK
pong

You can get the same result with any other tool:

➜ curl -X POST $(mantil env --url)/ping
pong%

mantil env --url returns API endpoint.

Each Go package in the api folder becomes route in the project URL. Package is expected to have exported New method which returns struct pointer. All exported methods of that struct will become accessible on endpoint/package/method URL. If there is a method named Default it is accessible on the endpoint/package (without method name) URL.

In our example package name is ping and we have Default method:

func (p *Ping) Default() string {
return "pong"
}

Exploring demo project

To execute non-default method we need to add method name to the path. Here is example of calling another method, named Hello:

➜ mantil invoke ping/hello --data "World"
200 OK
Hello, World

Hello method is again simple string in string out.

func (p *Ping) Hello(ctx context.Context, name string) (string, error) {
return "Hello, " + name, nil
}

You can also use curl for calling any method:

➜ curl -X POST $(mantil env --url)/ping/hello --data "World"
Hello, World%

ReqRsp demonstrates JSON formatted request/response:

➜ mantil invoke ping/reqrsp --data '{"name":"World"}'
200 OK
{
"Response": "Hello, World"
}

The logs method demonstrates display of function logs with invoke command. If your Lambda function is logging, the log lines are captured and shown before command output:

➜ mantil invoke ping/logs --data '{"name":"Foo"}'
λ start Logs method
λ req.Name: 'Foo'
λ end
200 OK
{
"Response": "Hello, Foo"
}

Testing

This project comes with integration tests. Run them with:

➜ mantil test
=== RUN TestPing
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/hello
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/hello
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/reqrsp
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/reqrsp2
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/non-existent-method
--- PASS: TestPing (0.62s)
PASS
ok my-project/test 0.902s

Test are located in test directory. When run they are using current stage to make requests and explore results.

Deployment

Lets first make some change into project to enable deployment. For example change "pong" string in Default method (file: api/ping/ping.go) to something else. I'll change it to "my-project" and than deploy changes with:

➜ mantil deploy

Building and deploying my-project to stage development
Building...
Uploading changes...
ping
Updating infrastructure...

Deploy successful!
Build time: 636ms, upload: 789ms (5.4 MiB), update: 1.618s

To test new behavior run invoke again:

➜ mantil invoke ping
200 OK
my-project

Run also mantil test again, it is failing because of this change:

➜ mantil test
=== RUN TestPing
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping
reporter.go:23:
Error Trace: reporter.go:23
chain.go:21
string.go:115
ping_test.go:17
Error:
expected string equal to:
"pong"

but got:
"my-project"
Test: TestPing
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/hello
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/hello
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/reqrsp
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/reqrsp2
printer.go:54: POST https://b2vhijcf2d.execute-api.eu-central-1.amazonaws.com/ping/non-existent-method
--- FAIL: TestPing (0.58s)
FAIL
exit status 1
FAIL my-project/test 0.867s

Working

There is mantil watch command to support this change/deploy/invoke cycle. It is monitoring project files for changes. On each change it deploys project and can call a method or run tests. Run:

mantil watch --method ping

and then change return string of the Default method and save changes few times to get the feeling.

To create new API run generate add implementation and deploy.

➜ mantil generate api second
Generating function second
test/init.go already exists
Generating test/second_test.go...
Generating api/second/second.go...

Now edit api/second/second.go add methods and deploy.

Cleanup

To remove project Stage from you AWS account run:

mantil stage destroy development

and after that mantil aws uninstall with the same attributes as in the first aws install step. And that's all. Your AWS account is the initial state.