<commit_before>= Serverless Lambda and API Gateway Using AWS CLI

Linked from link:readme.adoc[Microservice using AWS API Gateway, AWS Lambda and Couchbase].

. Create Lambda functions, one for each endpoint:
+
```
aws lambda create-function \
--function-name MicroserviceGetAll \
--role arn:aws:iam::598307997273:role/microserviceRole \
--handler org.sample.serverless.aws.couchbase.apigateway.BucketGetAll \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--description "Microservice HTTP Endpoint - Get All" \
--runtime java8 \
--region us-west-2 \
--timeout 30 \
--memory-size 1024 \
--environment Variables={COUCHBASE_HOST=ec2-35-163-21-104.us-west-2.compute.amazonaws.com} \
--publish
```
+
```
aws lambda create-function \
--function-name MicroservicePost \
--role arn:aws:iam::598307997273:role/microserviceRole \
--handler org.sample.serverless.aws.couchbase.apigateway.BucketPost \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--description "Microservice HTTP Endpoint - Post" \
--runtime java8 \
--region us-west-2 \
--timeout 30 \
--memory-size 1024 \
--environment Variables={COUCHBASE_HOST=ec2-35-163-21-104.us-west-2.compute.amazonaws.com} \
--publish
```
+
. (OPTIONAL) Update the function:
+
```
mvn clean package;
aws lambda update-function-code \
--function-name MicroservicePost \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--region us-west-2 \
--publish
```

== API Gateway Resources

. *Create API*
+
```
aws apigateway \
create-rest-api \
--name Book
```
+
to see the output:
+
```
{
    "name": "microservice", 
    "id": "3fsnu7i9k5", 
    "createdDate": 1483575361
}
```
+
Value of `id` attribute is `api-id`.
+
*Find the root id*: `aws apigateway get-resources --rest-api-id 3fsnu7i9k5`. It shows the output:
+
```
{
    "items": [
        {
            "path": "/", 
            "id": "s0oun9kp76"
        }
    ]
}
```
+
Value of `id` attribute is `root-id`. This is also the `parent-id` for top level resources.
+
. *Create resource*
+
```
aws apigateway create-resource \
--rest-api-id 3fsnu7i9k5 \
--parent-id s0oun9kp76 \
--path-part books
```
+
to see the output:
+
```
{
    "path": "/books", 
    "pathPart": "books", 
    "id": "ds9qul", 
    "parentId": "s0oun9kp76"
}
```
+
Value of `id` attribute is `resource-id`.

=== POST method

