Skip to content

Instantly share code, notes, and snippets.

@faermanj
Last active July 16, 2017 15:26
Show Gist options
  • Save faermanj/5ef93929bca38f2eaacc8d255fb504b6 to your computer and use it in GitHub Desktop.
Save faermanj/5ef93929bca38f2eaacc8d255fb504b6 to your computer and use it in GitHub Desktop.
Live Coding @capside Barcelona

Event info: https://www.meetup.com/Barcelona-Amazon-Web-Services-Meetup/events/241356452/

This gist: https://gist.github.com/jfaerman/5ef93929bca38f2eaacc8d255fb504b6

Me: Julio Faerman - https://twitter.com/jmfaerman

Live Stream: https://www.twitch.tv/jmfaerman

Today goals:

  • Start an application from scratch
  • Well-architected (Secure, Reliable, Performance Efficient, Cost Efficient, Operational Excellence)

After today we should have a initial application running from static files using Amazon S3 and a serverless API usin AWS Lambda and API Gateway. In the next live coding sessions we can build authentication, data access, machine learning and much more, join the AWS Barcelona Meetup!

  • Create an AWS Account on http://aws.amazon.com/free
  • Create an IAM User with Programmatic Access (note the Access Key and Secret Key) and Administrator Policy
  • Install AWS CLI from http://aws.amazon.com.cli
  • Setup CLI credentials and Region (profile is recommended to use multiple aws accounts)
$ aws configure --profile=awsdev
...
$ export AWS_PROFILE=awsdev
$ export AWS_REGION=us-east-1
  • Verify CLI access
$ aws iam get-user
{
    "User": {
        "UserName": "dalek",
        "Path": "/",
        "CreateDate": "2016-05-27T00:38:59Z",
        "UserId": "AIDAIOTCGLU7ZBPBV2UHY",
        "Arn": "arn:aws:iam::030555009967:user/dalek"
    }
}
$ aws ec2 describe-regions --output=text
REGIONS	ec2.ap-south-1.amazonaws.com	ap-south-1
REGIONS	ec2.eu-west-2.amazonaws.com	eu-west-2
REGIONS	ec2.eu-west-1.amazonaws.com	eu-west-1
REGIONS	ec2.ap-northeast-2.amazonaws.com	ap-northeast-2
REGIONS	ec2.ap-northeast-1.amazonaws.com	ap-northeast-1
REGIONS	ec2.sa-east-1.amazonaws.com	sa-east-1
REGIONS	ec2.ca-central-1.amazonaws.com	ca-central-1
REGIONS	ec2.ap-southeast-1.amazonaws.com	ap-southeast-1
REGIONS	ec2.ap-southeast-2.amazonaws.com	ap-southeast-2
REGIONS	ec2.eu-central-1.amazonaws.com	eu-central-1
REGIONS	ec2.us-east-1.amazonaws.com	us-east-1
REGIONS	ec2.us-east-2.amazonaws.com	us-east-2
REGIONS	ec2.us-west-1.amazonaws.com	us-west-1
REGIONS	ec2.us-west-2.amazonaws.com	us-west-2
  • Create a folder for the static website. Any name is fine, here we'll use the profile name and a separate dir for static files.
APP_DIR="${AWS_PROFILE}/static"
mkdir -p $APP_DIR
pushd "$APP_DIR"
  • Create a HTML static file named index.html
<html>
  <h1>Hola Mundo!</h1>
</html>
  • Create a S3 bucket with a unique name
$ BUILD_ID=$(date "+%Y%m%d%H%M%S")
$ BUCKET_NAME="${AWS_PROFILE}-${BUILD_ID}"
$ BUCKET_URL="s3://$BUCKET_NAME"

$ aws s3 mb $BUCKET_URL
make_bucket: awsdev-20170714140925
  • Setup website hosting with index document
$ aws s3 website $BUCKET_URL --index-document index.html
  • Upload website files with public read access
$ aws s3 sync . $BUCKET_URL --acl public-read

upload: ./index.html to s3://awsdev-20170714140925/index.html
  • Verify website is published
APP_URL="http://${BUCKET_NAME}.s3-website-us-east-1.amazonaws.com/"
curl -v $APP_URL

