Skip to content

Instantly share code, notes, and snippets.

@teknogeek0
Created January 16, 2013 15:48
Show Gist options
  • Save teknogeek0/4548131 to your computer and use it in GitHub Desktop.
Save teknogeek0/4548131 to your computer and use it in GitHub Desktop.
slightly cleaned up bees with machine guns cloudformation template
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Create a spot-priced AutoScaling group and a Bees With Machine Guns controller; execute the load test against the AutoScaling group and store the results in S3. Run /home/ec2-user/run-bees to execute load tests manually.",
"Parameters": {
"KeyName": {
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances",
"Type": "String"
},
"BeesControllerInstanceType": {
"Description": "Type of EC2 instance to launch",
"Type": "String",
"Default": "c1.medium",
"AllowedValues": [
"t1.micro",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge",
"m2.xlarge",
"m2.2xlarge",
"m2.4xlarge",
"c1.medium",
"c1.xlarge",
"cc1.4xlarge"
],
"ConstraintDescription": "Must be a valid EC2 instance type."
},
"TotalConnections": {
"Description": "Total connections per load tester",
"Type": "Number",
"Default": "200000"
},
"SpotPrice": {
"Description": "Spot price for application AutoScaling Group",
"Type": "Number",
"MinValue" : "0"
},
"ConcurrentConnections": {
"Description": "Number of concurrent requests per load tester",
"Type": "Number",
"Default": "1000"
},
"BeeCount": {
"Description": "Number of EC2 instances to launch as the load generators (bees)",
"Type": "Number",
"Default": "2"
},
"Target2Sting" : {
"Description": "The domain or hostname to send the bees to attack",
"Type": "String",
"Default": "http://localhost/"
},
"RunTests": {
"Description": "Enter 'true' to run tests immediately. WARNING: CreateStack will not finish until test executes if this is set to 'true'",
"Type": "String",
"Default": "true",
"AllowedValues": [ "true", "false" ],
"ConstraintDescription": "Must be 'true' or 'false'."
}
},
"Mappings": {
"AWSRegionPlatform2AMI": {
"us-east-1": {
"amzn": "ami-e565ba8c",
"bee" : "ami-e661c18f"
},
"us-west-1": {
"amzn": "ami-e78cd4a2",
"bee" : "ami-93b5efd6"
},
"eu-west-1": {
"amzn": "ami-f9231b8d",
"bee" : "ami-67212413"
},
"ap-southeast-1": {
"amzn": "ami-be3374ec",
"bee" : "ami-38bef86a"
},
"ap-northeast-1": {
"amzn": "ami-e47acbe5",
"bee" : "ami-16ac1f17"
},
"us-west-2": {
"amzn": "ami-3ac64a0a",
"bee" : "ami-bc05898c"
},
"sa-east-1": {
"amzn": "ami-a6855bbb",
"bee" : "ami-5a12cc47"
}
}
},
"Resources": {
"CfnUser": {
"Type": "AWS::IAM::User",
"Properties": {
"Path": "/",
"Policies": [
{
"PolicyName": "root",
"PolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Action": "cloudformation:DescribeStackResource",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "elasticloadbalancing:DescribeInstanceHealth",
"Resource": "*"
},
{
"Effect" : "Allow",
"Action" : "ec2:*",
"Resource" : "*"
}
]
}
}
]
}
},
"CfnKeys": {
"Type": "AWS::IAM::AccessKey",
"Properties": {
"UserName": {
"Ref": "CfnUser"
}
}
},
"ResultBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"AccessControl": "Private"
},
"DeletionPolicy" : "Retain"
},
"BucketPolicy" : {
"Type" : "AWS::S3::BucketPolicy",
"Properties" : {
"PolicyDocument": {
"Version" : "2008-10-17",
"Id" : "MyPolicy",
"Statement" : [{
"Sid" : "AllAccess",
"Action" : ["s3:*"],
"Effect" : "Allow",
"Resource" : { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ResultBucket" }, "/*"]]},
"Principal" : { "AWS": {"Fn::GetAtt" : ["CfnUser", "Arn"]} }
}]
},
"Bucket" : { "Ref" : "ResultBucket" }
}
},
"BeeController": {
"Type": "AWS::EC2::Instance",
"Metadata": {
"AWS::CloudFormation::Init": {
"config": {
"packages": {
"yum": {
"gcc": [],
"gcc-c++": [],
"make": [],
"openssl-devel": [],
"httpd": [],
"python-paramiko": [],
"gmp-devel" : [],
"python26-devel" : []
},
"python" : {
"beeswithmachineguns" : []
}
},
"files": {
"/home/ec2-user/create-keypair" : {
"content" : {
"Fn::Join" : ["", ["#!/usr/bin/python\n",
"import string\n",
"import random\n",
"import boto.ec2\n",
"kp_name = ''.join(random.choice(string.letters) for i in xrange(16))\n",
"ec2 = boto.ec2.connect_to_region('", {"Ref" : "AWS::Region" }, "')\n",
"keypair = ec2.create_key_pair(kp_name)\n",
"keypair.save('/home/ec2-user/.ssh/')\n",
"with file('/home/ec2-user/bees_keypair.txt', 'w') as f:\n",
" f.write(kp_name)\n",
"print 'Created keypair: %s' % kp_name\n"]]
},
"mode" : "000750",
"owner" : "ec2-user",
"group" : "ec2-user"
},
"/home/ec2-user/delete-keypair" : {
"content" : {
"Fn::Join" : ["", ["#!/usr/bin/python\n",
"import string\n",
"import random\n",
"import boto.ec2\n",
"import os\n",
"import sys\n",
"if not os.path.exists('/home/ec2-user/bees_keypair.txt'):\n",
" print >> sys.stderr, 'bees_keypair.txt does not exist'\n",
" sys.exit(-1)\n",
"with file('/home/ec2-user/bees_keypair.txt', 'r') as f:\n",
" kp_name = f.read().strip()\n",
"ec2 = boto.ec2.connect_to_region('", {"Ref" : "AWS::Region" }, "')\n",
"ec2.delete_key_pair(kp_name)\n",
"os.remove('/home/ec2-user/bees_keypair.txt')\n",
"os.remove('/home/ec2-user/.ssh/%s.pem' % kp_name)\n",
"print 'Deleted keypair: %s' % kp_name\n"]]
},
"mode" : "000750",
"owner" : "ec2-user",
"group" : "ec2-user"
},
"/home/ec2-user/create-swarm": {
"content": {
"Fn::Join": [ "", ["#!/bin/bash\n",
"/usr/bin/bees up -k `cat /home/ec2-user/bees_keypair.txt` -s ", { "Ref": "BeeCount" },
" -z ", { "Fn::Select" : [ "1", { "Fn::GetAZs" : "" }] },
" -g ", { "Ref" : "BeeSecurityGroup" },
" --instance ", { "Fn::FindInMap": [ "AWSRegionPlatform2AMI", { "Ref": "AWS::Region" }, "bee"]},
" --login ec2-user\n"]]
},
"mode": "000755",
"owner": "ec2-user",
"group": "ec2-user"
},
"/home/ec2-user/start-swarm": {
"content": {
"Fn::Join": [ "", ["#!/bin/bash\n",
"/usr/bin/bees attack --url", { "Ref": "Target2Sting" },
" -n ", { "Ref": "TotalConnections" },
" --concurrent ", { "Ref": "ConcurrentConnections" }]]
},
"mode": "000755",
"owner": "ec2-user",
"group": "ec2-user"
},
"/home/ec2-user/kill-swarm": {
"content": {
"Fn::Join": ["", ["#!/bin/bash\n",
"/usr/bin/bees down\n"]]
},
"mode": "000755",
"owner": "ec2-user",
"group": "ec2-user"
},
"/home/ec2-user/.boto": {
"content": {
"Fn::Join": ["", [ "[Credentials]\n",
"aws_access_key_id = ", { "Ref": "CfnKeys" }, "\n",
"aws_secret_access_key = ", { "Fn::GetAtt": ["CfnKeys", "SecretAccessKey"] }, "\n",
"[Boto]\n",
"ec2_region_name = ", { "Ref" : "AWS::Region" }, "\n",
"ec2_region_endpoint = ec2.", { "Ref" : "AWS::Region" }, ".amazonaws.com\n",
"elb_region_name = ", { "Ref" : "AWS::Region" }, "\n",
"elb_region_endpoint = elasticloadbalancing.", { "Ref" : "AWS::Region" }, ".amazonaws.com\n" ]]
},
"mode": "000600",
"owner": "ec2-user",
"group": "ec2-user"
},
"/home/ec2-user/run-bees": {
"content": {
"Fn::Join": ["", [ "#!/bin/bash\n\n",
"###/home/ec2-user/wait-for-elb\n",
"if [ $? -eq 0 ]\n",
"then\n",
" mkdir /home/ec2-user/swarm-results\n",
" /home/ec2-user/create-keypair > /home/ec2-user/swarm-results/create-keypair.log 2>&1\n",
" bash /home/ec2-user/create-swarm > /home/ec2-user/swarm-results/create-swarm.log 2>&1\n",
" sleep 45 # Allow EC2 instances to fully come up\n",
" bash /home/ec2-user/start-swarm > /home/ec2-user/swarm-results/start-swarm.log 2>&1\n",
" bash /home/ec2-user/kill-swarm > /home/ec2-user/swarm-results/kill-swarm.log 2>&1\n",
" /home/ec2-user/delete-keypair > /home/ec2-user/swarm-results/delete-keypair.log 2>&1\n",
" tar cvf /home/ec2-user/swarm-results.tar.gz /home/ec2-user/swarm-results/*\n",
" chown ec2-user:ec2-user -R /home/ec2-user/swarm-results\n",
" chown ec2-user:ec2-user /home/ec2-user/swarm-results.tar.gz\n",
" aws put ", { "Ref": "ResultBucket" }, "/swarm-results.tar.gz /home/ec2-user/swarm-results.tar.gz\n",
"else\n",
" exit 1\n",
"fi\n"]]
},
"mode": "000755",
"owner": "ec2-user",
"group": "ec2-user"
},
"/home/ec2-user/tools/aws" : {
"source" : "https://raw.github.com/timkay/aws/master/aws",
"mode" : "000755",
"owner": "ec2-user",
"group": "ec2-user"
},
"/home/ec2-user/.awssecret" : {
"content" : { "Fn::Join" : ["", [{ "Ref": "CfnKeys" }, "\n",
{ "Fn::GetAtt": ["CfnKeys", "SecretAccessKey"] }]] },
"mode" : "000600",
"owner": "ec2-user",
"group": "ec2-user"
},
"/root/.awssecret" : {
"content" : { "Fn::Join" : ["", [{ "Ref": "CfnKeys" }, "\n",
{ "Fn::GetAtt": ["CfnKeys", "SecretAccessKey"] }]] },
"mode" : "000600",
"owner": "root",
"group": "root"
}
},
"commands" : {
"00install_aws" : {
"command" : ["perl", "/home/ec2-user/tools/aws", "--install"]
},
"01run_bees" : {
"command" : ["su", "ec2-user", "-c", "./run-bees"],
"cwd" : "/home/ec2-user",
"test" : ["test", "true", "=", { "Ref": "RunTests" }]
}
}
}
}
},
"Properties": {
"SecurityGroups": [ { "Ref": "ControllerSecurityGroup" } ],
"KeyName": { "Ref": "KeyName" },
"ImageId": { "Fn::FindInMap": [ "AWSRegionPlatform2AMI", { "Ref": "AWS::Region" }, "amzn"]},
"InstanceType": { "Ref": "BeesControllerInstanceType" },
"Tags": [ { "Key": "Name", "Value": "bees-controller" } ],
"UserData": {
"Fn::Base64": {
"Fn::Join": [ "", [ "#!/bin/bash\n",
"yum update -y aws-cfn-bootstrap\n",
"/opt/aws/bin/cfn-init -v -s ", { "Ref": "AWS::StackName" },
" -r BeeController --access-key ", { "Ref": "CfnKeys" },
" --secret-key ", { "Fn::GetAtt": ["CfnKeys", "SecretAccessKey"] },
" --region ", { "Ref": "AWS::Region" }, "\n",
"/opt/aws/bin/cfn-signal -e $? '", { "Ref" : "ControllerHandle" }, "'\n"
]
]
}
}
}
},
"ControllerSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Enable SSH access",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"BeeSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Enable SSH access and HTTP access on the inbound port",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"SourceSecurityGroupName" : { "Ref" : "ControllerSecurityGroup" }
}
]
}
},
"ControllerHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle"
},
"ControllerCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "BeeController",
"Properties" : {
"Handle" : { "Ref" : "ControllerHandle" },
"Timeout" : "900"
}
}
},
"Outputs": {
"WebsiteURL": {
"Description": "URL of website under test",
"Value": { "Ref" : "Target2Sting" }
},
"BeeControllerAddress": {
"Description": "Public address of the bees controller",
"Value": { "Fn::GetAtt": [ "BeeController", "PublicDnsName" ] }
},
"TestResultsURL": {
"Value": { "Fn::Join": [ "", ["https://", { "Fn::GetAtt": [ "ResultBucket", "DomainName" ] }, "/swarm-results.tar.gz" ]]},
"Description": "URL of Results file"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment