Commit b8b14843 authored by Bertrand PINEL's avatar Bertrand PINEL

Add provision of Cloud directory in project file

parent da64fe8c
......@@ -8,6 +8,11 @@ It could also be seen as a starter for setting up Mirage, allowing the developpe
Complete code is available at https://gitlab.ippon.fr/bpinel/ember-aws-ehipster
A full tutorial is available on the Ippon Blog :
* in english: https://blog.ippon.tech/a-guinea-pig-in-the-cloud/
* in french: https://blog.ippon.fr/2019/03/19/un-cochon-dinde-dans-le-cloud/
Installation
------------------------------------------------------------------------------
......
Installing AWS infrastructure through Terraform scripts
==============================================================================
This file explains how to set up the expected infrastructure awaited to implement the JSON API.
The installation is based on Terraform (https://www.terraform.io/)
It expects that both AWS CLI and Terraform have been previously installed and set up correctly.
The AWS Credentials should also have been set up
How it works
------------------------------------------------------------------------------
AWS JSON API server relies on 3 main components, plus the needed IAM roles :
- A DynamoDB table manipuling all serialized objects
- A lambda function in charge of the translation from JSON API format to dynamoDB objects and managing the relationships and the optional parameters provided in the request
- An API Gateway configured to received the REST HTTP requests and proxying the Lambda
It also create three S3 buckets, one for storing the lambda code (nammed lambda-jsonapi-code-bucket) and the two other for receiving the ‘staging’ and ‘production’ version of the application (respectively nammed ember-aws-ehipster-staging and ember-aws-ehipster-production)
Several Terraform files are available, each one creating the needed component and their relationships with each other.
Installation
------------------------------------------------------------------------------
One this is done, simply run the terraform script :
```
terraform init
terraform apply -var bucket_name=<bucket name for static web site>
```
\ No newline at end of file
variable "bucket_name_production" {
type = "string"
default = "ember-aws-ehipster-production"
}
variable "bucket_name_staging" {
type = "string"
default = "ember-aws-ehipster-staging"
}
resource "aws_s3_bucket" "lambda-bucket" {
bucket = "lambda-jsonapi-code-bucket"
acl = "public-read"
}
resource "aws_s3_bucket_object" "lambda-bucket-code" {
bucket = "${aws_s3_bucket.lambda-bucket.bucket}"
key = "v1.0.0/lambda-jsonapi.zip"
source = "../lambda/lambda-jsonapi.zip"
etag = "${md5(file("../lambda/lambda-jsonapi.zip"))}"
}
resource "aws_s3_bucket" "production" {
bucket = "${var.bucket_name_production}"
acl = "public-read"
website {
index_document = "index.html"
error_document = "index.html"
}
}
resource "aws_s3_bucket" "staging" {
bucket = "${var.bucket_name_staging}"
acl = "public-read"
website {
index_document = "index.html"
error_document = "index.html"
}
}
locals {
s3_origin_id = "S3Origin"
}
resource "aws_cloudfront_distribution" "s3_distribution_production" {
origin {
domain_name = "${element(split("/","${aws_s3_bucket.production.website_endpoint}"),2)}"
origin_id = "${local.s3_origin_id}"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only"
origin_ssl_protocols = ["SSLv3", "TLSv1.1", "TLSv1.2"]
}
}
enabled = true
http_version = "http2"
is_ipv6_enabled = true
comment = "Production ehipster ClondFront"
default_root_object = "index.html"
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
compress = true
cached_methods = ["GET", "HEAD"]
target_origin_id = "${local.s3_origin_id}"
forwarded_values {
query_string = true
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
price_class = "PriceClass_All"
restrictions {
geo_restriction {
restriction_type = "none"
}
}
tags = {
Environment = "production"
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
resource "aws_cloudfront_distribution" "s3_distribution_staging" {
origin {
domain_name = "${element(split("/","${aws_s3_bucket.staging.website_endpoint}"),2)}"
origin_id = "${local.s3_origin_id}"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only"
origin_ssl_protocols = ["SSLv3", "TLSv1.1", "TLSv1.2"]
}
}
enabled = true
http_version = "http2"
is_ipv6_enabled = true
comment = "Staging ehipster ClondFront"
default_root_object = "index.html"
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
compress = true
cached_methods = ["GET", "HEAD"]
target_origin_id = "${local.s3_origin_id}"
forwarded_values {
query_string = true
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
price_class = "PriceClass_All"
restrictions {
geo_restriction {
restriction_type = "none"
}
}
tags = {
Environment = "staging"
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
resource "aws_dynamodb_table" "JsonApiTable" {
name = "JsonApiTable"
read_capacity = 3
write_capacity = 3
hash_key = "ObjectType"
range_key = "Id"
attribute {
name = "ObjectType"
type = "S"
}
attribute {
name = "Id"
type = "N"
}
}
resource "aws_iam_role" "lambda_jsonapi" {
name = "lambda_jsonapi"
path = "/"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
POLICY
}
resource "aws_iam_role_policy_attachment" "lambda_jsonapi_AmazonDynamoDBFullAccess" {
role = "${aws_iam_role.lambda_jsonapi.name}"
policy_arn = "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"
}
resource "aws_iam_role_policy_attachment" "lambda_jsonapi_CloudWatchFullAccess" {
role = "${aws_iam_role.lambda_jsonapi.name}"
policy_arn = "arn:aws:iam::aws:policy/CloudWatchFullAccess"
}
variable "region" {
default = "us-east-1"
}
provider "aws" {
region = "${var.region}"
}
resource "aws_lambda_function" "lambda-jsonapi" {
function_name = "lambda-jsonapi"
# The bucket name as created before running terraform scripts with "aws s3api create-bucket"
s3_bucket = "${aws_s3_bucket.lambda-bucket.bucket}"
s3_key = "${aws_s3_bucket_object.lambda-bucket-code.key}"
# "main" is the filename within the zip file (main.js) and "handler"
# is the name of the property under which the handler function was
# exported in that file.
handler = "lambda-jsonapi.handler"
runtime = "nodejs8.10"
role = "${aws_iam_role.lambda_jsonapi.arn}"
depends_on = ["aws_s3_bucket.lambda-bucket"]
}
# Allow API Gateway to access the defined lambda function
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.lambda-jsonapi.arn}"
principal = "apigateway.amazonaws.com"
# The /*/* portion grants access from any method on any resource
# within the API Gateway "REST API".
source_arn = "${aws_api_gateway_deployment.jsonapiDeployment.execution_arn}/*/*"
depends_on = ["aws_iam_role.lambda_jsonapi"]
}
\ No newline at end of file
#set($allParams = $input.params())
{
"body-json" : $input.json('$'),
"params" : {
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
},
"context" : {
"httpMethod" : "$context.httpMethod",
"account-id" : "$context.identity.accountId",
"api-id" : "$context.apiId",
"api-key" : "$context.identity.apiKey",
"authorizer-principal-id" : "$context.authorizer.principalId",
"caller" : "$context.identity.caller",
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
"stage" : "$context.stage",
"source-ip" : "$context.identity.sourceIp",
"user" : "$context.identity.user",
"user-agent" : "$context.identity.userAgent",
"user-arn" : "$context.identity.userArn",
"request-id" : "$context.requestId",
"resource-id" : "$context.resourceId",
"resource-path" : "$context.resourcePath"
}
}
\ No newline at end of file
......@@ -23,7 +23,8 @@ module.exports = {
return 'app';
}
},
__mirage__() { return '../mirage'}
__mirage__() { return '../mirage'},
__cloud__() { return '../cloud'}
}
},
......@@ -65,6 +66,10 @@ module.exports = {
let routerLine = "\tthis.route('entity-factory', function() {\n\t});\n";
addLineToFile(this, routerPath, /Router\.map\(function\(\) {/, routerLine);
// Add special rules to lint config file
let lintPath = ".template-lintrc.js";
let lintLines = ",\trules: {\n\t\t\"attribute-indentation\": false,\n\t\t\"block-indentation\": false\n\t}\n";
addLineToFile(this, lintPath, /extends: 'recommended'/, lintLines);
}
};
......
import Route from '@ember/routing/route';
import { hash } from 'rsvp';
export default Route.extend({
model() {
return Ember.RSVP.hash({
return hash({
<%=routeLoadModels%>
});
},
......
......@@ -37,6 +37,9 @@ function generateRowId(subid) {
objout.attributes[attr] = obj[attr];
} else {
let relationDetails = attr.split('_');
if (obj[attr] == null || typeof(obj[attr]) == "undefined" ) {
console.log("HUDSON, WE HAVE A PROBLEM with attr "+attr);
}
if (obj[attr].startsWith('[')) {
// hasMany relationship
let idsArray = obj[attr].substring(1, obj[attr].length-1).split(',');
......
......@@ -29,8 +29,8 @@ function generateRowId(subid) {
objout.attributes[attr] = obj[attr];
} else {
let relationDetails = attr.split('_');
if (obj[attr].startsWith('[')) {
// hasMany relationship
if (typeof obj[attr] == "string" && obj[attr].startsWith('[')) {
// hasMany relationship
let idsArray = obj[attr].substring(1, obj[attr].length-1).split(',');
let relData = [];
for (let l=0;l<idsArray.length;l++) {
......
{
"name": "ember-aws-ehipster",
"version": "0.4.3",
"version": "0.5.5",
"description": "Attempt to build a complete web application using serverless architecture on AWS",
"keywords": [
"ember-addon",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment