Class: CloudMaker::EC2
- Inherits:
-
Object
- Object
- CloudMaker::EC2
- Defined in:
- lib/cloud_maker/ec2.rb
Constant Summary collapse
- CLOUD_MAKER_CONFIG =
Public: A CloudMaker::Config hash that describes the config properties EC2 relies on.
{ 'cloud-maker' => { 'ami' => { 'required' => true, 'description' => "The Amazon AMI ID for the instance." }, 'instance_type' => { 'required' => true, 'description' => "The Amazon instance type, eg. m1.small." }, 'availability_zone' => { 'required' => true, 'description' => "The Amazon availability zone, eg. us-east-1a" }, 'key_pair' => { 'default' => "", 'description' => "The name of an Amazon key pair, so you can actually login to the instance." }, 'elastic_ip' => { 'default' => '', 'description' => "An elastic IP address you control that you would like to associate to the instance." }, 'security_group' => { 'default' => 'default', 'required' => true, 'description' => 'The Amazon EC2 security group to launch the instance with.' }, 'iam_role' => { 'default' => '', 'description' => 'The IAM instance profile name or ARN you would like to use.' }, 'cname' => { 'default' => '', 'description' => "A dns entry you would like to CNAME to this instance." }, 'block_device_mappings' => { 'description' => "A hash of block devices mappings. ie. { /dev/sda1 => { volume_size => <value_in_GB>, snapshot_id => <id>, delete_on_termination => <boolean> } }" }, 'elb' => { 'default' => '', 'description' => "The load balancer to use." } } }
- BUCKET_TAG =
Public: The name of the tag that will be used to find the name of an s3 bucket for archiving/information retrieval
's3_archive_bucket'
Instance Attribute Summary collapse
-
#aws_access_key_id ⇒ Object
Public: Gets/Sets the AWS secret.
-
#aws_secret_access_key ⇒ Object
Public: Gets/Sets the AWS access key.
-
#ec2 ⇒ Object
Internal: Gets/Sets the AWS::EC2 instance.
Class Method Summary collapse
-
.instance_to_hash(instance) ⇒ Object
Public: Generates a hash of properties from an AWS::EC2 instance.
Instance Method Summary collapse
-
#find_instance(instance_id) ⇒ Object
Internal: Find the instance object for an instance ID regardless of what region the instance is in.
-
#find_region(availability_zone) ⇒ Object
Internal: Find the region object for a given availability zone.
-
#info(instance_id) ⇒ Object
Public: Fetch archived information about an instance.
-
#initialize(options) ⇒ EC2
constructor
Public: Creates a new EC2 instance.
-
#launch(cloud_maker_config) ⇒ Object
Public: Launches a new EC2 instance, associates any specified elastic IPS with it, adds any specified tags, and archives the launch details to S3.
-
#terminate(instance_id) ⇒ Object
Public: Terminates the specified EC2 instance.
Constructor Details
#initialize(options) ⇒ EC2
Public: Creates a new EC2 instance
cloud_maker_config - A CloudMaker::Config object describing the instance
to be managed.
options - S3 configuration options
:aws_access_key_id - (required) The AWS access key
:aws_secret_access_key - (required) The AWS secret
Returns a new CloudMaker::EC2 instance Raises RuntimeError if any of the required options are not specified
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/cloud_maker/ec2.rb', line 69 def initialize() required_keys = [:aws_access_key_id, :aws_secret_access_key] unless (required_keys - .keys).empty? raise RuntimeError.new("Instantiated #{self.class} without required attributes: #{required_keys - .keys}.") end self.aws_access_key_id = [:aws_access_key_id] self.aws_secret_access_key = [:aws_secret_access_key] self.ec2 = AWS::EC2.new(:access_key_id => self.aws_access_key_id, :secret_access_key => self.aws_secret_access_key) end |
Instance Attribute Details
#aws_access_key_id ⇒ Object
Public: Gets/Sets the AWS secret.
6 7 8 |
# File 'lib/cloud_maker/ec2.rb', line 6 def aws_access_key_id @aws_access_key_id end |
#aws_secret_access_key ⇒ Object
Public: Gets/Sets the AWS access key.
4 5 6 |
# File 'lib/cloud_maker/ec2.rb', line 4 def aws_secret_access_key @aws_secret_access_key end |
#ec2 ⇒ Object
Internal: Gets/Sets the AWS::EC2 instance.
8 9 10 |
# File 'lib/cloud_maker/ec2.rb', line 8 def ec2 @ec2 end |
Class Method Details
.instance_to_hash(instance) ⇒ Object
Public: Generates a hash of properties from an AWS::EC2 instance
Returns a hash of properties for the instance.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/cloud_maker/ec2.rb', line 242 def instance_to_hash(instance) { :instance_id => instance.id, :ami => instance.image_id, :api_termination_disabled => instance.api_termination_disabled?, :dns_name => instance.dns_name, :ip_address => instance.ip_address, :private_ip_address => instance.private_ip_address, :key_name => instance.key_name, :owner_id => instance.owner_id, :status => instance.status, :tags => instance..inject({}) {|hash, tag| hash[tag.first] = tag.last;hash} } end |
Instance Method Details
#find_instance(instance_id) ⇒ Object
Internal: Find the instance object for an instance ID regardless of what region the instance is in. It looks in the default region (us-east-1) first and then looks in all regions if it’s not there.
Returns nil or an AWS::EC2::Instance
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/cloud_maker/ec2.rb', line 207 def find_instance(instance_id) # Check the default region first return ec2.instances[instance_id] if ec2.instances[instance_id].exists? # If we don't find it there look in every region instance = nil ec2.regions.each do |region| if region.instances[instance_id].exists? instance = region.instances[instance_id] break end end instance end |
#find_region(availability_zone) ⇒ Object
Internal: Find the region object for a given availability zone. Currently works based on amazon naming conventions and will break if they change.
Returns an AWS::EC2::Region Raises a RuntimeError if the region doesn’t exist
229 230 231 232 233 234 235 236 |
# File 'lib/cloud_maker/ec2.rb', line 229 def find_region(availability_zone) region_name = availability_zone.gsub(/(\d)\w$/, '\1') if ec2.regions[region_name].exists? ec2.regions[region_name] else raise RuntimeError.new("The region #{region_name} doesn't exist - region name generated from availability_zone: #{availability_zone}.") end end |
#info(instance_id) ⇒ Object
Public: Fetch archived information about an instance
Returns a hash of information about the instance as it was launched
84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/cloud_maker/ec2.rb', line 84 def info(instance_id) instance = find_instance(instance_id) bucket = instance.[BUCKET_TAG] archiver = S3Archiver.new( :instance_id => instance_id, :aws_access_key_id => self.aws_access_key_id, :aws_secret_access_key => self.aws_secret_access_key, :bucket_name => bucket ) archiver.load_archive end |
#launch(cloud_maker_config) ⇒ Object
Public: Launches a new EC2 instance, associates any specified elastic IPS with it, adds any specified tags, and archives the launch details to S3.
Returns an AWS::EC2 object for the launched instance.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/cloud_maker/ec2.rb', line 109 def launch(cloud_maker_config) user_data = cloud_maker_config.to_user_data if !cloud_maker_config['availability_zone'].nil? && !cloud_maker_config['availability_zone'].empty? region = find_region(cloud_maker_config['availability_zone']) else region = ec2 # .instances.create will just put things in the default region end config = { :image_id => cloud_maker_config['ami'], :iam_instance_profile => cloud_maker_config['iam_role'], :security_groups => cloud_maker_config['security_group'], :instance_type => cloud_maker_config['instance_type'], :key_name => cloud_maker_config['key_pair'], :availability_zone => cloud_maker_config['availability_zone'], :user_data => user_data } config[:block_device_mappings] = cloud_maker_config['block_device_mappings'] if cloud_maker_config['block_device_mappings'] instance = region.instances.create(config) begin if cloud_maker_config['tags'] # we can only set tags to be strings so make sure we convert all of our tags # to strings = cloud_maker_config['tags'].inject({}) do |hash, pair| hash[pair[0]] = pair[1].to_s hash end instance..set() end rescue AWS::EC2::Errors::InvalidInstanceID::NotFound => e retries ||= 0 if retries < 5 sleep(2**retries) retries += 1 retry end end if cloud_maker_config.elastic_ip? || cloud_maker_config.cname? while instance.status == :pending #wait end instance.associate_elastic_ip(cloud_maker_config["elastic_ip"]) if cloud_maker_config.elastic_ip? if cloud_maker_config.cname? r53 = AWS::Route53::Client.new(:access_key_id => self.aws_access_key_id, :secret_access_key => self.aws_secret_access_key) zone = r53.list_hosted_zones[:hosted_zones].select {|zone| cloud_maker_config['cname'] + '.' =~ /#{Regexp.escape(zone[:name])}$/ }.first r53.change_resource_record_sets( :hosted_zone_id => zone[:id], :change_batch => { :comment => "CloudMaker initialization of #{instance.instance_id}.", :changes => [{ :action => "CREATE", :resource_record_set => { :name => cloud_maker_config['cname'], :type => 'CNAME', :ttl => 60, :resource_records => [{:value => instance.dns_name}] } }] } ) end end if cloud_maker_config.elb? while instance.status == :pending #wait end elb_interface = ElbInterface.new( :instance => instance, :aws_access_key_id => self.aws_access_key_id, :aws_secret_access_key => self.aws_secret_access_key, :elb_name => cloud_maker_config["elb"] ).attach end archiver = S3Archiver.new( :instance_id => instance.id, :aws_access_key_id => self.aws_access_key_id, :aws_secret_access_key => self.aws_secret_access_key, :bucket_name => cloud_maker_config["tags"][BUCKET_TAG] ) archiver.store_archive(cloud_maker_config, self.class.instance_to_hash(instance)) instance end |
#terminate(instance_id) ⇒ Object
Public: Terminates the specified EC2 instance.
Returns nothing.
101 102 103 |
# File 'lib/cloud_maker/ec2.rb', line 101 def terminate(instance_id) find_instance(instance_id).terminate end |