engineyard-cloud-client 1.0.12 → 1.0.13

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/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