engineyard-cloud-client 1.0.12 → 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  *
6
6
 
7
+ ## v1.0.13 (2013-08-13)
8
+
9
+ *
10
+
7
11
  ## v1.0.12 (2013-05-31)
8
12
 
9
13
  * Fix for ruby 2.0.0
data/README.md CHANGED
@@ -30,7 +30,7 @@ Setup:
30
30
  require 'engineyard-cloud-client'
31
31
  require 'engineyard-cloud-client/test'
32
32
 
33
- token = EY::CloudClient.authenticate("your@email.com", "password")
33
+ token = EY::CloudClient.new.authenticate("your@email.com", "password")
34
34
  ui = EY::CloudClient::Test::VerboseUI.new
35
35
  # Test::VerboseUI is used in this example for simplicity.
36
36
  # You may substitute your own ui object with #debug and #info methods
@@ -64,5 +64,17 @@ module EY
64
64
  EY::CloudClient::User.from_hash(self, get('/current_user')['user'])
65
65
  end
66
66
 
67
+ # Accepts an environment name and optional account name and returns the
68
+ # best matching environment for the given constraints.
69
+ #
70
+ # This is a shortcut for Environment.resolve
71
+ # Raises if nothing is found or if more than one env is found.
72
+ def environment_by_name(environment_name, account_name=nil)
73
+ EY::CloudClient::Environment.by_name(self, environment_name, account_name)
74
+ end
75
+
76
+ # For ease of use:
77
+ alias :env_by_name :environment_by_name
78
+
67
79
  end # API
68
80
  end # EY
@@ -3,9 +3,12 @@ module EY
3
3
  class Error < RuntimeError
4
4
  end
5
5
 
6
- class RequestFailed < Error; end
7
- class InvalidCredentials < RequestFailed; end
8
- class ResourceNotFound < RequestFailed; end
6
+ class RequestFailed < Error; end
7
+ class InvalidCredentials < RequestFailed; end
8
+ class ResourceNotFound < RequestFailed; end
9
+ class InvalidInstanceRole < Error; end
10
+ class InstanceNotProvisioned < Error; end
11
+ class MultipleMatchesError < RequestFailed; end
9
12
 
10
13
  class BadEndpointError < Error
11
14
  def initialize(endpoint)
@@ -33,6 +33,10 @@ module EY
33
33
  def environments
34
34
  @environments ||= []
35
35
  end
36
+
37
+ def <=>(other)
38
+ name <=> other.name
39
+ end
36
40
  end
37
41
  end
38
42
  end
@@ -1,6 +1,7 @@
1
1
  require 'engineyard-cloud-client/models/api_struct'
2
2
  require 'engineyard-cloud-client/errors'
3
3
  require 'stringio'
4
+ require 'time'
4
5
 
5
6
  module EY
6
7
  class CloudClient
@@ -37,6 +37,41 @@ module EY
37
37
  ResolverResult.new(api, matches, response['errors'], response['suggestions'])
38
38
  end
39
39
 
40
+ # Accepts an api object, environment name and optional account name
41
+ # and returns the best matching environment for the given constraints.
42
+ #
43
+ # This is a shortcut for resolve_environments.
44
+ # Raises if nothing is found or if more than one environment is found.
45
+ def self.by_name(api, environment_name, account_name=nil)
46
+ constraints = {
47
+ :environment_name => environment_name,
48
+ :account_name => account_name,
49
+ }
50
+ resolver = resolve(api, constraints)
51
+
52
+ resolver.one_match { |match| return match }
53
+
54
+ resolver.no_matches do |errors, suggestions|
55
+ message = nil
56
+ if suggestions.any?
57
+ message = "Suggestions found:\n"
58
+ suggestions.sourt_by{|suggest| suggest['account_name']}.each do |suggest|
59
+ message << "\t#{suggest['account_name']}/#{suggest['env_name']}\n"
60
+ end
61
+ end
62
+
63
+ raise ResourceNotFound.new([errors,message].compact.join("\n").strip)
64
+ end
65
+
66
+ resolver.many_matches do |matches|
67
+ message = "Multiple environments possible, please be more specific:\n"
68
+ matches.sort_by {|env| env.account}.each do |env|
69
+ message << "\t#{env.account.name}/#{env.name}\n"
70
+ end
71
+ raise MultipleMatchesError.new(message)
72
+ end
73
+ end
74
+
40
75
  # Usage
