cloud-maker 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/cloud-maker CHANGED
@@ -43,7 +43,7 @@ class CloudMakerCLI < Thor
43
43
  puts
44
44
 
45
45
  if yes?("Are you sure you wish to terminate this instance?".red + " (y/n)")
46
- cloud_maker = CloudMaker::Ec2.new(
46
+ cloud_maker = CloudMaker::EC2.new(
47
47
  :aws_access_key_id => options.aws_access_key_id,
48
48
  :aws_secret_access_key => options.aws_secret_access_key
49
49
  )
@@ -64,7 +64,7 @@ class CloudMakerCLI < Thor
64
64
  :default => ENV['AWS_SECRET_ACCESS_KEY'],
65
65
  :required => true
66
66
  def info(aws_instance_id)
67
- cloud_maker = CloudMaker::Ec2.new(
67
+ cloud_maker = CloudMaker::EC2.new(
68
68
  :aws_access_key_id => options.aws_access_key_id,
69
69
  :aws_secret_access_key => options.aws_secret_access_key
70
70
  )
@@ -111,16 +111,17 @@ class CloudMakerCLI < Thor
111
111
  print_config_hash(config.to_hash)
112
112
 
113
113
  if options.yes || yes?("Launch a new EC2 instance with the options above? (y/n)")
114
- cloud_maker = CloudMaker::Ec2.new(
114
+ cloud_maker = CloudMaker::EC2.new(
115
115
  :aws_access_key_id => options.aws_access_key_id,
116
- :aws_secret_access_key => options.aws_secret_access_key
116
+ :aws_secret_access_key => options.aws_secret_access_key,
117
+ :region => config['region']
117
118
  )
118
119
 
119
120
  instance = cloud_maker.launch(config)
120
121
  puts
121
- say "Successfully launched new EC2 instance: ".green + instance[:aws_instance_id].magenta
122
+ say "Successfully launched new EC2 instance: ".green + instance.id.magenta
122
123
  puts
123
- print_colored_hash(instance)
124
+ print_colored_hash(CloudMaker::EC2.instance_to_hash(instance))
124
125
  else
125
126
  say "Launch aborted!".red
126
127
  end
data/lib/cloud-maker.rb CHANGED
@@ -2,7 +2,7 @@ require 'yaml'
2
2
  require 'thor'
3
3
  require 'colorize'
4
4
  require 'deep_merge'
5
- require 'right_aws'
5
+ require 'aws-sdk'
6
6
 
7
7
  require 'cloud_maker/config'
8
8
  require 'cloud_maker/ec2'
@@ -70,7 +70,7 @@ module CloudMaker
70
70
  # extra_options - Options that describe the config as opposed to being part
71
71
  # of the config.
72
72
  # 'config_path' - The path the config was loaded from. Used for archival purposes.
73
- # 'import_ec2' - CloudMaker::Ec2 defines properties it relies on, if this value
73
+ # 'import_ec2' - CloudMaker::EC2 defines properties it relies on, if this value
74
74
  # is true then we pull those property definitions in.
75
75
  #
76
76
  # Returns a CloudMaker object
@@ -83,7 +83,7 @@ module CloudMaker
83
83
  self.imports = extract_imports!(cloud_config)
84
84
  self.cloud_config = cloud_config
85
85
 
86
- self.import(self.class.new(Ec2::CLOUD_MAKER_CONFIG)) if (extra_options['import_ec2'])
86
+ self.import(self.class.new(EC2::CLOUD_MAKER_CONFIG)) if (extra_options['import_ec2'])
87
87
  self.imports.reverse.each do |import_path|
88
88
  self.import(self.class.from_yaml(import_path))
89
89
  end
@@ -1,15 +1,15 @@
1
1
  require 'right_aws'
2
2
 
3
3
  module CloudMaker
4
- class Ec2
4
+ class EC2
5
5
  # Public: Gets/Sets the AWS access key.
6
6
  attr_accessor :aws_secret_access_key
7
7
  # Public: Gets/Sets the AWS secret.
8
8
  attr_accessor :aws_access_key_id
9
- # Internal: Gets/Sets the RightAws::Ec2 instance.
9
+ # Internal: Gets/Sets the AWS::EC2 instance.
10
10
  attr_accessor :ec2
11
11
 
12
- # Public: A CloudMaker::Config hash that describes the config properties Ec2 relies on.
12
+ # Public: A CloudMaker::Config hash that describes the config properties EC2 relies on.
13
13
  CLOUD_MAKER_CONFIG = {
14
14
  'cloud-maker' => {
15
15
  'ami' => {
@@ -42,7 +42,7 @@ module CloudMaker
42
42
  # Public: The name of the tag that will be used to find the name of an s3 bucket for archiving/information retrieval
43
43
  BUCKET_TAG = 's3_archive_bucket'
44
44
 
45
- # Public: Creates a new Ec2 instance
45
+ # Public: Creates a new EC2 instance
46
46
  #
47
47
  # cloud_maker_config - A CloudMaker::Config object describing the instance
48
48
  # to be managed.
@@ -50,7 +50,7 @@ module CloudMaker
50
50
  # :aws_access_key_id - (required) The AWS access key
51
51
  # :aws_secret_access_key - (required) The AWS secret
52
52
  #
53
- # Returns a new CloudMaker::Ec2 instance
53
+ # Returns a new CloudMaker::EC2 instance
54
54
  # Raises RuntimeError if any of the required options are not specified
55
55
  def initialize(options)
56
56
  required_keys = [:aws_access_key_id, :aws_secret_access_key]
@@ -61,80 +61,123 @@ module CloudMaker
61
61
  self.aws_access_key_id = options[:aws_access_key_id]
62
62
  self.aws_secret_access_key = options[:aws_secret_access_key]
63
63
 
64
- self.ec2 = RightAws::Ec2.new(self.aws_access_key_id, self.aws_secret_access_key)
64
+ self.ec2 = AWS::EC2.new(:access_key_id => self.aws_access_key_id, :secret_access_key => self.aws_secret_access_key)
65
65
  end
66
66
 
67
67
  # Public: Fetch archived information about an instance
68
68
  #
69
69
  # Returns a hash of information about the instance as it was launched
70
70
  def info(instance_id)
71
- bucket = self.ec2.describe_tags(:filters => {'resource-id' => instance_id, 'key' => BUCKET_TAG}).first[:value]
71
+ instance = find_instance(instance_id)
72
+ bucket = instance.tags[BUCKET_TAG]
73
+
72
74
  archiver = S3Archiver.new(
73
75
  :instance_id => instance_id,
74
76
  :aws_access_key_id => self.aws_access_key_id,
75
77
  :aws_secret_access_key => self.aws_secret_access_key,
76
78
  :bucket_name => bucket
77
79
  )
80
+
78
81
  archiver.load_archive
79
82
  end
80
83
 
81
84
  # Public: Terminates the specified EC2 instance.
82
85
  #
83
- # Returns a RightAws supplied Hash describing the terminated instance.
86
+ # Returns nothing.
84
87
  def terminate(instance_id)
85
- self.ec2.terminate_instances([instance_id])
88
+ find_instance(instance_id).terminate
86
89
  end
87
90
 
88
91
  # Public: Launches a new EC2 instance, associates any specified elastic IPS
89
92
  # with it, adds any specified tags, and archives the launch details to S3.
90
93
  #
91
- # Returns a RightAws supplied Hash describing the launched instance.
94
+ # Returns an AWS::EC2 object for the launched instance.
92
95
  def launch(cloud_maker_config)
93
96
  user_data = cloud_maker_config.to_user_data
94
97
 
95
- instance = ec2.launch_instances(cloud_maker_config['ami'],
96
- :group_names => cloud_maker_config['security_group'],
98
+ if !cloud_maker_config['availability_zone'].nil? && !cloud_maker_config['availability_zone'].empty?
99
+ region = find_region(cloud_maker_config['availability_zone'])
100
+ else
101
+ region = ec2 # .instances.create will just put things in the default region
102
+ end
103
+
104
+ instance = region.instances.create(
105
+ :image_id => cloud_maker_config['ami'],
106
+ :security_groups => cloud_maker_config['security_group'],
97
107
  :instance_type => cloud_maker_config['instance_type'],
98
108
  :key_name => cloud_maker_config['key_pair'],
99
109
  :availability_zone => cloud_maker_config['availability_zone'],
100
110
  :user_data => user_data
101
- ).first
102
-
103
- instance_id = instance[:aws_instance_id]
104
-
105
- ec2.create_tags(instance_id, cloud_maker_config["tags"]) if cloud_maker_config["tags"]
106
-
107
- if (cloud_maker_config["elastic_ip"])
108
- #we can't associate IPs while the state is pending
109
- while instance[:aws_state] == 'pending'
110
- #this is going to hammer EC2 a bit, it might be necessary to add some delay in here
111
- instance = ec2.describe_instances([instance_id]).first
112
- end
113
-
114
- ec2.associate_address(instance_id, :public_ip => cloud_maker_config["elastic_ip"])
115
- end
111
+ )
116
112
 
117
- begin
118
- instance = ec2.describe_instances([instance_id]).first # So we get updated tag/ip info
119
- rescue RightAws::AwsError => e
120
- tries ||= 0
121
- tries += 1
122
- if tries <= 5
123
- sleep 2**tries
124
- else
125
- raise e
126
- end
127
- end
113
+ instance.tags.set(cloud_maker_config["tags"]) if cloud_maker_config["tags"]
114
+ instance.associate_elastic_ip(cloud_maker_config["elastic_ip"]) if cloud_maker_config["elastic_ip"]
128
115
 
129
116
  archiver = S3Archiver.new(
130
- :instance_id => instance_id,
117
+ :instance_id => instance.id,
131
118
  :aws_access_key_id => self.aws_access_key_id,
132
119
  :aws_secret_access_key => self.aws_secret_access_key,
133
120
  :bucket_name => cloud_maker_config["tags"][BUCKET_TAG]
134
121
  )
135
- archiver.store_archive(cloud_maker_config, instance)
122
+ archiver.store_archive(cloud_maker_config, self.class.instance_to_hash(instance))
136
123
 
137
124
  instance
138
125
  end
126
+
127
+ # Internal: Find the instance object for an instance ID regardless of what
128
+ # region the instance is in. It looks in the default region (us-east-1) first
129
+ # and then looks in all regions if it's not there.
130
+ #
131
+ # Returns nil or an AWS::EC2::Instance
132
+ def find_instance(instance_id)
133
+ # Check the default region first
134
+ return ec2.instances[instance_id] if ec2.instances[instance_id].exists?
135
+
136
+ # If we don't find it there look in every region
137
+ instance = nil
138
+ ec2.regions.each do |region|
139
+ if region.instances[instance_id].exists?
140
+ instance = region.instances[instance_id]
141
+ break
142
+ end
143
+ end
144
+
145
+ instance
146
+ end
147
+
148
+
149
+ # Internal: Find the region object for a given availability zone. Currently works
150
+ # based on amazon naming conventions and will break if they change.
151
+ #
152
+ # Returns an AWS::EC2::Region
153
+ # Raises a RuntimeError if the region doesn't exist
154
+ def find_region(availability_zone)
155
+ region_name = availability_zone.gsub(/(\d)\w$/, '\1')
156
+ if ec2.regions[region_name].exists?
157
+ ec2.regions[region_name]
158
+ else
159
+ raise RuntimeError.new("The region #{region_name} doesn't exist - region name generated from availability_zone: #{availability_zone}.")
160
+ end
161
+ end
162
+
163
+ class << self
164
+ # Public: Generates a hash of properties from an AWS::EC2 instance
165
+ #
166
+ # Returns a hash of properties for the instance.
167
+ def instance_to_hash(instance)
168
+ {
169
+ :instance_id => instance.id,
170
+ :ami => instance.image_id,
171
+ :api_termination_disabled => instance.api_termination_disabled?,
172
+ :dns_name => instance.dns_name,
173
+ :ip_address => instance.ip_address,
174
+ :private_ip_address => instance.private_ip_address,
175
+ :key_name => instance.key_name,
176
+ :owner_id => instance.owner_id,
177
+ :status => instance.status
178
+ }
179
+ end
180
+ end
181
+
139
182
  end
140
183
  end
@@ -7,7 +7,7 @@ module CloudMaker
7
7
  attr_accessor :aws_access_key_id
8
8
  # Public: Gets/Sets the EC2 instance ID string.
9
9
  attr_accessor :instance_id
10
- # Internal: Gets/Sets the RightAws::S3::Bucket used for storing/loading archives.
10
+ # Internal: Gets/Sets the bucket object used for storing/loading archives.
11
11
  attr_accessor :bucket
12
12
 
13
13
  # Public: All archive keys will be prefixed with KEY_PREFIX/
@@ -37,22 +37,26 @@ module CloudMaker
37
37
  self.aws_access_key_id = options[:aws_access_key_id]
38
38
  self.aws_secret_access_key = options[:aws_secret_access_key]
39
39
 
40
- s3 = RightAws::S3.new(self.aws_access_key_id, self.aws_secret_access_key)
41
- self.bucket = s3.bucket(options[:bucket_name])
40
+ self.bucket = AWS::S3.new(
41
+ :access_key_id => self.aws_access_key_id,
42
+ :secret_access_key => self.aws_secret_access_key
43
+ ).buckets[options[:bucket_name]]
44
+
45
+ raise RuntimeError.new("The S3 bucket #{options[:bucket_name]} does not exist.") unless self.bucket.exists?
42
46
  end
43
47
 
44
48
  # Public: Generates an archive with all information relevant to an instance
45
49
  # launch and stores it to S3.
46
50
  #
47
51
  # cloud_maker_config - The CloudMaker::Config the instance was launched with
48
- # instance - A Hash describing the properties of the launched instance
52
+ # properties - A Hash describing the properties of the launched instance
49
53
  #
50
54
  # Returns nothing.
51
- def store_archive(cloud_maker_config, instance)
55
+ def store_archive(cloud_maker_config, properties)
52
56
  userdata = cloud_maker_config.to_user_data
53
- self.bucket.put(self.user_data_key, userdata)
54
- self.bucket.put(self.instance_yaml_key, instance.to_yaml)
55
- self.bucket.put(self.cloud_config_yaml_key, cloud_maker_config.to_hash.to_yaml)
57
+ self.bucket.objects.create(self.user_data_key, :data => userdata)
58
+ self.bucket.objects.create(self.instance_yaml_key, :data => properties.to_yaml)
59
+ self.bucket.objects.create(self.cloud_config_yaml_key, :data => cloud_maker_config.to_hash.to_yaml)
56
60
  true
57
61
  end
58
62
 
@@ -61,9 +65,9 @@ module CloudMaker
61
65
  # Returns the content of the archive.
62
66
  def load_archive
63
67
  {
64
- :user_data => self.bucket.get(self.user_data_key),
65
- :cloud_config => YAML::load(self.bucket.get(self.cloud_config_yaml_key)),
66
- :instance => YAML::load(self.bucket.get(self.instance_yaml_key))
68
+ :user_data => self.bucket.objects[self.user_data_key].read,
69
+ :cloud_config => YAML::load(self.bucket.objects[self.cloud_config_yaml_key].read),
70
+ :instance => YAML::load(self.bucket.objects[self.instance_yaml_key].read)
67
71
  }
68
72
  end
69
73
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloud-maker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-08-09 00:00:00.000000000 Z
13
+ date: 2012-08-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: colorize
@@ -45,13 +45,13 @@ dependencies:
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0.15'
47
47
  - !ruby/object:Gem::Dependency
48
- name: right_aws
48
+ name: aws-sdk
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: '1.6'
55
55
  type: :runtime
56
56
  prerelease: false
57
57
  version_requirements: !ruby/object:Gem::Requirement
@@ -59,7 +59,7 @@ dependencies:
59
59
  requirements:
60
60
  - - ~>
61
61
  - !ruby/object:Gem::Version
62
- version: '3.0'
62
+ version: '1.6'
63
63
  - !ruby/object:Gem::Dependency
64
64
  name: deep_merge
65
65
  requirement: !ruby/object:Gem::Requirement