. *Create a `POST` method*
+
```
aws apigateway put-method \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--authorization-type NONE
```
+
to see the response:
+
```
{
    "apiKeyRequired": false, 
    "httpMethod": "POST", 
    "authorizationType": "NONE"
}
```
+
. *Configure Lambda function*
.. Set Lambda function as destination of POST
+
```
aws apigateway put-integration \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--type AWS \
--integration-http-method POST \
--uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost/invocations
```
+
to see the output:
+
```
{
    "httpMethod": "POST", 
    "passthroughBehavior": "WHEN_NO_MATCH", 
    "cacheKeyParameters": [], 
    "type": "AWS", 
    "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost/invocations", 
    "cacheNamespace": "ds9qul"
}
```
+
.. Set `content-type` of POST method response
+
```
aws apigateway put-method-response \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--status-code 200 \
--response-models "{\"application/json\": \"Empty\"}"
```
+
to see the response:
+
```
{
    "responseModels": {
        "application/json": "Empty"
    }, 
    "statusCode": "200"
}
```
+
.. Set `content-type` of POST method integration response
+
```
aws apigateway put-integration-response \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--status-code 200 \
--response-templates "{\"application/json\": \"Empty\"}"
```
+
to see the response:
+
```
{
    "statusCode": "200", 
    "responseTemplates": {
        "application/json": "Empty"
    }
}
```
+
. *Deploy the API*
+
```
aws apigateway create-deployment \
--rest-api-id 3fsnu7i9k5 \
--stage-name test
```
+
to see the output:
+
```
{
    "id": "roqra5", 
    "createdDate": 1483575542
}
```
+
. *Grant permission* to allow API Gateway to invoke Lambda Function
+
```
aws lambda add-permission \
--function-name MicroservicePost \
--statement-id apigateway-test-post-1 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-2:598307997273:3fsnu7i9k5/*/POST/books"
```
+
to see the response
+
```
{
    "Statement": "{\"Sid\":\"apigateway-test-post-1\",\"Resource\":\"arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":[\"lambda:InvokeFunction\"],\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-west-2:598307997273:lb2qgujjif/*/POST/books\"}}}"
}
```
+
Grant permission to the deployed API:
+
```
aws lambda add-permission \
--function-name MicroservicePost \
--statement-id apigateway-test-post-2 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-2:598307997273:3fsnu7i9k5/test/GET/books"
```
+
to see the output
+
```
{
    "Statement": "{\"Sid\":\"apigateway-test-post-2\",\"Resource\":\"arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":[\"lambda:InvokeFunction\"],\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-west-2:598307997273:lb2qgujjif/test/GET/books\"}}}"
}
```
+
. *Test method*
+
```
aws apigateway test-invoke-method \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--path-with-query-string "" \
--body "{\"id\": \"6\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}"
```
+
to see the response
+
```
{
    "status": 200, 
    "body": "Empty", 
    "log": "Execution log for request test-request\nThu Jan 05 00:21:05 UTC 2017 : Starting execution for request: test-invoke-request\nThu Jan 05 00:21:05 UTC 2017 : HTTP Method: POST, Resource Path: /books\nThu Jan 05 00:21:05 UTC 2017 : Method request path: {}\nThu Jan 05 00:21:05 UTC 2017 : Method request query string: {}\nThu Jan 05 00:21:05 UTC 2017 : Method request headers: {}\nThu Jan 05 00:21:05 UTC 2017 : Method request body before transformations: {\"id\": \"6\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}\nThu Jan 05 00:21:05 UTC 2017 : Endpoint request URI: https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost/invocations\nThu Jan 05 00:21:05 UTC 2017 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************7512bb, X-Amz-Date=20170105T002105Z, x-amzn-apigateway-api-id=3fsnu7i9k5, X-Amz-Source-Arn=arn:aws:execute-api:us-west-2:598307997273:3fsnu7i9k5/null/POST/books, Accept=application/json, User-Agent=AmazonAPIGateway_3fsnu7i9k5, X-Amz-Security-Token=<KEY> [TRUNCATED]\nThu Jan 05 00:21:05 UTC 2017 : Endpoint request body after transformations: {\"id\": \"6\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}\nThu Jan 05 00:21:05 UTC 2017 : Endpoint response body before transformations: {\"errorMessage\":\"Class not found: org.sample.serverless.aws.couchbase.apigateway.BucketPost\",\"errorType\":\"class java.lang.ClassNotFoundException\"}\nThu Jan 05 00:21:05 UTC 2017 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=d8f45cd8-d2dc-11e6-b83b-f54427452e6e, Connection=keep-alive, Content-Length=146, X-Amz-Function-Error=Unhandled, Date=Thu, 05 Jan 2017 00:21:05 GMT, Content-Type=application/json}\nThu Jan 05 00:21:05 UTC 2017 : Method response body after transformations: Empty\nThu Jan 05 00:21:05 UTC 2017 : Method response headers: {X-Amzn-Trace-Id=Root=1-586d9171-74e3cf5c46e18a79117fbd55, Content-Type=application/json}\nThu Jan 05 00:21:05 UTC 2017 : Successfully completed execution\nThu Jan 05 00:21:05 UTC 2017 : Method completed with status: 200\n", 
    "latency": 59, 
    "headers": {
        "X-Amzn-Trace-Id": "Root=1-586d9171-74e3cf5c46e18a79117fbd55", 
        "Content-Type": "application/json"
    }
}
```
+
. Get detailed logs using `aws logs filter-log-events --log-group /aws/lambda/MicroservicePost`.

=== GET method

