engineyard-cloud-client 1.0.3 → 1.0.4

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.
Files changed (27) hide show
  1. data/lib/engineyard-cloud-client.rb +14 -93
  2. data/lib/engineyard-cloud-client/connection.rb +142 -0
  3. data/lib/engineyard-cloud-client/models/account.rb +1 -1
  4. data/lib/engineyard-cloud-client/models/app.rb +2 -2
  5. data/lib/engineyard-cloud-client/models/app_environment.rb +4 -4
  6. data/lib/engineyard-cloud-client/models/deployment.rb +6 -6
  7. data/lib/engineyard-cloud-client/models/environment.rb +13 -11
  8. data/lib/engineyard-cloud-client/models/keypair.rb +3 -3
  9. data/lib/engineyard-cloud-client/models/recipes.rb +3 -6
  10. data/lib/engineyard-cloud-client/test.rb +3 -3
  11. data/lib/engineyard-cloud-client/test/fake_awsm/config.ru +4 -3
  12. data/lib/engineyard-cloud-client/test/fake_awsm/views/base_app_environment.rabl +1 -1
  13. data/lib/engineyard-cloud-client/test/fake_awsm/views/base_environment.rabl +1 -1
  14. data/lib/engineyard-cloud-client/test/fake_awsm/views/environments.rabl +1 -1
  15. data/lib/engineyard-cloud-client/test/scenario.rb +2 -3
  16. data/lib/engineyard-cloud-client/version.rb +1 -1
  17. data/spec/engineyard-cloud-client/api_spec.rb +15 -33
  18. data/spec/engineyard-cloud-client/integration/account_spec.rb +0 -1
  19. data/spec/engineyard-cloud-client/integration/app_environment_spec.rb +0 -1
  20. data/spec/engineyard-cloud-client/integration/app_spec.rb +0 -1
  21. data/spec/engineyard-cloud-client/integration/deployment_spec.rb +1 -2
  22. data/spec/engineyard-cloud-client/integration/environment_spec.rb +0 -1
  23. data/spec/engineyard-cloud-client/integration/user_spec.rb +6 -9
  24. data/spec/spec_helper.rb +0 -3
  25. data/spec/support/helpers.rb +2 -6
  26. metadata +9 -9
  27. data/lib/engineyard-cloud-client/test/ui.rb +0 -33
@@ -3,6 +3,7 @@ module EY
3
3
  end
4
4
  end
5
5
 
6
+ require 'engineyard-cloud-client/connection'
6
7
  require 'engineyard-cloud-client/model_registry'
7
8
  require 'engineyard-cloud-client/models'
8
9
  require 'engineyard-cloud-client/rest_client_ext'
@@ -11,58 +12,33 @@ require 'engineyard-cloud-client/version'
11
12
  require 'engineyard-cloud-client/errors'
12
13
  require 'multi_json'
13
14
  require 'pp'
15
+ require 'forwardable'
14
16
 
15
17
  module EY
16
18
  class CloudClient
17
- attr_reader :token, :registry
18
- attr_accessor :ui
19
+ extend Forwardable
19
20
 
20
- USER_AGENT_STRING = "EngineYardCloudClient/#{EY::CloudClient::VERSION}"
21
+ def_delegators :connection, :head, :get, :post, :put, :delete, :request, :endpoint, :token, :token=, :authenticate!, :authenticated?
21
22
 
22
- def self.endpoint
23
- @endpoint
24
- end
25
-
26
- def self.endpoint=(endpoint)
27
- @endpoint = URI.parse(endpoint)
28
- unless @endpoint.absolute?
29
- raise BadEndpointError.new(endpoint)
30
- end
31
- @endpoint
32
- end
33
-
34
- def self.default_endpoint!
35
- self.endpoint = "https://cloud.engineyard.com/"
36
- end
37
- default_endpoint!
23
+ attr_reader :connection
38
24
 
39
- def initialize(token, ui)
40
- self.token = token
41
- self.ui = ui
25
+ # Initialize a new EY::CloudClient.
26
+ #
27
+ # Creates and stores a new Connection for communicating with EY Cloud.
28
+ #
29
+ # See EY::CloudClient::Connection for options.
30
+ def initialize(options={})
31
+ @connection = Connection.new(options)
42
32
  end
43
33
 
44
34
  def ==(other)
45
- other.is_a?(self.class) && other.token == token
35
+ other.is_a?(self.class) && other.connection == connection
46
36
  end
47
37
 
48
38
  def registry
49
39
  @registry ||= ModelRegistry.new
50
40
  end
51
41
 