41
76
  # Environment.create(api, {
42
77
  # app: app, # requires: app.id
@@ -169,6 +204,120 @@ module EY
169
204
  name.gsub(/^#{Regexp.quote(app.name)}_/, '')
170
205
  end
171
206
 
207
+ #
208
+ # Throws a POST request at the API to /add_instances and adds one instance
209
+ # to this environment.
210
+ #
211
+ # Usage example:
212
+ #
213
+ # api = EY::CloudClient.new(token: 'your token here')
214
+ # env = api.environment_by_name('your_env_name')
215
+ #
216
+ # env.add_instance(role: "app")
217
+ # env.add_instance(role: "util", name: "foo")
218
+ #
219
+ # Note that the role for an instance MUST be either "app" or "util".
220
+ # No other value is acceptable. The "name" parameter can be anything,
221
+ # but it only applies to utility instances.
222
+ def add_instance(opts)
223
+ unless %w[app util].include?(opts[:role].to_s)
224
+ # Fail immediately because we don't have valid arguments.
225
+ raise InvalidInstanceRole, "Instance role must be one of: app, util"
226
+ end
227
+
228
+ # We know opts[:role] is right, name can be passed straight to the API.
229
+ # Return the response body for error output, logging, etc.
230
+ return api.post("/environments/#{id}/add_instances", :request => {
231
+ "role" => opts[:role],
232
+ "name" => opts[:name]
233
+ })
234
+ end
235
+
236
+ #
237
+ # Gets an instance's Amazon ID by its "id" attribute as reported
238
+ # by AWSM. When an instance is added via the API, the JSON that's
239
+ # returned contains an "id" attribute for that instance. Developers
240
+ # may save that ID so they can later discover an instance's Amazon ID.
241
+ # This is because, when an instance object is first *created* (see
242
+ # #add_instance above), its Amazon ID isn't yet known. The object is
243
+ # created, and *then* later provisioned, so you can't get an Amazon
244
+ # ID until after provisioning has taken place. This method allows you
245
+ # to send an ID to it, and then returns the instance object that
246
+ # corresponds to that ID, which will have an Amazon ID with it if the
247
+ # instance has been provisioned at the time the environment information
248
+ # was read.
249
+ #
250
+ # Note that the ID passed in must be an integer.
251
+ #
252
+ # Usage example:
253
+ #
254
+ # api = EY::CloudClient.new(token: 'token')
255
+ # env = api.environment_by_name('my_env')
256
+ # env.instance_by_id(12345)
257
+ # => <EY::CloudClient::Instance ...>
258
+ def instance_by_id(id)
259
+ instances.detect { |x| x.id == id } # ID should always be unique
260
+ end
261
+
262
+ #
263
+ # Sends a request to the API to remove the instance specified by
264
+ # its "provisioned_id" (Amazon ID).
265
+ #
266
+ # Usage example:
267
+ #
268
+ # api = EY::CloudClient.new(token: 'token')
269
+ # env = api.environment_by_name('my_app_production')
270
+ # bad_instance = env.instance_by_id(12345) # instance ID should be saved upon creation
271
+ # env.remove_instance(bad_instance)
272
+ #
273
+ # Warnings/caveats:
274
+ #
275
+ # + The API is responsible for actually removing this instance. All this
276
+ # does is send an appropriate request to the API.
277
+ # + You should look carefully at the API response JSON to see whether or
278
+ # not the API accepted or rejected your request. If it accepted the
279
+ # request, that instance *should* be removed as soon as possible.
280
+ # + Note that this is a client that talks to an API, which talks to an
281
+ # API, which talks to an API. Ultimately the IaaS provider API has the
282
+ # final say on whether or not to remove an instance, so a failure there
283
+ # can definitely affect how things work at every point down the line.
284
+ # + If the instance you pass in doesn't exist in the live cloud
285
+ # environment you're working on, the status should be rejected and thus
286
+ # the instance won't be removed (because *that* instance isn't there).
287
+ # This is important to keep in mind for scheduled/auto scaling; if
288
+ # for some reason the automatically added instance is removed before
289
+ # a "scale down" event that you might trigger, you may wind up with an
290
+ # unknown/unexpected number of instances in your environment.
291
+ # + Only works for app/util instances. Raises an error if you pass one
292
+ # that isn't valid.
293
+ def remove_instance(instance)
294
+ unless instance
295
+ raise ArgumentError, "A argument of type Instance was expected. Got #{instance.inspect}"
296
+ end
297
+
298
+ # Check to make sure that we have a valid instance role here first.
299
+ unless %w[app util].include?(instance.role)
300
+ raise InvalidInstanceRole, "Removing instances is only supported for app, util instances"
301
+ end
302
+
303
+ # Check to be sure that instance is actually provisioned
304
+ # TODO: Rip out the amazon_id stuff when we have IaaS agnosticism nailed down
305
+ unless instance.amazon_id && instance.provisioned?
306
+ raise InstanceNotProvisioned, "Instance is not provisioned or is in unusual state."
307
+ end
308
+
309
+ response = api.post("/environments/#{id}/remove_instances", :request => {
310
+ :provisioned_id => instance.amazon_id,
311
+ :role => instance.role
312
+ })
313
+
314
+ # Reset instances so they are fresh if they are requested again.
315
+ @instances = nil
316
+
317
+ # Return the response.
318
+ return response
319
+ end
320
+
172
321
  protected
173
322
 
174
323
  def set_account(account_attrs)
@@ -17,6 +17,10 @@ module EY
17
17
  def provisioned?
18
18
  hostname && role && status != "starting" # not foolproof, but help throw out bad instances
19
19
  end
20
+
21
+ def remove
22
+ environment.remove_instance(self)
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -1,7 +1,7 @@
1
1
  # This file is maintained by a herd of rabid monkeys with Rakes.
2
2
  module EY
3
3
  class CloudClient
4
- VERSION = '1.0.12'
4
+ VERSION = '1.0.13'
5
5
  end
6
6
  end
7
7
  # Please be aware that the monkeys like tho throw poo sometimes.
@@ -56,6 +56,26 @@ describe EY::CloudClient::Environment do
56
56
  end
57
57
  end
58
58
 
59
+ describe "api.environment_by_name / Environment.by_name / api.env_by_name" do
60
+ it "finds an environment" do
61
+ api = scenario_cloud_client "Multiple Ambiguous Accounts"
62
+ result = api.environment_by_name('giblets', 'main')
63
+ result.should be_a_kind_of(EY::CloudClient::Environment)
64
+ result.name.should == 'giblets'
65
+ result.account.name.should == 'main'
66
+ end
67
+
68
+ it "raises on ambiguous query" do
69
+ api = scenario_cloud_client "Multiple Ambiguous Accounts"
70
+ expect { EY::CloudClient::Environment.by_name(api, 'giblets') }.to raise_error(EY::CloudClient::MultipleMatchesError)
71
+ end
72
+
73
+ it "raises when env doesn't exist" do
74
+ api = scenario_cloud_client "Multiple Ambiguous Accounts"
75
+ expect { api.env_by_name('gobblegobble') }.to raise_error(EY::CloudClient::ResourceNotFound)
76
+ end
77
+ end
78
+
59
79
  context "with an environment" do
60
80
  before do
61
81
  api = scenario_cloud_client "Linked App"
@@ -291,4 +291,172 @@ describe EY::CloudClient::Environment do
291
291
  short('dev', 'dev').should == 'dev'
292
292
  end
293
293
  end
294
+
295
+ describe "#remove_instance(instance)" do
296
+ before do
297
+ @instances_response = [
298
+ {
299
+ 'id' => 12345,
300
+ 'role' => 'app',
301
+ 'status' => 'stale',
302
+ },
303
+ {
304
+ 'id' => 54321,
305
+ 'role' => 'util',
306
+ 'public_hostname' => 'some-hostname',
307
+ 'status' => 'running',
308
+ 'amazon_id' => 'i-xxxxxxx'
309
+ },
310
+ {
311
+ 'id' => 8675309,
312
+ 'role' => 'db_master'
313
+ },
314
+ {
315
+ 'id' => 55555,
316
+ 'role' => 'app',
317
+ 'public_hostname' => 'some-hostname',
318
+ 'status' => 'running',
319
+ 'amazon_id' => 'i-xxxxxxx'
320
+ }
321
+ ]
322
+
323
+ @api = EY::CloudClient.new(:token => 't')
324
+ @env = EY::CloudClient::Environment.from_hash(@api, {
325
+ 'name' => 'fake',
326
+ 'id' => '123',
327
+ 'instances_count' => 4,
328
+ })
329
+
330
+ FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/remove_instances",
331
+ :content_type => "application/json",
332
+ :body => MultiJson.dump({
333
+ "request" => {"provisioned_id"=>"i-xxxxxx", "role"=>"app"},
334
+ "instance" => {"amazon_id"=>"i-xxxxxxx", "id"=>12345, "role"=>"app", "status"=>"running"},
335
+ "status"=>"accepted"
336
+ }))
337
+
338
+ FakeWeb.register_uri(:get, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/instances?",
339
+ :content_type => "application/json", :body => MultiJson.dump('instances' => @instances_response))
340
+ end
341
+
342
+ after do
343
+ @env = nil # clean up
344
+ end
345
+
346
+ it "raises an error if role isn't app/util" do
347
+ i = @env.instance_by_id(8675309)
348
+ expect {
349
+ @env.remove_instance(i) # db_master, should fail
350
+ }.to raise_error EY::CloudClient::InvalidInstanceRole
351
+ FakeWeb.should_not have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/remove_instances")
352
+ end
353
+
354
+ it "raises an error if the instance isn't provisioned yet" do
355
+ i = @env.instance_by_id(12345)
356
+ expect {
357
+ @env.remove_instance(i) # app, but not provisioned and no amazon id
358
+ }.to raise_error EY::CloudClient::InstanceNotProvisioned
359
+ FakeWeb.should_not have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/remove_instances")
360
+ end
361
+
362
+ it "sends an API request when things check out" do
363
+ i = @env.instance_by_id(55555) # known good instance as defined above
364
+ expect {
365
+ @env.remove_instance(i)
366
+ }.to_not raise_error
367
+ FakeWeb.should have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/remove_instances")
368
+ end
369
+
370
+ it "does the same thing when Instance#remove helper method is used instead" do
371
+ i = @env.instance_by_id(54321)
372
+ expect {
373
+ i.remove
374
+ }.to_not raise_error
375
+ FakeWeb.should have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/remove_instances")
376
+ end
377
+
378
+ it "reloads the instances after a remove request" do
379
+ @env.instance_by_id(55555).remove
380
+ @instances_response.pop
381
+ FakeWeb.register_uri(:get, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/instances?",
382
+ :content_type => "application/json", :body => MultiJson.dump('instances' => @instances_response))
383
+ FakeWeb.should have_requested(:get, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/instances?")
384
+ end
385
+ end
386
+
387
+ describe "#add_instances(name: 'foo', role: 'app')" do
388
+ before :all do
389
+ @env = EY::CloudClient::Environment.from_hash(
390
+ EY::CloudClient.new(:token => 't'), {'name' => 'fake', "id" => "123"} )
391
+
392
+ # Register the API endpoint with FakeWeb
393
+ FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/add_instances",
394
+ :body => '{
395
+ "request"=>{"role"=>"app", "name"=>"foo"},
396
+ "instance"=>{
397
+ "id"=>257843, "name"=>nil,
398
+ "role"=>"app", "status"=>"starting"
399
+ },
400
+ "status"=>"accepted"}'
401
+ )
402
+ end
403
+
404
+ after :all do
405
+ @env = nil # clean up
406
+ end
407
+
408
+ it "will raise if role isn't present" do
409
+ expect {
410
+ @env.add_instance(:name => 'foo')
411
+ }.to raise_error EY::CloudClient::InvalidInstanceRole
412
+ FakeWeb.should_not have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/add_instances")
413
+ end
414
+
415
+ it "will raise if role isn't either app or util" do
416
+ expect {
417
+ @env.add_instance(:role => 'fake')
418
+ }.to raise_error EY::CloudClient::InvalidInstanceRole
419
+ FakeWeb.should_not have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/add_instances")
420
+ end
421
+
422
+ it "sends a POST request to the API" do
423
+ @env.add_instance(:role => "app")
424
+ FakeWeb.should have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/add_instances")
425
+ end
426
+
427
+ it "returns the API's response body" do
428
+ @env.add_instance(:role => "util", :name => "blah").should_not be_nil
429
+ FakeWeb.should have_requested(:post, "https://cloud.engineyard.com/api/v2/environments/#{@env.id}/add_instances")
430
+ end
431
+ end
432
+
433
+
434
+ describe "#instance_by_id(id)" do
435
+ before :all do
436
+ @env = EY::CloudClient::Environment.from_hash(
437
+ EY::CloudClient.new(:token => 't'),
438
+ {
439
+ 'name' => 'fake',
440
+ "id" => 123,
441
+ "instances" => [
442
+ {
443
+ "id" => 12345,
444
+ "role" => "app"
445
+ }
446
+ ]
447
+ })
448
+ end
449
+
450
+ after :all do
451
+ @env = nil
452
+ end
453
+
454
+ it "returns one instance when called with a valid id" do
455
+ @env.instance_by_id(12345).should_not be_nil
456
+ end
457
+
458
+ it "returns nil when called with a non-existent id" do
459
+ @env.instance_by_id(54321).should be_nil
460
+ end
461
+ end
294
462
  end
data/spec/spec_helper.rb CHANGED
@@ -27,6 +27,7 @@ require 'rspec'
27
27
  require 'tmpdir'
28
28
  require 'yaml'
29
29
  require 'pp'
30
+ require 'pry'
30
31
  support = Dir[File.join(EY_ROOT,'/spec/support/*.rb')]
31
32
  support.each{|helper| require helper }
32
33
 
metadata CHANGED
@@ -1,278 +1,295 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: engineyard-cloud-client
3
- version: !ruby/object:Gem::Version
4
- version: 1.0.12
3
+ version: !ruby/object:Gem::Version
4
+ hash: 13
5
5
  prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 13
10
+ version: 1.0.13
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - EY Cloud Team
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2013-06-01 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2013-08-13 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: rest-client
16
- requirement: !ruby/object:Gem::Requirement
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
17
23
  none: false
18
- requirements:
24
+ requirements:
19
25
  - - ~>
20
- - !ruby/object:Gem::Version
26
+ - !ruby/object:Gem::Version
27
+ hash: 15
28
+ segments:
29
+ - 1
30
+ - 6
31
+ - 0
21
32
  version: 1.6.0
22
- type: :runtime
23
33
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: 1.6.0
30
- - !ruby/object:Gem::Dependency
34
+ type: :runtime
35
+ requirement: *id001
36
+ - !ruby/object:Gem::Dependency
31
37
  name: multi_json
