Skip to content
This repository has been archived by the owner on Sep 25, 2020. It is now read-only.

Commit

Permalink
Merge pull request #69 from speee/spotfleet_cloudformation
Browse files Browse the repository at this point in the history
SpotFleet CloudFormation
  • Loading branch information
selmertsx authored Jun 26, 2017
2 parents 8c1d620 + 7656843 commit 44b822d
Show file tree
Hide file tree
Showing 8 changed files with 420 additions and 0 deletions.
43 changes: 43 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,46 @@ application/config/environments/*.local.yml
.DS_Store
.AppleDouble
.LSOverride

### https://raw.github.com/github/gitignore/9f6724149b9a0a861b402683f6c50c5f085d130b/node.gitignore

# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

infrastructure/**/built
7 changes: 7 additions & 0 deletions infrastructure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## How to Deploy

```bash
# BUCKET_NAME is used for `aws cloudformation package`
# STACK_NAME is used for `aws cloudformation deploy`
$ BUCKET_NAME=bucket-name STACK_NAME=stack-name bin/deploy
```
30 changes: 30 additions & 0 deletions infrastructure/bin/deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

if [ -z "$BUCKET_NAME" ]; then
echo 'BUCKET_NAME is required'
exit 1
fi

if [ -z "$STACK_NAME" ]; then
echo 'STACK_NAME is required'
exit 1
fi

TEMPLATE_FILE=cloudformation.yml

# Move project root
cd "$(dirname "$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$0")")/.." || exit 1

sh -c 'cd ./functions/RunEcsTask && npm install && npm run build && cp -rf ./node_modules ./built/'

mkdir -p ./built

aws cloudformation package \
--template-file "$TEMPLATE_FILE" \
--output-template-file ./built/cloudformation.yml \
--s3-bucket "$BUCKET_NAME"

aws cloudformation deploy \
--capabilities CAPABILITY_NAMED_IAM \
--template-file built/cloudformation.yml \
--stack-name "$STACK_NAME"
217 changes: 217 additions & 0 deletions infrastructure/cloudformation.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: revieee development settings
Resources:

Expand Down Expand Up @@ -163,6 +164,53 @@ Resources:
Properties:
ClusterName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeCluster ] ]

#------ SpotFleet ---------#
EcsSpotFleetRequest:
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfigData:
IamFleetRole: !GetAtt FleetIAMRole.Arn
SpotPrice: !Ref SpotPrice
TargetCapacity: !Ref TargetCapacity
LaunchSpecifications:
- EbsOptimized: 'false'
InstanceType: !Ref MainContainerInstanceType
ImageId: !Ref ContainerInstanceImageId
WeightedCapacity: '4'
UserData:
Fn::Base64: !Sub |
#!/bin/bash
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
- EbsOptimizes: 'false'
InstanceType: !Ref SubContainerInstanceType
ImageId: !Ref ContainerInstanceImageId
SubnetId:
Ref: ContainerInstanceSubnet1c
WeightedCapacity: '1'
UserData:
Fn::Base64: !Sub |
#!/bin/bash
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config

FleetIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- spotfleet.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole'
RoleName: !Join [ "-", [ !Ref "AWS::StackName", FleetIAMRole ] ]

#------- SpotFleet/ --------#

EndpointInstanceIamRole:
Type: AWS::IAM::Role
Properties:
Expand Down Expand Up @@ -199,6 +247,159 @@ Resources:
Value: RevieeeEndpointInstance
# UserData: [TODO] run itamae

# ------ API Gateway ------

ApiRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- apigateway.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "states:*"
Resource: "*"
PolicyName: !Join [ "-", [ !Ref "AWS::StackName", AWSStepFunctionsFullAccess ] ]
RoleName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeApiRole ] ]

RevieeeApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Join [ "-", [ !Ref "AWS::StackName", RevieeeApi ] ]
RevieeeApiResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref RevieeeApi
ParentId: !GetAtt RevieeeApi.RootResourceId
PathPart: "stage"
RevieeeApiCreateMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RevieeeApi
ResourceId: !Ref RevieeeApiResource
AuthorizationType: NONE
HttpMethod: POST
Integration:
IntegrationHttpMethod: POST
IntegrationResponses:
- StatusCode: 200
PassthroughBehavior: WHEN_NO_TEMPLATES
RequestTemplates:
application/json: !Sub
- |-
{
"input": "{}",
"name": "Hello",
"stateMachineArn": "${stateMachineArn}"
}
- { stateMachineArn: !Ref StateMachineCreate }
Type: AWS
Uri: !Join [ "", [ "arn:aws:apigateway:", !Ref "AWS::Region", ":states:action/StartExecution" ] ]
Credentials: !GetAtt ApiRole.Arn
MethodResponses:
- StatusCode: 200
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: RevieeeApiCreateMethod
Properties:
RestApiId: !Ref RevieeeApi
StageName: pub

# ------ /API Gateway ------

# ------ StepFunctions ------

StateMachineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- states.ap-northeast-1.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "lambda:InvokeFunction"
Resource: "*"
PolicyName: !Join [ "-", [ !Ref "AWS::StackName", StatesExecutionPolicy ] ]
RoleName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeStateMachineRole ] ]

StateMachineCreate:
Type: AWS::StepFunctions::StateMachine
Properties:
DefinitionString: !Sub
- |-
{
"Comment": "Run ECS Task",
"StartAt": "RunEcsTask",
"States": {
"RunEcsTask": {
"Type": "Task",
"Resource": "${taskArn}",
"End": true
}
}
}
- { "taskArn": !Ref RunEcsTaskFunction }
RoleArn: !GetAtt StateMachineRole.Arn

# ------ /StepFunctions ------

# ------ Lambda ------

RunEcsTaskFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "ecs:RunTask"
Resource: "*"
PolicyName: !Join [ "-", [ !Ref "AWS::StackName", RunEcsTaskFunctionPolicy ] ]
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
RoleName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeRunEcsTaskFunctionRole ] ]

RunEcsTaskFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs6.10
CodeUri: ./functions/RunEcsTask/built/
Role: !GetAtt RunEcsTaskFunctionRole.Arn

# ------ /Lambda ------

# Parameter
Parameters:
SSHPort:
Expand All @@ -209,6 +410,22 @@ Parameters:
Type: String
AcceptCidrIp:
Type: String
# Parameters for SpotFleetRequest
SpotPrice:
Default: 0.139
Type: Number
TargetCapacity:
Default: 2
Type: Number
MainContainerInstanceType:
Default: 'm4.large'
Type: String
SubContainerInstanceType:
Default: 'm3.large'
Type: String
ContainerInstanceImageId:
Default: 'ami-3a000e5d'
Type: 'String'

Conditions:
SSHKeySpecified:
Expand Down
23 changes: 23 additions & 0 deletions infrastructure/functions/RunEcsTask/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "run-ecs-task",
"version": "0.0.1",
"description": "Lambda function that to run ECS Task",
"main": "index.js",
"scripts": {
"build": "tsc -p ./tsconfig.json",
"clean": "rm -rf ./built"
},
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/speee/webapp-revieee"
},
"devDependencies": {
"@types/aws-lambda": "0.0.12",
"@types/node": "^7.0.31",
"aws-sdk": "^2.71.0",
"tslint": "^5.4.3",
"typescript": "^2.3.4"
}
}
32 changes: 32 additions & 0 deletions infrastructure/functions/RunEcsTask/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Callback, Context } from "aws-lambda";
import * as AWS from "aws-sdk";

const ecs = new AWS.ECS();

export function handler(event: any, context: Context, callback: Callback) {
const envBranch: AWS.ECS.KeyValuePair = {
name: "BRANCH",
value: "master",
};
const containerOverride: AWS.ECS.ContainerOverride = {
name: "main",
environment: [envBranch],
};
const taskOverride: AWS.ECS.TaskOverride = {
containerOverrides: [containerOverride],
};
const params: AWS.ECS.RunTaskRequest = {
cluster: "revieee",
taskDefinition: "arn:aws:ecs:ap-northeast-1:951787653356:task-definition/im-ieul-core:3",
overrides: taskOverride,
};

(async () => {
return await ecs.runTask(params).promise();
})().then((result: AWS.ECS.RunTaskResponse) => {
console.log(result.tasks);
callback(null, result.tasks[0].taskArn);
}).catch((err: AWS.AWSError) => {
callback(err);
});
}
Loading

0 comments on commit 44b822d

Please sign in to comment.