52
- def token=(new_token)
53
- unless new_token
54
- raise ArgumentError, "EY Cloud API token required"
55
- end
56
- @token = new_token
57
- end
58
-
59
- def request(url, opts={})
60
- opts[:headers] ||= {}
61
- opts[:headers]["X-EY-Cloud-Token"] = token
62
- ui.debug("Token", token)
63
- self.class.request(url, ui, opts)
64
- end
65
-
66
42
  def resolve_environments(constraints)
67
43
  EY::CloudClient::Environment.resolve(self, constraints)
68
44
  end
@@ -86,62 +62,7 @@ module EY
86
62
  end
87
63
 
88
64
  def current_user
89
- EY::CloudClient::User.from_hash(self, request('/current_user')['user'])
90
- end
91
-
92
- def self.request(path, ui, opts={})
93
- url = self.endpoint + "api/v2#{path}"
94
- method = (opts.delete(:method) || 'get').to_s.downcase.to_sym
95
- params = opts.delete(:params) || {}
96
- headers = opts.delete(:headers) || {}
97
- headers["Accept"] ||= "application/json"
98
- headers["User-Agent"] = USER_AGENT_STRING
99
-
100
- begin
101
- ui.debug("Request", "#{method.to_s.upcase} #{url}")
102
- ui.debug("Params", params.inspect)
103
- case method
104
- when :get, :delete, :head
105
- unless params.empty?
106
- url.query = RestClient::Payload::UrlEncoded.new(params).to_s
107
- end
108
- resp = RestClient.send(method, url.to_s, headers)
109
- else
110
- resp = RestClient.send(method, url.to_s, params, headers)
111
- end
112
- rescue RestClient::Unauthorized
113
- raise InvalidCredentials
114
- rescue Errno::ECONNREFUSED
115
- raise RequestFailed, "Could not reach the cloud API"
116
- rescue RestClient::ResourceNotFound
117
- raise ResourceNotFound, "The requested resource could not be found"
118
- rescue RestClient::BadGateway
119
- raise RequestFailed, "EY Cloud API is temporarily unavailable. Please try again soon."
120
- rescue RestClient::RequestFailed => e
121
- raise RequestFailed, "#{e.message} #{e.response}"
122
- rescue OpenSSL::SSL::SSLError
123
- raise RequestFailed, "SSL is misconfigured on your cloud"
124
- end
125
-
126
- if resp.body.empty?
127
- data = ''
128
- elsif resp.headers[:content_type] =~ /application\/json/
129
- begin
130
- data = MultiJson.load(resp.body)
131
- ui.debug("Response", "\n" + data.pretty_inspect)
132
- rescue MultiJson::DecodeError
133
- ui.debug("Raw response", resp.body)
134
- raise RequestFailed, "Response was not valid JSON."
135
- end
136
- else
137
- data = resp.body
138
- end
139
-
140
- data
141
- end
142
-
143
- def self.authenticate(email, password, ui)
144
- request("/authenticate", ui, { :method => "post", :params => { :email => email, :password => password }})["api_token"]
65
+ EY::CloudClient::User.from_hash(self, get('/current_user')['user'])
145
66
  end
146
67
 
147
68
  end # API
@@ -0,0 +1,142 @@
1
+ require 'engineyard-cloud-client/rest_client_ext'
2
+ require 'multi_json'
3
+ require 'uri'
4
+
5
+ module EY
6
+ class CloudClient
7
+ class Connection
8
+ attr_reader :token, :output, :user_agent, :endpoint
9
+
10
+ BASE_USER_AGENT = "EngineYardCloudClient/#{EY::CloudClient::VERSION}".freeze
11
+ DEFAULT_ENDPOINT = "https://cloud.engineyard.com/".freeze
12
+
13
+ # Initialize a new EY::CloudClient::Connection with a hash including:
14
+ #
15
+ # :token: (optional) Perform authenticated requests with this token
16
+ # :user_agent: (optional) A user agent name/version pair to add to the User-Agent header. (e.g. EngineYardCLI/2.0.0)
17
+ # :output: (optional) Send output to a stream other than $stdout
18
+ # :endpoint: (optional) An alternate Engine Yard Cloud endpoint URI
19
+ def initialize(options={})
20
+ @output = options[:output] || $stdout
21
+ @user_agent = [options[:user_agent], BASE_USER_AGENT].compact.join(' ').strip
22
+ @endpoint = URI.parse(options[:endpoint] || DEFAULT_ENDPOINT)
23
+ self.token = options[:token]
24
+
25
+ unless @endpoint.absolute?
26
+ raise BadEndpointError.new(@endpoint)
27
+ end
28
+ end
29
+
30
+ def token=(new_token)
31
+ @token = new_token
32
+ end
33
+
34
+ def debug(name, value)
35
+ return unless ENV['DEBUG']
36
+
37
+ indent = 12 # 12 because that's what Thor used.
38
+ unless String === value
39
+ value = value.pretty_inspect.rstrip # remove trailing whitespace
40
+ if value.index("\n") # if the inspect is multi-line
41
+ value.gsub!(/[\r\n]./, "\n" + ' ' * (indent + 2)) # indent it
42
+ end
43
+ end
44
+ @output << "#{name.to_s.rjust(indent)} #{value.rstrip}\n" # just one newline
45
+ end
46
+
47
+ def ==(other)
48
+ other.is_a?(self.class) && [other.token, other.user_agent, other.endpoint] == [token, user_agent, endpoint]
49
+ end
50
+
51
+ %w[ get head post put delete ].each do |meth|
52
+ eval <<-RUBY, binding, __FILE__, __LINE__ + 1
53
+ def #{meth}(path, params=nil, headers=nil, &block)
54
+ request("#{meth}", path, params, headers, &block)
55
+ end
56
+ RUBY
57
+ end
58
+
59
+ def request(meth, path, params=nil, extra_headers=nil)
60
+ url = endpoint + "api/v2#{path}"
61
+ meth ||= 'get'
62
+ meth = meth.to_s.downcase.to_sym
63
+ params ||= {}
64
+
65
+ headers = {
66
+ "User-Agent" => user_agent,
67
+ "Accept" => "application/json",
68
+ }
69
+
70
+ if token
71
+ headers["X-EY-Cloud-Token"] = token
72
+ end
73
+
74
+ if extra_headers
75
+ headers.merge!(extra_headers)
76
+ end
77
+
78
+ debug(meth.to_s.upcase, url.to_s)
79
+ debug("Params", params) if params
80
+ debug("Headers", headers)
81
+
82
+ resp = do_request(meth, url, params, headers)
83
+ data = parse_response(resp)
84
+
85
+ data
86
+ end
87
+
88
+ def authenticate!(email, password)
89
+ response = post("/authenticate", :email => email, :password => password)
90
+ self.token = response["api_token"]
91
+ token
92
+ end
93
+
94
+ def authenticated?
95
+ !token.nil? && !token.empty?
96
+ end
97
+
98
+ private
99
+
100
+ def do_request(meth, url, params, headers)
101
+ case meth
102
+ when :get, :delete, :head
103
+ if params
104
+ url.query = RestClient::Payload::UrlEncoded.new(params).to_s
105
+ end
106
+ RestClient.send(meth, url.to_s, headers)
107
+ else
108
+ RestClient.send(meth, url.to_s, params, headers)
109
+ end
110
+ rescue RestClient::Unauthorized
111
+ raise InvalidCredentials
112
+ rescue Errno::ECONNREFUSED
113
+ raise RequestFailed, "Could not reach the cloud API"
114
+ rescue RestClient::ResourceNotFound
115
+ raise ResourceNotFound, "The requested resource could not be found"
116
+ rescue RestClient::BadGateway
117
+ raise RequestFailed, "EY Cloud API is temporarily unavailable. Please try again soon."
118
+ rescue RestClient::RequestFailed => e
119
+ raise RequestFailed, "#{e.message} #{e.response}"
120
+ rescue OpenSSL::SSL::SSLError
121
+ raise RequestFailed, "SSL is misconfigured on your cloud"
122
+ end
123
+
124
+ def parse_response(resp)
125
+ if resp.body.empty?
126
+ ''
127
+ elsif resp.headers[:content_type] =~ /application\/json/
128
+ begin
129
+ data = MultiJson.load(resp.body)
130
+ debug("Response", data)
131
+ data
132
+ rescue MultiJson::DecodeError
133
+ debug("Response", resp.body)
134
+ raise RequestFailed, "Response was not valid JSON."
135
+ end
136
+ else
137
+ resp.body
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -5,7 +5,7 @@ module EY
5
5
  class Account < ApiStruct.new(:id, :name)
6
6
 
7
7
  def self.all(api)
8
- self.from_array(api, api.request('/accounts')["accounts"])
8
+ self.from_array(api, api.get("/accounts")["accounts"])
9
9
  end
10
10
 
11
11
  def add_app(app)
@@ -9,7 +9,7 @@ module EY
9
9
 
10
10
  # Return list of all Apps linked to all current user's accounts
11
11
  def self.all(api)
12
- self.from_array(api, api.request('/apps?no_instances=true')["apps"])
12
+ self.from_array(api, api.get("/apps", 'no_instances' => 'true')["apps"])
13
13
  end
14
14
 
15
15
  # An everything-you-need helper to create an App
@@ -32,7 +32,7 @@ module EY
32
32
  raise EY::CloudClient::AttributeRequiredError.new("name") unless params["name"]
33
33
  raise EY::CloudClient::AttributeRequiredError.new("repository_uri") unless params["repository_uri"]
34
34
  raise EY::CloudClient::AttributeRequiredError.new("app_type_id") unless params["app_type_id"]
35
- response = api.request("/accounts/#{account.id}/apps", :method => :post, :params => {"app" => params})
35
+ response = api.post("/accounts/#{account.id}/apps", "app" => params)
36
36
  from_hash(api, response['app'])
37
37
  end
38
38
 
@@ -7,15 +7,15 @@ module EY
7
7
 
8
8
  # Return a constrained list of app_environments given a set of constraints like:
9
9
  #
10
- # * app_name
11
- # * account_name
12
- # * environment_name
10
+ # * app_name: app name full or partial match string
11
+ # * account_name: account name full or partial match string
12
+ # * environment_name: environment name full or partial match string
13
13
  # * remotes: An array of git remote URIs
14
14
  #
15
15
  def self.resolve(api, constraints)
16
16
  clean_constraints = constraints.reject { |k,v| v.nil? }
17
17
  params = {'constraints' => clean_constraints}
18
- response = api.request("/app_environments/resolve", :method => :get, :params => params)['resolver']
18
+ response = api.get("/app_environments/resolve", params)['resolver']
19
19
  matches = from_array(api, response['matches'])
20
20
  ResolverResult.new(api, matches, response['errors'], response['suggestions'])
21
21
  end
@@ -14,7 +14,7 @@ module EY
14
14
 
15
15
  def self.get(api, app_environment, id)
16
16
  uri = api_root(app_environment.app.id, app_environment.environment.id) + "/#{id}"
17
- response = api.request(uri, :method => :get)
17
+ response = api.get(uri)
18
18
  load_from_response api, app_environment, response
19
19
  rescue EY::CloudClient::ResourceNotFound
20
20
  nil
@@ -47,16 +47,16 @@ module EY
47
47
  alias deployed_by= user_name=
48
48
 
49
49
  def created_at
50
- super && (@created_at ||= Time.parse(super))
50
+ @created_at ||= super && Time.parse(super)
51
51
  end
52
52
 
53
53
  def finished_at
54
- super && (@finished_at ||= Time.parse(super))
54
+ @finished_at ||= super && Time.parse(super)
55
55
  end
56
56
 
57
57
  def config
58
58
  return {} unless deployed_by # not started yet so not all info is here
59
- @config ||= {'deployed_by' => deployed_by}.merge(extra_config)
59
+ @config ||= {'input_ref' => ref, 'deployed_by' => deployed_by}.merge(extra_config)
60
60
  end
61
61
 
62
62
  def start
@@ -95,11 +95,11 @@ module EY
95
95
  private
96
96
 
97
97
  def post_to_api(params)
98
- update_with_response api.request(collection_uri, :method => :post, :params => {:deployment => params})
98
+ update_with_response api.post(collection_uri, 'deployment' => params)
99
99
  end
100
100
 
101
101
  def put_to_api(params)
102
- update_with_response api.request(member_uri("/finished"), :method => :put, :params => {:deployment => params})
102
+ update_with_response api.put(member_uri("/finished"), 'deployment' => params)
103
103
  end
104
104
 
105
105
  def collection_uri
@@ -4,27 +4,29 @@ require 'engineyard-cloud-client/errors'
4
4
 
5
5
  module EY
6
6
  class CloudClient
7
- class Environment < ApiStruct.new(:id, :name, :framework_env, :instances_count,
7
+ class Environment < ApiStruct.new(:id, :name, :framework_env,
8
+ :instances_count,
9
+ :instance_status,
8
10
  :username, :app_server_stack_name,
9
11
  :load_balancer_ip_address
10
12
  )
11
13
 
12
14
  # Return list of all Environments linked to all current user's accounts
13
15
  def self.all(api)
14
- self.from_array(api, api.request('/environments?no_instances=true')["environments"])
16
+ self.from_array(api, api.get("/environments", "no_instances" => "true")["environments"])
15
17
  end
16
18
 
17
19
  # Return a constrained list of environments given a set of constraints like:
18
20
  #
19
- # * app_name
20
- # * account_name
21
- # * environment_name
21
+ # * app_name: app name full or partial match string
22
+ # * account_name: account name full or partial match string
23
+ # * environment_name: environment name full or partial match string
22
24
  # * remotes: An array of git remote URIs
23
25
  #
24
26
  def self.resolve(api, constraints)
25
27
  clean_constraints = constraints.reject { |k,v| v.nil? }
26
28
  params = {'constraints' => clean_constraints}
27
- response = api.request("/environments/resolve", :method => :get, :params => params)['resolver']
29
+ response = api.get("/environments/resolve", params)['resolver']
28
30
  matches = from_array(api, response['matches'])
29
31
  ResolverResult.new(api, matches, response['errors'], response['suggestions'])
30
32
  end
@@ -52,7 +54,7 @@ module EY
52
54
 
53
55
  params = {"environment" => attrs.dup}
54
56
  unpack_cluster_configuration(params, cluster_configuration)
55
- response = api.request("/apps/#{app.id}/environments", :method => :post, :params => params)
57
+ response = api.post("/apps/#{app.id}/environments", params)
56
58
  self.from_hash(api, response['environment'])
57
59
  end
58
60
  attr_accessor :apps, :account
@@ -99,7 +101,7 @@ module EY
99
101
  end
100
102
 
101
103
  def logs
102
- Log.from_array(api, api.request("/environments/#{id}/logs", :method => :get)["logs"])
104
+ Log.from_array(api, api.get("/environments/#{id}/logs")["logs"])
103
105
  end
104
106
 
105
107
  def deploy_to_instances
@@ -114,13 +116,13 @@ module EY
114
116
  if bridge.nil?
115
117
  raise NoBridgeError.new(name)
116
118
  elsif !ignore_bad_bridge && bridge.status != "running"
117
- raise BadBridgeStatusError.new(bridge.status, EY::CloudClient.endpoint)
119
+ raise BadBridgeStatusError.new(bridge.status, api.endpoint)
118
120
  end
119
121
  bridge
120
122
  end
121
123
 
122
124
  def update
123
- api.request("/environments/#{id}/update_instances", :method => :put)
125
+ api.put("/environments/#{id}/update_instances")
124
126
  true # raises on failure
125
127
  end
126
128
  alias rebuild update
@@ -178,7 +180,7 @@ module EY
178
180
  if instances_count.zero?
179
181
  []
180
182
  else
181
- instances_attrs = api.request("/environments/#{id}/instances")["instances"]
183
+ instances_attrs = api.get("/environments/#{id}/instances")["instances"]
182
184
  load_instances(instances_attrs)
183
185
  end
184
186
  end
@@ -5,7 +5,7 @@ module EY
5
5
  class Keypair < ApiStruct.new(:id, :name, :public_key)
6
6
 
7
7
  def self.all(api)
8
- self.from_array(api, api.request('/keypairs')["keypairs"])
8
+ self.from_array(api, api.get("/keypairs")["keypairs"])
9
9
  end
10
10
 
11
11
  # Create a Keypair with your SSH public key so that you can access your Instances
@@ -24,8 +24,8 @@ module EY
24
24
  params = attrs.dup # no default fields
25
25
  raise EY::CloudClient::AttributeRequiredError.new("name") unless params["name"]
26
26
  raise EY::CloudClient::AttributeRequiredError.new("public_key") unless params["public_key"]
27
- response = api.request("/keypairs", :method => :post, :params => {"keypair" => params})
28
- self.from_hash(api, response['keypair'])
27
+ response = api.post("/keypairs", "keypair" => params)['keypair']
28
+ self.from_hash(api, response)
29
29
  end
30
30
  end
31
31
  end
@@ -12,13 +12,13 @@ module EY
12
12
  end
13
13
 
14
14
  def run
15
- api.request("/environments/#{environment.id}/run_custom_recipes", :method => :put)
15
+ api.put("/environments/#{environment.id}/run_custom_recipes")
16
16
  true
17
17
  end
18
18
 
19
19
  def download
20
20
  tmp = Tempfile.new("recipes")
21
- data = api.request("/environments/#{environment.id}/recipes")
21
+ data = api.get("/environments/#{environment.id}/recipes")
22
22
  tmp.write(data)
23
23
  tmp.flush
24
24
  tmp.close
@@ -37,10 +37,7 @@ module EY
37
37
  # Expects a File object opened for binary reading.
38
38
  # i.e. upload(File.open(recipes_path, 'rb'))
39
39
  def upload(file_to_upload)
40
- api.request("/environments/#{environment.id}/recipes", {
41
- :method => :post,
42
- :params => {:file => file_to_upload}
43
- })
40
+ api.post("/environments/#{environment.id}/recipes", :file => file_to_upload)
44
41
  true
45
42
  end
46
43
 
@@ -15,11 +15,12 @@ rescue LoadError
15
15
  engineyard-cloud-client needs the following gems to run in test mode:
16
16
 
17
17
  group 'engineyard-cloud-client-test' do
18
- gem 'dm-core'
18
+ gem 'dm-core', '~>1.2.0'
19
19
  gem 'dm-migrations'
20
20
  gem 'dm-aggregates'
21
+ gem 'dm-timestamps'
21
22
  gem 'dm-sqlite-adapter'
22
- gem 'ey_resolver', '~>0.2.1'
23
+ gem 'ey_resolver', '~>0.2.1'
23
24
  gem 'rabl'
24
25
  end
25
26
 
@@ -27,5 +28,4 @@ Please add the above to your Gemfile.
27
28
  ERROR
28
29
  end
29
30
 
30
- require 'engineyard-cloud-client/test/ui'
31
31
  require 'engineyard-cloud-client/test/scenario'
@@ -36,9 +36,10 @@ class FakeAwsm < Sinatra::Base
36
36
  before do
37
37
  if env['PATH_INFO'] =~ %r#/api/v2#
38
38
  user_agent = env['HTTP_USER_AGENT']
39
- unless user_agent =~ %r#^EngineYardCloudClient/\d#
40
- $stderr.puts 'No user agent header, expected EngineYardCloudClient/'
41
- halt 400, 'No user agent header, expected EngineYardCloudClient/'
39
+ unless user_agent =~ %r#EngineYardCloudClient/\d#
40
+ msg = "No user agent header, expected EngineYardCloudClient/ got #{user_agent.inspect}"
41
+ $stderr.puts msg
42
+ halt 400, msg
42
43
  end
43
44
  end
44
45
  content_type "application/json"
@@ -1,6 +1,6 @@
1
1
  attributes :id, :domain_name, :uri
2
2
  child :environment do
3
- attributes :id, :ssh_username, :name, :instances_count, :app_server_stack_name, :load_balancer_ip_address, :framework_env
3
+ attributes :id, :ssh_username, :name, :instances_count, :instance_status, :app_server_stack_name, :load_balancer_ip_address, :framework_env
4
4
  child :account do
5
5
  attributes :id, :name
6
6
  end
@@ -1,4 +1,4 @@
1
- attributes :id, :ssh_username, :name, :instances_count, :app_server_stack_name, :load_balancer_ip_address, :framework_env
1
+ attributes :id, :ssh_username, :name, :instances_count, :instance_status, :app_server_stack_name, :load_balancer_ip_address, :framework_env
2
2
  child :account do
3
3
  attributes :id, :name
4
4
  end
@@ -1,5 +1,5 @@
1
1
  collection @environments, :root => :environments, :object_root => false
2
- attributes :id, :ssh_username, :name, :instances_count, :app_server_stack_name, :load_balancer_ip_address, :framework_env
2
+ attributes :id, :ssh_username, :name, :instances_count, :instance_status, :app_server_stack_name, :load_balancer_ip_address, :framework_env
3
3
  child :account do
4
4
  attributes :id, :name
5
5
  end
@@ -2,7 +2,6 @@ require 'multi_json'
2
2
  require 'engineyard-cloud-client/rest_client_ext'
3
3
  require 'engineyard-cloud-client/test'
4
4
  require 'engineyard-cloud-client/test/fake_awsm'
5
- require 'engineyard-cloud-client/test/ui'
6
5
 
7
6
  module EY::CloudClient::Test
8
7
  class Scenario
@@ -32,8 +31,8 @@ module EY::CloudClient::Test
32
31
  @api_token = options['api_token']
33
32
  end
34
33
 
35
- def cloud_client(ui = EY::CloudClient::Test::UI.new)
36
- EY::CloudClient.new(@api_token, ui)
34
+ def cloud_client
35
+ EY::CloudClient.new(:endpoint => EY::CloudClient::Test::FakeAwsm.uri, :token => @api_token)
37
36
  end
38
37
 
39
38
  def inspect
@@ -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.3'
4
+ VERSION = '1.0.4'
5
5
  end
6
6
  end
7
7
  # Please be aware that the monkeys like tho throw poo sometimes.
@@ -2,50 +2,32 @@ require 'spec_helper'
2
2
 
3
3
  describe EY::CloudClient do
4
4
  it "holds an api token" do
5
- EY::CloudClient.new('asdf', test_ui).token.should == "asdf"
5
+ EY::CloudClient.new(:token => 'asdf').connection.token.should == "asdf"
6
6
  end
7
7
 
8
- it "holds a UI" do
9
- EY::CloudClient.new('asdf', test_ui).ui.should == test_ui
8
+ it "uses production EY Cloud by default" do
9
+ FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :body => %|{"api_token": "cloudtoken"}|, :content_type => 'application/json')
10
+ client = EY::CloudClient.new
11
+ client.authenticate!("a@b.com", "foo")
12
+ client.connection.token.should == "cloudtoken"
10
13
  end
11
14
 
12
- describe ".endpoint" do
13
- after do
14
- EY::CloudClient.default_endpoint!
15
- end
16
-
17
- it "defaults to production EY Cloud" do
18
- EY::CloudClient.endpoint.should == URI.parse('https://cloud.engineyard.com')
19
- end
20
-
21
- it "accepts a valid endpoint" do
22
- EY::CloudClient.endpoint = "http://fake.local/"
23
- EY::CloudClient.endpoint.should == URI.parse('http://fake.local')
24
- end
25
-
26
- it "uses the endpoint to make requests" do
27
- FakeWeb.register_uri(:post, "http://fake.local/api/v2/authenticate", :body => %|{"api_token": "fake.localtoken"}|, :content_type => 'application/json')
28
-
29
- EY::CloudClient.endpoint = "http://fake.local/"
30
- EY::CloudClient.authenticate("a@b.com", "foo", test_ui).should == "fake.localtoken"
31
- end
32
-
33
- it "raises on an invalid endpoint" do
34
- lambda { EY::CloudClient.endpoint = "non/absolute" }.should raise_error(EY::CloudClient::BadEndpointError)
35
- end
15
+ it "uses a custom endpoint to make requests" do
16
+ FakeWeb.register_uri(:post, "http://fake.local/api/v2/authenticate", :body => %|{"api_token": "fake.localtoken"}|, :content_type => 'application/json')
17
+ client = EY::CloudClient.new(:endpoint => "http://fake.local/")
18
+ client.authenticate!("a@b.com", "foo")
19
+ client.connection.token.should == "fake.localtoken"
36
20
  end
37
21
 
38
- it "authenticates with valid credentials and returns the api token" do
39
- FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :body => %|{"api_token": "asdf"}|, :content_type => 'application/json')
40
-
41
- EY::CloudClient.authenticate("a@b.com", "foo", test_ui).should == "asdf"
22
+ it "raises on an invalid endpoint" do
23
+ lambda { EY::CloudClient.new(:endpoint => "non/absolute") }.should raise_error(EY::CloudClient::BadEndpointError)
42
24
  end
43
25
 
44
26
  it "raises InvalidCredentials when the credentials are invalid" do
45
27
  FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :status => 401, :content_type => 'application/json')
46
28
 
47
29
  lambda {
48
- EY::CloudClient.authenticate("a@b.com", "foo", test_ui)
30
+ EY::CloudClient.new.authenticate!("a@b.com", "foo")
49
31
  }.should raise_error(EY::CloudClient::InvalidCredentials)
50
32
  end
51
33
 
@@ -53,7 +35,7 @@ describe EY::CloudClient do
53
35
  FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :status => 502, :content_type => 'text/html')
54
36
 
55
37
  lambda {
56
- EY::CloudClient.authenticate("a@b.com", "foo", test_ui)
38
+ EY::CloudClient.new.authenticate!("a@b.com", "foo")
57
39
  }.should raise_error(EY::CloudClient::RequestFailed, /API is temporarily unavailable/)
58
40
  end
59
41
  end
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe EY::CloudClient::Account do
4
4
  before do
5
5
  FakeWeb.allow_net_connect = true
6
- EY::CloudClient.endpoint = EY::CloudClient::Test::FakeAwsm.uri
7
6
  end
8
7
 
9
8
  describe ".all" do
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe EY::CloudClient::AppEnvironment do
4
4
  before(:each) do
5
5
  FakeWeb.allow_net_connect = true
6
- EY::CloudClient.endpoint = EY::CloudClient::Test::FakeAwsm.uri
7
6
  end
8
7
 
9
8
  describe ".resolve" do
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe EY::CloudClient::App do
4
4
  before(:each) do
5
5
  FakeWeb.allow_net_connect = true
6
- EY::CloudClient.endpoint = EY::CloudClient::Test::FakeAwsm.uri
7
6
  end
8
7
 
9
8
  describe ".all" do
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe EY::CloudClient::AppEnvironment do
4
4
  before(:each) do
5
5
  FakeWeb.allow_net_connect = true
6
- EY::CloudClient.endpoint = EY::CloudClient::Test::FakeAwsm.uri
7
6
  end
8
7
 
9
8
  describe "deploying" do
@@ -31,7 +30,7 @@ describe EY::CloudClient::AppEnvironment do
31
30
 
32
31
  deployment.created_at.should_not be_nil
33
32
  deployment.finished_at.should be_nil
34
- deployment.config.should == {'deployed_by' => 'Multiple Ambiguous Accounts', 'extra' => 'config'}
33
+ deployment.config.should == {'input_ref' => 'master', 'deployed_by' => 'Multiple Ambiguous Accounts', 'extra' => 'config'}
35
34
  deployment.commit.should =~ /[0-9a-f]{40}/
36
35
  deployment.resolved_ref.should_not be_nil
37
36
  deployment.out << "Test output"
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe EY::CloudClient::Environment do
4
4
  before(:each) do
5
5
  FakeWeb.allow_net_connect = true
6
- EY::CloudClient.endpoint = EY::CloudClient::Test::FakeAwsm.uri
7
6
  end
8
7
 
9
8
  describe ".all" do
@@ -3,16 +3,13 @@ require 'spec_helper'
3
3
  describe EY::CloudClient::User do
4
4
  before do
5
5
  FakeWeb.allow_net_connect = true
6
- EY::CloudClient.endpoint = EY::CloudClient::Test::FakeAwsm.uri
7
6
  end
8
7
 
9
- describe ".all" do
10
- it "returns all accounts" do
11
- api = scenario_cloud_client "User Name"
12
- user = api.current_user
13
- user.name.should == 'User Name'
14
- user.accounts.size.should == 1
15
- user.accounts.first.name.should == 'main'
16
- end
8
+ it "loads current user and returns all accounts" do
9
+ api = scenario_cloud_client "User Name"
10
+ user = api.current_user
11
+ user.name.should == 'User Name'
12
+ user.accounts.size.should == 1
13
+ user.accounts.first.name.should == 'main'
17
14
  end
18
15
  end
data/spec/spec_helper.rb CHANGED
@@ -44,7 +44,4 @@ RSpec.configure do |config|
44
44
  FakeWeb.allow_net_connect = false
45
45
  end
46
46
 
47
- config.before(:each) do
48
- EY::CloudClient.default_endpoint!
49
- end
50
47
  end
@@ -1,12 +1,8 @@
1
1
  require 'rest_client'
2
2
 
3
3
  module SpecHelpers
4
- def test_ui
5
- @test_ui ||= EY::CloudClient::Test::UI.new
6
- end
7
-
8
- def cloud_client(token = 'asdf', ui = test_ui)
9
- @cloud_client ||= EY::CloudClient.new(token, ui)
4
+ def cloud_client(token = 'asdf')
5
+ @cloud_client ||= EY::CloudClient.new(:token => token)
10
6
  end
11
7
 
12
8
  def scenario_cloud_client(scenario)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: engineyard-cloud-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-13 00:00:00.000000000 Z
12
+ date: 2012-08-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -160,17 +160,17 @@ dependencies:
160
160
  requirement: !ruby/object:Gem::Requirement
161
161
  none: false
162
162
  requirements:
163
- - - ! '>='
163
+ - - ~>
164
164
  - !ruby/object:Gem::Version
165
- version: '0'
165
+ version: 1.2.0
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  none: false
170
170
  requirements:
171
- - - ! '>='
171
+ - - ~>
172
172
  - !ruby/object:Gem::Version
173
- version: '0'
173
+ version: 1.2.0
174
174
  - !ruby/object:Gem::Dependency
175
175
  name: dm-migrations
176
176
  requirement: !ruby/object:Gem::Requirement
@@ -273,6 +273,7 @@ executables: []
273
273
  extensions: []
274
274
  extra_rdoc_files: []
275
275
  files:
276
+ - lib/engineyard-cloud-client/connection.rb
276
277
  - lib/engineyard-cloud-client/errors.rb
277
278
  - lib/engineyard-cloud-client/model_registry.rb
278
279
  - lib/engineyard-cloud-client/models/account.rb
@@ -312,7 +313,6 @@ files:
312
313
  - lib/engineyard-cloud-client/test/fake_awsm/views/user.rabl
313
314
  - lib/engineyard-cloud-client/test/fake_awsm.rb
314
315
  - lib/engineyard-cloud-client/test/scenario.rb
315
- - lib/engineyard-cloud-client/test/ui.rb
316
316
  - lib/engineyard-cloud-client/test.rb
317
317
  - lib/engineyard-cloud-client/version.rb
318
318
  - lib/engineyard-cloud-client.rb
@@ -348,7 +348,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
348
348
  version: '0'
349
349
  segments:
350
350
  - 0
351
- hash: -4133734354650536829
351
+ hash: 2753056383473924638
352
352
  required_rubygems_version: !ruby/object:Gem::Requirement
353
353
  none: false
354
354
  requirements:
@@ -357,7 +357,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
357
357
  version: '0'
358
358
  segments:
359
359
  - 0
360
- hash: -4133734354650536829
360
+ hash: 2753056383473924638
361
361
  requirements: []
362
362
  rubyforge_project:
363
363
  rubygems_version: 1.8.24
@@ -1,33 +0,0 @@
1
- require 'engineyard-cloud-client/test'
2
-
3
- module EY::CloudClient::Test
4
- class QuietUI
5
- def info(*)
6
- end
7
-
8
- def debug(*)
9
- end
10
- end
11
-
12
- class VerboseUI
13
- def info(name, message = nil)
14
- say name, message
15
- end
16
-
17
- def debug(name, message = nil)
18
- name = name.inspect unless name.nil? or name.is_a?(String)
19
- message = message.inspect unless message.nil? or message.is_a?(String)
20
- say name, message
21
- end
22
-
23
- def say(status, message = nil)
24
- if message
25
- $stdout.puts "#{status.to_s.rjust(12)} #{message}"
26
- else
27
- $stdout.puts status
28
- end
29
- end
30
- end
31
-
32
- UI = ENV['DEBUG'] ? VerboseUI : QuietUI
33
- end