cloud-maker 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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