32
- requirement: !ruby/object:Gem::Requirement
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
33
39
  none: false
34
- requirements:
40
+ requirements:
35
41
  - - ~>
36
- - !ruby/object:Gem::Version
37
- version: '1.6'
38
- type: :runtime
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 1
46
+ - 6
47
+ version: "1.6"
39
48
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: '1.6'
46
- - !ruby/object:Gem::Dependency
49
+ type: :runtime
50
+ requirement: *id002
51
+ - !ruby/object:Gem::Dependency
47
52
  name: rspec
48
- requirement: !ruby/object:Gem::Requirement
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
49
54
  none: false
50
- requirements:
55
+ requirements:
51
56
  - - ~>
52
- - !ruby/object:Gem::Version
53
- version: '2.0'
54
- type: :development
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 2
61
+ - 0
62
+ version: "2.0"
55
63
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '2.0'
62
- - !ruby/object:Gem::Dependency
63
- name: rake
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
64
  type: :development
65
+ requirement: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: rake
68
+ version_requirements: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
71
77
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- - !ruby/object:Gem::Dependency
79
- name: fakeweb
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
85
- version: '0'
86
78
  type: :development
79
+ requirement: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: fakeweb
82
+ version_requirements: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
87
91
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
94
- - !ruby/object:Gem::Dependency
95
- name: fakeweb-matcher
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
92
  type: :development
93
+ requirement: *id005
94
+ - !ruby/object:Gem::Dependency
95
+ name: fakeweb-matcher
96
+ version_requirements: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
103
105
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ! '>='
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- - !ruby/object:Gem::Dependency
111
- name: sinatra
112
- requirement: !ruby/object:Gem::Requirement
113
- none: false
114
- requirements:
115
- - - ! '>='
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
106
  type: :development
107
+ requirement: *id006
108
+ - !ruby/object:Gem::Dependency
109
+ name: sinatra
110
+ version_requirements: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
119
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ! '>='
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
120
+ type: :development
121
+ requirement: *id007
122
+ - !ruby/object:Gem::Dependency
127
123
  name: realweb
128
- requirement: !ruby/object:Gem::Requirement
124
+ version_requirements: &id008 !ruby/object:Gem::Requirement
129
125
  none: false
130
- requirements:
126
+ requirements:
131
127
  - - ~>
132
- - !ruby/object:Gem::Version
128
+ - !ruby/object:Gem::Version
129
+ hash: 21
130
+ segments:
131
+ - 1
132
+ - 0
133
+ - 1
133
134
  version: 1.0.1
134
- type: :development
135
135
  prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ~>
140
- - !ruby/object:Gem::Version
141
- version: 1.0.1
142
- - !ruby/object:Gem::Dependency
136
+ type: :development
137
+ requirement: *id008
138
+ - !ruby/object:Gem::Dependency
143
139
  name: dm-core
144
- requirement: !ruby/object:Gem::Requirement
140
+ version_requirements: &id009 !ruby/object:Gem::Requirement
145
141
  none: false
146
- requirements:
142
+ requirements:
147
143
  - - ~>
148
- - !ruby/object:Gem::Version
144
+ - !ruby/object:Gem::Version
145
+ hash: 31
146
+ segments:
147
+ - 1
148
+ - 2
149
+ - 0
149
150
  version: 1.2.0
150
- type: :development
151
151
  prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ~>
156
- - !ruby/object:Gem::Version
157
- version: 1.2.0
158
- - !ruby/object:Gem::Dependency
159
- name: dm-migrations
160
- requirement: !ruby/object:Gem::Requirement
161
- none: false
162
- requirements:
163
- - - ! '>='
164
- - !ruby/object:Gem::Version
165
- version: '0'
166
152
  type: :development
153
+ requirement: *id009
154
+ - !ruby/object:Gem::Dependency
155
+ name: dm-migrations
156
+ version_requirements: &id010 !ruby/object:Gem::Requirement
157
+ none: false
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ hash: 3
162
+ segments:
163
+ - 0
164
+ version: "0"
167
165
  prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
- requirements:
171
- - - ! '>='
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- - !ruby/object:Gem::Dependency
175
- name: dm-aggregates
176
- requirement: !ruby/object:Gem::Requirement
177
- none: false
178
- requirements:
179
- - - ! '>='
180
- - !ruby/object:Gem::Version
181
- version: '0'
182
166
  type: :development
167
+ requirement: *id010
168
+ - !ruby/object:Gem::Dependency
169
+ name: dm-aggregates
170
+ version_requirements: &id011 !ruby/object:Gem::Requirement
171
+ none: false
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ hash: 3
176
+ segments:
177
+ - 0
178
+ version: "0"
183
179
  prerelease: false
184
- version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
- requirements:
187
- - - ! '>='
188
- - !ruby/object:Gem::Version
189
- version: '0'
190
- - !ruby/object:Gem::Dependency
191
- name: dm-timestamps
192
- requirement: !ruby/object:Gem::Requirement
193
- none: false
194
- requirements:
195
- - - ! '>='
196
- - !ruby/object:Gem::Version
197
- version: '0'
198
180
  type: :development
181
+ requirement: *id011
182
+ - !ruby/object:Gem::Dependency
183
+ name: dm-timestamps
184
+ version_requirements: &id012 !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ hash: 3
190
+ segments:
191
+ - 0
192
+ version: "0"
199
193
  prerelease: false
200
- version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
- requirements:
203
- - - ! '>='
204
- - !ruby/object:Gem::Version
205
- version: '0'
206
- - !ruby/object:Gem::Dependency
207
- name: dm-sqlite-adapter
208
- requirement: !ruby/object:Gem::Requirement
209
- none: false
210
- requirements:
211
- - - ! '>='
212
- - !ruby/object:Gem::Version
213
- version: '0'
214
194
  type: :development
195
+ requirement: *id012
196
+ - !ruby/object:Gem::Dependency
197
+ name: dm-sqlite-adapter
198
+ version_requirements: &id013 !ruby/object:Gem::Requirement
199
+ none: false
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ hash: 3
204
+ segments:
205
+ - 0
206
+ version: "0"
215
207
  prerelease: false
216
- version_requirements: !ruby/object:Gem::Requirement
217
- none: false
218
- requirements:
219
- - - ! '>='
220
- - !ruby/object:Gem::Version
221
- version: '0'
222
- - !ruby/object:Gem::Dependency
208
+ type: :development
209
+ requirement: *id013
210
+ - !ruby/object:Gem::Dependency
223
211
  name: ey_resolver
224
- requirement: !ruby/object:Gem::Requirement
212
+ version_requirements: &id014 !ruby/object:Gem::Requirement
225
213
  none: false
226
- requirements:
214
+ requirements:
227
215
  - - ~>
228
- - !ruby/object:Gem::Version
216
+ - !ruby/object:Gem::Version
217
+ hash: 21
218
+ segments:
219
+ - 0
220
+ - 2
221
+ - 1
229
222
  version: 0.2.1
230
- type: :development
231
223
  prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- none: false
234
- requirements:
235
- - - ~>
236
- - !ruby/object:Gem::Version
237
- version: 0.2.1
238
- - !ruby/object:Gem::Dependency
224
+ type: :development
225
+ requirement: *id014
226
+ - !ruby/object:Gem::Dependency
239
227
  name: rabl
240
- requirement: !ruby/object:Gem::Requirement
241
- none: false
242
- requirements:
243
- - - ! '>='
244
- - !ruby/object:Gem::Version
245
- version: '0'
228
+ version_requirements: &id015 !ruby/object:Gem::Requirement
229
+ none: false
230
+ requirements:
231
+ - - ">="
232
+ - !ruby/object:Gem::Version
233
+ hash: 3
234
+ segments:
235
+ - 0
236
+ version: "0"
237
+ prerelease: false
246
238
  type: :development
239
+ requirement: *id015
240
+ - !ruby/object:Gem::Dependency
241
+ name: activesupport
242
+ version_requirements: &id016 !ruby/object:Gem::Requirement
243
+ none: false
244
+ requirements:
245
+ - - <
246
+ - !ruby/object:Gem::Version
247
+ hash: 63
248
+ segments:
249
+ - 4
250
+ - 0
251
+ - 0
252
+ version: 4.0.0
247
253
  prerelease: false
248
- version_requirements: !ruby/object:Gem::Requirement
249
- none: false
250
- requirements:
251
- - - ! '>='
252
- - !ruby/object:Gem::Version
253
- version: '0'
254
- - !ruby/object:Gem::Dependency
254
+ type: :development
255
+ requirement: *id016
256
+ - !ruby/object:Gem::Dependency
255
257
  name: oj
256
- requirement: !ruby/object:Gem::Requirement
257
- none: false
258
- requirements:
259
- - - ! '>='
260
- - !ruby/object:Gem::Version
261
- version: '0'
258
+ version_requirements: &id017 !ruby/object:Gem::Requirement
259
+ none: false
260
+ requirements:
261
+ - - ">="
262
+ - !ruby/object:Gem::Version
263
+ hash: 3
264
+ segments:
265
+ - 0
266
+ version: "0"
267
+ prerelease: false
262
268
  type: :development
269
+ requirement: *id017
270
+ - !ruby/object:Gem::Dependency
271
+ name: pry
272
+ version_requirements: &id018 !ruby/object:Gem::Requirement
273
+ none: false
274
+ requirements:
275
+ - - ">="
276
+ - !ruby/object:Gem::Version
277
+ hash: 3
278
+ segments:
279
+ - 0
280
+ version: "0"
263
281
  prerelease: false
264
- version_requirements: !ruby/object:Gem::Requirement
265
- none: false
266
- requirements:
267
- - - ! '>='
268
- - !ruby/object:Gem::Version
269
- version: '0'
282
+ type: :development
283
+ requirement: *id018
270
284
  description: This gem connects to the EY Cloud API
271
285
  email: cloud@engineyard.com
272
286
  executables: []
287
+
273
288
  extensions: []
289
+
274
290
  extra_rdoc_files: []
275
- files:
291
+
292
+ files:
276
293
  - lib/engineyard-cloud-client/connection.rb
277
294
  - lib/engineyard-cloud-client/errors.rb
278
295
  - lib/engineyard-cloud-client/model_registry.rb
@@ -341,36 +358,39 @@ files:
341
358
  - spec/support/helpers.rb
342
359
  - spec/support/matchers.rb
343
360
  homepage: http://github.com/engineyard/engineyard-cloud-client
344
- licenses: []
361
+ licenses:
362
+ - MIT
345
363
  post_install_message:
346
364
  rdoc_options: []
347
- require_paths:
365
+
366
+ require_paths:
348
367
  - lib
349
- required_ruby_version: !ruby/object:Gem::Requirement
368
+ required_ruby_version: !ruby/object:Gem::Requirement
350
369
  none: false
351
- requirements:
352
- - - ! '>='
353
- - !ruby/object:Gem::Version
354
- version: '0'
355
- segments:
370
+ requirements:
371
+ - - ">="
372
+ - !ruby/object:Gem::Version
373
+ hash: 3
374
+ segments:
356
375
  - 0
357
- hash: -3400955285524549392
358
- required_rubygems_version: !ruby/object:Gem::Requirement
376
+ version: "0"
377
+ required_rubygems_version: !ruby/object:Gem::Requirement
359
378
  none: false
360
- requirements:
361
- - - ! '>='
362
- - !ruby/object:Gem::Version
363
- version: '0'
364
- segments:
379
+ requirements:
380
+ - - ">="
381
+ - !ruby/object:Gem::Version
382
+ hash: 3
383
+ segments:
365
384
  - 0
366
- hash: -3400955285524549392
385
+ version: "0"
367
386
  requirements: []
387
+
368
388
  rubyforge_project:
369
389
  rubygems_version: 1.8.25
370
390
  signing_key:
371
391
  specification_version: 3
372
392
  summary: EY Cloud API Client
373
- test_files:
393
+ test_files:
374
394
  - spec/engineyard-cloud-client/api_spec.rb
375
395
  - spec/engineyard-cloud-client/integration/account_spec.rb
376
396
  - spec/engineyard-cloud-client/integration/app_environment_spec.rb