Skip to content

Commit

Permalink
First version
Browse files Browse the repository at this point in the history
  • Loading branch information
shaicoleman committed May 8, 2015
1 parent 93ab21f commit 6bf1804
Show file tree
Hide file tree
Showing 23 changed files with 1,657 additions and 35 deletions.
34 changes: 1 addition & 33 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,35 +1,3 @@
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/test/tmp/
/test/version_tmp/
/tmp/

## Specific to RubyMotion:
.dat*
.repl_history
build/

## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/

## Environment normalisation:
/.bundle/
/vendor/bundle
/lib/bundler/man/

# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
Gemfile.lock
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'
gem 'aws-sdk', '~> 2.0.42'
gem 'awesome_print', '~> 1.6.1'
gem 'cfndsl', '~> 0.1.14'
gem 'parallel', '~> 1.4.1'
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
# aws-sdk-ruby-examples
Examples for AWS SDK for Ruby v2
# aws-ruby-examples
Unofficial code samples for AWS SDK for Ruby v2

These examples demonstrate the flow of the APIs for the different AWS services, and are not meant for production use.

sudo pip install --upgrade awscli # Install AWS CLI via Python PIP
aws configure # Configure credentials and region
aws ec2 describe-key-pairs --output text # Test configuration

bundle install

You'll need to edit the config.rb file

To load a file into IRB:

irb -r ./<file>.rb

Work in progress
89 changes: 89 additions & 0 deletions autoscaling.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require './config'

def ec2
@ec2 ||= Aws::EC2::Client.new(region: @region)
end

def autoscaling
@autoscaling = Aws::AutoScaling::Client.new(region: @region)
end

def get_vpc_public_subnets_ids
resp = ec2.describe_subnets
public_subnets = resp[:subnets].find_all { |s| s[:default_for_az] && s[:map_public_ip_on_launch] }
public_subnet_ids = public_subnets.map { |s| s[:subnet_id] }
end

def create_security_group
group_name = 'autoscaling-sg'
description = 'Ports 22/80/443/ICMP'
ip_permissions = [
{ ip_protocol: 'tcp', from_port: 22, to_port: 22, ip_ranges: [cidr_ip: '0.0.0.0/0'] },
{ ip_protocol: 'tcp', from_port: 80, to_port: 80, ip_ranges: [cidr_ip: '0.0.0.0/0'] },
{ ip_protocol: 'tcp', from_port: 443, to_port: 443, ip_ranges: [cidr_ip: '0.0.0.0/0'] },
{ ip_protocol: 'icmp', from_port: -1, to_port: -1, ip_ranges: [cidr_ip: '0.0.0.0/0'] } ]
resp = ec2.create_security_group \
group_name: group_name, description: description
@group_id = resp[:group_id]
resp = ec2.authorize_security_group_ingress \
group_name: group_name, ip_permissions: ip_permissions
resp
end

def create_launch_configuration
raise '@launch_configuration_name missing' unless @launch_configuration_name
raise '@group_id' unless @group_id
image_id = get_ubuntu_image_id
security_groups = [@group_id]
instance_type = 't2.micro'
user_data = <<-SH.gsub(/^ +/, '')
#!/bin/bash
apt-get update >> /var/log/cloud-init-output.log &&
apt-get -yy install php5 apache2 >> /var/log/cloud-init-output.log &&
echo -e "<h1>PHP, the time is now <?= date('Y-m-d H:i:s'); ?>, Host is <?= gethostname(); ?></h1>" > /var/www/html/index.php &&
rm -f /var/www/html/index.html &&
service apache2 start
SH
block_device_mappings =
[{ device_name: '/dev/sda1', ebs: { volume_size: 8, volume_type: 'gp2'} }]

resp = autoscaling.create_launch_configuration \
launch_configuration_name: @launch_configuration_name, image_id: image_id,
key_name: @key_name, security_groups: security_groups,
user_data: Base64.encode64(user_data), instance_type: instance_type,
block_device_mappings: block_device_mappings
end

def create_autoscaling_group
raise '@launch_configuration_name missing' unless @launch_configuration_name
min_size = 1
max_size = 1
desired_capacity = 1
vpc_zone_identifier = get_vpc_public_subnets_ids.join(',')
resp = autoscaling.create_auto_scaling_group \
auto_scaling_group_name: @auto_scaling_group_name,
launch_configuration_name: @launch_configuration_name,
min_size: min_size, max_size: max_size, desired_capacity: desired_capacity,
vpc_zone_identifier: vpc_zone_identifier
end

def run
puts "Region: #{@region}"
puts 'Creating security group...'; ap resp = create_security_group
puts 'Creating launch configuration...'; ap resp = create_launch_configuration
puts 'Creating autoscaling group...'; ap resp = create_autoscaling_group
end

def cleanup
raise '@launch_configuration_name missing' unless @launch_configuration_name
raise '@auto_scaling_group_name' unless @auto_scaling_group_name
resp = autoscaling.update_auto_scaling_group \
auto_scaling_group_name: @auto_scaling_group_name,
min_size: 0, max_size: 0, desired_capacity: 0
resp = autoscaling.delete_auto_scaling_group \
auto_scaling_group_name: @auto_scaling_group_name
resp = autoscaling.delete_launch_configuration \
launch_configuration_name: @launch_configuration_name
resp = ec2.delete_security_group group_name: 'autoscaling-sg'
true
end
58 changes: 58 additions & 0 deletions cloudformation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
require './config'

def cloudformation
@cloudformation ||= Aws::CloudFormation::Client.new(region: @region)
end

def create_stack
raise '@stack_name missing' unless @stack_name
template_url = 'https://s3.amazonaws.com/cloudformation-templates-us-east-1/WordPress_Single_Instance.template'
@db_name = 'wordpressdb'
@db_user = 'wordpressdb'
@db_password = random_token
@db_root_password = random_token
parameters = [
{ parameter_key: 'DBName', parameter_value: @db_name },
{ parameter_key: 'DBPassword', parameter_value: @db_password },
{ parameter_key: 'DBRootPassword', parameter_value: @db_root_password },
{ parameter_key: 'DBUser', parameter_value: @db_user },
{ parameter_key: 'InstanceType', parameter_value: 't2.micro' },
{ parameter_key: 'KeyName', parameter_value: @key_name },
{ parameter_key: 'SSHLocation', parameter_value: '0.0.0.0/0' } ]
on_failure = 'DO_NOTHING'
resp = cloudformation.create_stack \
stack_name: @stack_name, template_url: template_url,
parameters: parameters, on_failure: on_failure
end

def create_stack_waiter
resp = cloudformation.wait_until :stack_create_complete, stack_name: @stack_name
@website_url = resp[:stacks][0][:outputs].find { |o| o[:output_key] == 'WebsiteURL' }[:output_value]
resp
end

def delete_stack
resp = cloudformation.delete_stack stack_name: @stack_name
end

def delete_stack_waiter
resp = cloudformation.wait_until :stack_delete_complete, stack_name: @stack_name
end

def cleanup
puts 'Deleting stack...'; ap resp = delete_stack
puts 'Waiting for deletion...'; ap resp = delete_stack_waiter
true
end

def run
puts "Region: #{@region}"
puts 'Creating stack...'; ap resp = create_stack
puts 'Waiting for creation...'; ap resp = create_stack_waiter
puts "DB Name: #{@db_name}"
puts "DB User: #{@db_user}"
puts "DB Password: #{@db_password}"
puts "DB Root Password: #{@db_root_password}"
puts "WordPress will be available on #{@website_url}"
true
end
152 changes: 152 additions & 0 deletions cloudformation_template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Based on https://github.com/stevenjack/cfndsl/blob/master/sample/autoscale2.rb

# cfndsl cloudformation_template.rb | jq .

CloudFormation {
require './helpers'

AWSTemplateFormatVersion "2010-09-09"

Description <<-DESC.gsub(/^ +/, '')
Create a multi-az, load balanced, Auto Scaled sample web site. The
Auto Scaling trigger is based on the CPU utilization of the web
servers. The AMI is chosen based on the region in which the stack is
run. This example creates a web service running across all
availability zones in a region. The instances are load balanced with a
simple health check. The web site is available on port 80, however,
the instances can be configured to listen on any port (8888 by
default).
DESC

Parameter("InstanceType") {
Description "Type of EC2 instance to launch"
Type "String"
Default "t2.micro"
AllowedValues INSTANCE_TYPES
}

Parameter( "WebServerPort") {
Description "The TCP port for the Web Server"
Type "String"
Default "8888"
}
Parameter("KeyName") {
Description "The EC2 Key Pair to allow SSH access to the instances"
Type "String"
}

Mapping("AWSRegionArch2AMI", cfn_ubuntu_region_arch_to_ami)

Mapping("AWSInstanceType2Arch", cfn_instance_type_to_arch)

# Resources work similar to Parameters
AutoScalingGroup("WebServerGroup") {
UpdatePolicy("AutoScalingRollingUpdate", {
"MinInstancesInService" => "1",
"MaxBatchSize" => "1",
"PauseTime" => "PT15M"
})
AvailabilityZones FnGetAZs("")
LaunchConfigurationName Ref("LaunchConfig")
MinSize 1
MaxSize 3
LoadBalancerNames Ref( "ElasticLoadBalancer" )
}

LaunchConfiguration("LaunchConfig") {
KeyName Ref("KeyName")
ImageId FnFindInMap( "AWSRegionArch2AMI",
Ref("AWS::Region"),
FnFindInMap( "AWSInstanceType2Arch", Ref("InstanceType"), "Arch") )

UserData FnBase64( Ref("WebServerPort"))
SecurityGroup Ref("InstanceSecurityGroup")
InstanceType Ref("InstanceType")
}

Resource( "WebServerScaleUpPolicy" ) {
Type "AWS::AutoScaling::ScalingPolicy"
Property("AdjustmentType", "ChangeInCapacity")
Property("AutoScalingGroupName", Ref( "WebServerGroup") )
Property("Cooldown", "60")
Property("ScalingAdjustment", "1")
}

Resource("WebServerScaleDownPolicy") {
Type "AWS::AutoScaling::ScalingPolicy"
Property("AdjustmentType", "ChangeInCapacity")
Property("AutoScalingGroupName", Ref( "WebServerGroup" ))
Property("Cooldown", "60")
Property("ScalingAdjustment", "-1")
}

alarms = []
alarms.push Resource("CPUAlarmHigh") {
Type "AWS::CloudWatch::Alarm"
Property("AlarmDescription", "Scale-up if CPU > 90% for 10 minutes")
Property("Threshold", "90")
Property("AlarmActions", [ Ref("WebServerScaleUpPolicy" ) ])
Property("ComparisonOperator", "GreaterThanThreshold")
}

alarms.push Resource("CPUAlarmLow") {
Type "AWS::CloudWatch::Alarm"
Property("AlarmDescription", "Scale-down if CPU < 70% for 10 minutes")
Property("Threshold", "70")
Property("AlarmActions", [ Ref("WebServerScaleDownPolicy" ) ])
Property("ComparisonOperator", "LessThanThreshold")
}

alarms.each do |alarm|
alarm.declare {
Property("MetricName", "CPUUtilization")
Property("Namespace", "AWS/EC2")
Property("Statistic", "Average")
Property("Period", "300")
Property("EvaluationPeriods", "2")
Property("Dimensions", [ { "Name" => "AutoScalingGroupName",
"Value" => Ref("WebServerGroup" ) } ] )
}
end

Resource( "ElasticLoadBalancer" ) {
Type "AWS::ElasticLoadBalancing::LoadBalancer"
Property( "AvailabilityZones", FnGetAZs(""))
Property( "Listeners" , [ { "LoadBalancerPort" => "80",
"InstancePort" => Ref( "WebServerPort" ),
"Protocol" => "HTTP" } ] )
Property( "HealthCheck" , {
# FnFormat replaces %0, %1, etc with passed in parameters
# Note that it renders to a call to Fn::Join in the json.
"Target" => FnFormat("HTTP:%0/", Ref( "WebServerPort" ) ),
"HealthyThreshold" => "3",
"UnhealthyThreshold" => "5",
"Interval" => "30",
"Timeout" => "5"
})
}

Resource("InstanceSecurityGroup" ) {
Type "AWS::EC2::SecurityGroup"
Property("GroupDescription" , "Enable SSH access and HTTP access on the inbound port")
Property("SecurityGroupIngress", [ {
"IpProtocol" => "tcp",
"FromPort" => "22",
"ToPort" => "22",
"CidrIp" => "0.0.0.0/0"
},
{
"IpProtocol" => "tcp",
"FromPort" => Ref( "WebServerPort" ),
"ToPort" => Ref( "WebServerPort" ),
"SourceSecurityGroupOwnerId" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"),
"SourceSecurityGroupName" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.GroupName")
} ])
}

Output( "URL" ) {
Description "The URL of the website"
Value FnJoin( "", [ "http://", FnGetAtt( "ElasticLoadBalancer", "DNSName" ) ] )
}

}
Loading

0 comments on commit 6bf1804

Please sign in to comment.