. *Create a `GET` method*
+
```
aws apigateway put-method \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method GET \
--authorization-type NONE
```
. *Configure Lambda function*
.. Set Lambda function as destination of GET
+
```
aws apigateway put-integration \
--rest-api-id 3fsnu7i9k5 \<commit_msg>updating output for POST<commit_after>= Serverless Lambda and API Gateway Using AWS CLI

Linked from link:readme.adoc[Microservice using AWS API Gateway, AWS Lambda and Couchbase].

. Create Lambda functions, one for each endpoint:
+
```
aws lambda create-function \
--function-name MicroserviceGetAll \
--role arn:aws:iam::598307997273:role/microserviceRole \
--handler org.sample.serverless.aws.couchbase.apigateway.BucketGetAll \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--description "Microservice HTTP Endpoint - Get All" \
--runtime java8 \
--region us-west-2 \
--timeout 30 \
--memory-size 1024 \
--environment Variables={COUCHBASE_HOST=ec2-35-163-21-104.us-west-2.compute.amazonaws.com} \
--publish
```
+
```
aws lambda create-function \
--function-name MicroservicePost \
--role arn:aws:iam::598307997273:role/microserviceRole \
--handler org.sample.serverless.aws.couchbase.apigateway.BucketPost \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--description "Microservice HTTP Endpoint - Post" \
--runtime java8 \
--region us-west-2 \
--timeout 30 \
--memory-size 1024 \
--environment Variables={COUCHBASE_HOST=ec2-35-163-21-104.us-west-2.compute.amazonaws.com} \
--publish
```
+
. (OPTIONAL) Update the function:
+
```
mvn clean package;
aws lambda update-function-code \
--function-name MicroservicePost \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--region us-west-2 \
--publish
```

== API Gateway Resources

. *Create API*
+
```
aws apigateway \
create-rest-api \
--name Book
```
+
to see the output:
+
```
{
    "name": "microservice", 
    "id": "3fsnu7i9k5", 
    "createdDate": 1483575361
}
```
+
Value of `id` attribute is `api-id`.
+
*Find the root id*: `aws apigateway get-resources --rest-api-id 3fsnu7i9k5`. It shows the output:
+
```
{
    "items": [
        {
            "path": "/", 
            "id": "s0oun9kp76"
        }
    ]
}
```
+
Value of `id` attribute is `root-id`. This is also the `parent-id` for top level resources.
+
. *Create resource*
+
```
aws apigateway create-resource \
--rest-api-id 3fsnu7i9k5 \
--parent-id s0oun9kp76 \
--path-part books
```
+
to see the output:
+
```
{
    "path": "/books", 
    "pathPart": "books", 
    "id": "ds9qul", 
    "parentId": "s0oun9kp76"
}
```
+
Value of `id` attribute is `resource-id`.

=== POST method

. *Create a `POST` method*
+
```
aws apigateway put-method \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--authorization-type NONE
```
+
to see the response:
+
```
{
    "apiKeyRequired": false, 
    "httpMethod": "POST", 
    "authorizationType": "NONE"
}
```
+
. *Configure Lambda function*
.. Set Lambda function as destination of POST
+
```
aws apigateway put-integration \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--type AWS \
--integration-http-method POST \
--uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost/invocations
```
+
to see the output:
+
```
{
    "httpMethod": "POST", 
    "passthroughBehavior": "WHEN_NO_MATCH", 
    "cacheKeyParameters": [], 
    "type": "AWS", 
    "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost/invocations", 
    "cacheNamespace": "ds9qul"
}
```
+
.. Set `content-type` of POST method response
+
```
aws apigateway put-method-response \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--status-code 200 \
--response-models "{\"application/json\": \"Empty\"}"
```
+
to see the response:
+
```
{
    "responseModels": {
        "application/json": "Empty"
    }, 
    "statusCode": "200"
}
```
+
.. Set `content-type` of POST method integration response
+
```
aws apigateway put-integration-response \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--status-code 200 \
--response-templates "{\"application/json\": \"Empty\"}"
```
+
to see the response:
+
```
{
    "statusCode": "200", 
    "responseTemplates": {
        "application/json": "Empty"
    }
}
```
+
. *Deploy the API*
+
```
aws apigateway create-deployment \
--rest-api-id 3fsnu7i9k5 \
--stage-name test
```
+
to see the output:
+
```
{
    "id": "roqra5", 
    "createdDate": 1483575542
}
```
+
. *Grant permission* to allow API Gateway to invoke Lambda Function
+
```
aws lambda add-permission \
--function-name MicroservicePost \
--statement-id apigateway-test-post-1 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-2:598307997273:3fsnu7i9k5/*/POST/books"
```
+
to see the response
+
```
{
    "Statement": "{\"Sid\":\"apigateway-test-post-1\",\"Resource\":\"arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":[\"lambda:InvokeFunction\"],\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-west-2:598307997273:lb2qgujjif/*/POST/books\"}}}"
}
```
+
Grant permission to the deployed API:
+
```
aws lambda add-permission \
--function-name MicroservicePost \
--statement-id apigateway-test-post-2 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-2:598307997273:3fsnu7i9k5/test/GET/books"
```
+
to see the output
+
```
{
    "Statement": "{\"Sid\":\"apigateway-test-post-2\",\"Resource\":\"arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":[\"lambda:InvokeFunction\"],\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-west-2:598307997273:lb2qgujjif/test/GET/books\"}}}"
}
```
+
. *Test method*
+
```
aws apigateway test-invoke-method \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method POST \
--path-with-query-string "" \
--body "{\"id\": \"6\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}"
```
+
to see the response
+
```
{
    "status": 200, 
    "body": "Empty", 
    "log": "Execution log for request test-request\nThu Jan 05 00:38:28 UTC 2017 : Starting execution for request: test-invoke-request\nThu Jan 05 00:38:28 UTC 2017 : HTTP Method: POST, Resource Path: /books\nThu Jan 05 00:38:28 UTC 2017 : Method request path: {}\nThu Jan 05 00:38:28 UTC 2017 : Method request query string: {}\nThu Jan 05 00:38:28 UTC 2017 : Method request headers: {}\nThu Jan 05 00:38:28 UTC 2017 : Method request body before transformations: {\"id\": \"6\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}\nThu Jan 05 00:38:28 UTC 2017 : Endpoint request URI: https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:598307997273:function:MicroservicePost/invocations\nThu Jan 05 00:38:28 UTC 2017 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************a1d8c4, X-Amz-Date=20170105T003828Z, x-amzn-apigateway-api-id=3fsnu7i9k5, X-Amz-Source-Arn=arn:aws:execute-api:us-west-2:598307997273:3fsnu7i9k5/null/POST/books, Accept=application/json, User-Agent=AmazonAPIGateway_3fsnu7i9k5, X-Amz-Security-Token=FQoDYXdzEOH//////////wEaDOcimMO4oJrtLXiwJyK3A6U8NiIZZs1ubfhCuqBwgrAN9SQlp2rg0yDsI6ROaelCAbBBQMl0oP4vK+bfC3d+P7vYW94qqYpY2bDZtKNem+oBf3TTjeQne2ZNRq1XMQ2Ph2lJyts1EzaK18q/5KcctLCfoxI9zfYctpPx1ZU4qybsa2FPNdQe1sRdOLKIpXDvBl+lMaYegqq4mPRx4kUYDlkX/GohH1f9ybCQbfC86ay2NkwFgOY2UA54Qq6voB4rxvaHiXioJ6qzFtBCxoeorFrQvoa0XIMXRH02ske1ImVHukPI57x8Z6n+6p81EBQfpeyaQ1EApLtRyTxHY1I [TRUNCATED]\nThu Jan 05 00:38:28 UTC 2017 : Endpoint request body after transformations: {\"id\": \"6\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}\nThu Jan 05 00:38:35 UTC 2017 : Endpoint response body before transformations: \"{\\\"name\\\":null,\\\"cost\\\":\\\"1.23\\\",\\\"id\\\":\\\"6\\\",\\\"isbn\\\":\\\"123\\\"}\"\nThu Jan 05 00:38:35 UTC 2017 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=46c600c4-d2df-11e6-b378-55d8ead25460, Connection=keep-alive, Content-Length=65, Date=Thu, 05 Jan 2017 00:38:34 GMT, Content-Type=application/json}\nThu Jan 05 00:38:35 UTC 2017 : Method response body after transformations: Empty\nThu Jan 05 00:38:35 UTC 2017 : Method response headers: {X-Amzn-Trace-Id=Root=1-586d9584-ea10523d888997782f3cba94, Content-Type=application/json}\nThu Jan 05 00:38:35 UTC 2017 : Successfully completed execution\nThu Jan 05 00:38:35 UTC 2017 : Method completed with status: 200\n", 
    "latency": 6467, 
    "headers": {
        "X-Amzn-Trace-Id": "Root=1-586d9584-ea10523d888997782f3cba94", 
        "Content-Type": "application/json"
    }
}
```
+
. Get detailed logs using `aws logs filter-log-events --log-group /aws/lambda/MicroservicePost`.

=== GET method

. *Create a `GET` method*
+
```
aws apigateway put-method \
--rest-api-id 3fsnu7i9k5 \
--resource-id ds9qul \
--http-method GET \
--authorization-type NONE
```
. *Configure Lambda function*
.. Set Lambda function as destination of GET
+
```
aws apigateway put-integration \
--rest-api-id 3fsnu7i9k5 \
{'fraction_non_alphanumeric': 0.21101443234512582, 'fraction_numerical': 0.07226593028708383, 'mean_word_length': 4.057707509881423, 'pattern_counts': {'":': 142, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6252517', 'n_tokens_mistral': 7954, 'n_tokens_neox': 6821, 'n_words': 1308}