*   Trying 52.216.229.18...
* TCP_NODELAY set
* Connected to awsdev-20170714143104.s3-website-us-east-1.amazonaws.com (52.216.229.18) port 80 (#0)
> GET / HTTP/1.1
> Host: awsdev-20170714143104.s3-website-us-east-1.amazonaws.com
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 200 OK
< x-amz-id-2: ebQ02FUDku7Y0lkc3jRJJNqElXS+DNWXXPSyTPAUp+UIoYG3yQmD8qFjrhdabs9YaP54rre5wY4=
< x-amz-request-id: 270BB7E5832A9266
< Date: Fri, 14 Jul 2017 12:33:01 GMT
< Last-Modified: Fri, 14 Jul 2017 12:32:11 GMT
< ETag: "a63be6917f6571a539a278730f9b4c0e"
< Content-Type: text/html
< Content-Length: 38
< Server: AmazonS3
<
<html>
  <h1>Hola Mundo!</h1>
</html>
* Curl_http_done: called premature == 0
* Connection #0 to host awsdev-20170714143104.s3-website-us-east-1.amazonaws.com left intact
  • Create a new directory for the API tier
mkdir ../api
pushd ../api
npm install -g serverless
  • Create a servless API
$ serverless create \
  --template aws-nodejs \
  --name $API_NAME
  • Change the serverless.yml file:
    • Update Node.JS
    • Select region
    • Select deployment stage name
    • Enable Cross Origin Resource Sharing (CORS)
# serverless.yml

service: awsdevapi

provider:
  name: aws
  runtime: nodejs6.10
  region: us-east-1
  stage: prod

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: hello
          method: get
          cors: true
  • Update function code in handler.js to return HTTP headers to be bypassed by lambda-proxy and computed message
'use strict';

module.exports.hello = function(event, context, callback) {

    const response = {
      statusCode: 200,
      headers: {
        "Access-Control-Allow-Origin" : "*",
        "Access-Control-Allow-Credentials" : true
      },
      body: JSON.stringify({ "message": "Hello World! 0.1+0.1+0.1="+(0.1+0.1+0.1) })
    };

    callback(null, response);
};
  • Deploy API
$ sls deploy
...
endpoints:
  GET - https://cjxpxfejol.execute-api.us-east-1.amazonaws.com/prod/hello
...
  • Verify deployment
$ curl -v https://cjxpxfejol.execute-api.us-east-1.amazonaws.com/prod/hello
*   Trying 54.192.28.91...
* TCP_NODELAY set
* Connected to cjxpxfejol.execute-api.us-east-1.amazonaws.com (54.192.28.91) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.execute-api.us-east-1.amazonaws.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> GET /prod/hello HTTP/1.1
> Host: cjxpxfejol.execute-api.us-east-1.amazonaws.com
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 58
< Connection: keep-alive
< Date: Fri, 14 Jul 2017 13:20:35 GMT
< x-amzn-RequestId: 385e3d73-6897-11e7-97a9-493f386caa95
< Access-Control-Allow-Origin: *
< X-Amzn-Trace-Id: sampled=0;root=1-5968c523-5990b7de3ddfc518b194c172
< Access-Control-Allow-Credentials: true
< X-Cache: Miss from cloudfront
< Via: 1.1 22d1048cb75c81d8e25a9b2b49d5d6ab.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: MGkOAl_DOLdc_V6JQvQgZ3CdlprTuK1Z0geRMeogO4Mrzv5ZTBYOhQ==
<
* Curl_http_done: called premature == 0
* Connection #0 to host cjxpxfejol.execute-api.us-east-1.amazonaws.com left intact
{"message":"Hello World! 0.1+0.1+0.1=0.30000000000000004"}

  • Change HTML to use new API
<html>
  <h1>Loading...</h1>
  <script>
  window.onload = function(){
    var url = "https://cjxpxfejol.execute-api.us-east-1.amazonaws.com/prod/hello";
    fetch(url).then(function(response) {
      return response.json();
    }).then(function(json) {
      const h1 = document.querySelector('h1');
      h1.innerHTML = json.message;
    });
  }
  </script>
</html>
  • Upload new HTML to S3
$ popd
$ aws s3 sync . $BUCKET_URL --acl public-read

  • Verify application

Screenshot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment