engineyard-cloud-client 1.0.2 → 1.0.3

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.
@@ -1,7 +1,130 @@
1
- = engineyard-cloud-client
1
+ = Engine Yard Cloud Client
2
2
 
3
- The API client for awsm. Extracted from the engineyard gem because this piece is often all a project needs for EY Cloud API usage.
3
+ engineyard-cloud-client contains a Ruby api library to the Engine Yard Cloud API. Extracted from the engineyard gem.
4
4
 
5
- See engineyard gem for a usage example. Bother someone if this is released and the documentation is still not updated.
5
+ Setup:
6
+
7
+ require 'engineyard-cloud-client'
8
+ require 'engineyard-cloud-client/test'
9
+
10
+ token = EY::CloudClient.authenticate("your@email.com", "password")
11
+ ui = EY::CloudClient::Test::VerboseUI.new
12
+ # Test::VerboseUI is used in this example for simplicity.
13
+ # You may substitute your own ui object with #debug and #info methods
14
+
15
+ ey_api = EY::CloudClient.new(token, ui)
16
+
17
+ Current User:
18
+
19
+ user = ey_api.current_user
20
+ user.class # => EY::CloudClient::User
21
+ user.name # => "Your Name"
22
+ user.email # => "your@email.com"
23
+
24
+ Apps:
25
+
26
+ apps = ey_api.apps # loads all your app data at once; caches result
27
+
28
+ app = apps.find {|app| app.name == 'myapp'}
29
+ app.class # => EY::CloudClient::App
30
+ app.name # => 'myapp'
31
+ app.id # => 123
32
+ app.repository_uri # => git@github.com:myaccount/myapp.git
33
+
34
+ app.account.class # => EY::CloudClient::Account
35
+
36
+ app.app_environments.first.class # => EY::CloudClient::AppEnvironment
37
+ app.app_environments.map {|e| e.environment.name} # => ['myapp_production', 'myapp_staging']
38
+
39
+ Create a new application (to be booted within Environments):
40
+
41
+ account = EY::CloudClient::Account.new(ey_api, {:id => 4212, :name => 'drnic'})
42
+ app = EY::CloudClient::App.create(ey_api,
43
+ "account" => account
44
+ "name" => "myapp",
45
+ "repository_uri" => "git@github.com:mycompany/myapp.git",
46
+ "app_type_id" => "rails3",
47
+ })
48
+
49
+ Valid `app_type_id` are: `rack, rails2, rails3, rails4, sinatra, nodejs`. For some your account may require an early access feature to be enabled.
50
+
51
+ Accounts:
52
+
53
+ account = app.account
54
+ account.class # => EY::CloudClient::Account
55
+ account.id # => 1234
56
+ account.name # => 'myaccount'
57
+
58
+ Keypairs:
59
+
60
+ Upload your SSH public keys before you create Environments.
61
+
62
+ keypair = EY::CloudClient::Keypair.create(ey_api, {
63
+ "name" => 'laptop',
64
+ "public_key" => "ssh-rsa OTHERKEYPAIR"
65
+ })
66
+
67
+ Environments:
68
+
69
+ envs = ey_api.environments # loads all your environment data at once; caches result
70
+
71
+ env = envs.find {|e| e.name == 'myapp_production'}
72
+ env.class # => EY::CloudClient::Environment
73
+ env.name # => 'myapp_production'
74
+ env.id # => 2345
75
+ env.framework_env # => "production"
76
+ env.app_server_stack_name # => "nginx_thin"
77
+ env.deployment_configurations # => {"myapp"=>{"name"=>"myapp", "uri"=>nil, "migrate"=>{"command"=>"rake db:migrate", "perform"=>false}, "repository_uri"=>"git@github.com:myaccount/myapp.git", "id"=>123, "domain_name"=>"_"}}
78
+ env.load_balancer_ip_address # => "1.2.3.4"
79
+
80
+ # if environment isn't booted
81
+ env.instances_count # => 0
82
+ env.app_master # => nil
83
+ env.instances.count # => []
84
+
85
+ # if environment is booted
86
+ env.instances_count # => 1
87
+ env.app_master.class # => EY::CloudClient::Instance
88
+ env.instances.first.class # => EY::CloudClient::Instance
89
+
90
+ Create a new environment (for a given App):
91
+
92
+ app = EY::CloudClient::App.new(ey_api, {:id => 4212, :name => 'drnic'})
93
+ env = EY::CloudClient::Environment.create(ey_api,
94
+ "app" => app,
95
+ "name" => 'myapp_production',
96
+ "app_server_stack_name" => 'nginx_thin', # default: nginx_passenger3
97
+ "region" => 'us-west-1', # default: us-east-1
98
+ "framework_env" => 'staging' # default: production
99
+ })
100
+
101
+
102
+ Valid `app_server_stack_name` values: `nginx_unicorn, nginx_passenger3, nginx_nodejs, nginx_thin, nginx_puma`. For some your account may require an early access feature to be enabled.
103
+
104
+ Instances:
105
+
106
+ instance = env.instances.first
107
+ instance.class # => EY::CloudClient::Instance
108
+ instance.id # => 12345
109
+ instance.role # => "solo"
110
+ instance.status # => "running"
111
+ instance.amazon_id # => "i-abcdefg"
112
+ instance.hostname # => "ec2-1-2-3-4.compute-1.amazonaws.com"
113
+ instance.public_hostname # => "ec2-1-2-3-4.compute-1.amazonaws.com" # alias of hostname
114
+
115
+ == Debugging:
116
+
117
+ When $DEBUG is set, display debug information to the ui object using the #debug method. The API commands will print internal request information:
118
+
119
+ app = EY::CloudClient::App.create(ey_api, 'account' => account, 'name' => 'myapp2', 'repository_uri' => 'git@github.com:myaccount/myapp2.git', 'app_type_id' => 'rails3')
120
+ Token YOURTOKEN
121
+ Request POST https://cloud.engineyard.com/api/v2/accounts/1234/apps
122
+ Params {"app"=>{"name"=>"myapp2", "app_type_id"=>"rails3", "repository_uri"=>"git@github.com:myaccount/myapp2.git"}}
123
+ Response
124
+ {"app"=>
125
+ {"environments"=>[],
126
+ "name"=>"myapp2",
127
+ "repository_uri"=>"git@github.com:myaccount/myapp2.git",
128
+ "account"=>{"name"=>"myaccount", "id"=>1234},
129
+ "id"=>12345}}
6
130
 
7
- This is currently unreleased.
@@ -127,7 +127,7 @@ module EY
127
127
  data = ''
128
128
  elsif resp.headers[:content_type] =~ /application\/json/
129
129
  begin
130
- data = MultiJson.decode(resp.body)
130
+ data = MultiJson.load(resp.body)
131
131
  ui.debug("Response", "\n" + data.pretty_inspect)
132
132
  rescue MultiJson::DecodeError
133
133
  ui.debug("Raw response", resp.body)
@@ -12,8 +12,8 @@ module EY
12
12
  end
13
13
 
14
14
  def set(klass, obj)
15
- if obj.respond_to?(:id) && id = obj.id
16
- @registry[klass][id] = obj
15
+ if obj.respond_to?(:id) && obj.id
16
+ @registry[klass][obj.id] = obj
17
17
  end
18
18
  end
19
19
  end
@@ -53,6 +53,16 @@ module EY
53
53
  existing_app_env || app_env
54
54
  end
55
55
 
56
+ def attributes=(attrs)
57
+ account_attrs = attrs.delete('account')
58
+ environments_attrs = attrs.delete('environments')
59
+ super
60
+ set_account account_attrs if account_attrs
61
+ set_environments environments_attrs if environments_attrs
62
+ end
63
+
64
+ protected
65
+
56
66
  def set_account(account_attrs)
57
67
  @account = Account.from_hash(api, account_attrs)
58
68
  @account.add_app(self)
@@ -64,14 +74,6 @@ module EY
64
74
  AppEnvironment.from_hash(api, {'app' => self, 'environment' => env})
65
75
  end
66
76
  end
67
-
68
- def attributes=(attrs)
69
- account_attrs = attrs.delete('account')
70
- environments_attrs = attrs.delete('environments')
71
- super
72
- set_account account_attrs if account_attrs
73
- set_environments environments_attrs if environments_attrs
74
- end
75
77
  end
76
78
  end
77
79
  end
@@ -27,18 +27,6 @@ module EY
27
27
  raise ArgumentError, 'AppEnvironment created without environment!' unless environment
28
28
  end
29
29
 
30
- def set_app(app_or_hash)
31
- self.app = App.from_hash(api, app_or_hash)
32
- app.add_app_environment(self)
33
- app
34
- end
35
-
36
- def set_environment(env_or_hash)
37
- self.environment = Environment.from_hash(api, env_or_hash)
38
- environment.add_app_environment(self)
39
- environment
40
- end
41
-
42
30
  def attributes=(attrs)
43
31
  app_attrs = attrs.delete('app')
44
32
  environment_attrs = attrs.delete('environment')
@@ -75,6 +63,20 @@ module EY
75
63
  Deployment.from_hash(api, attrs.merge(:app_environment => self))
76
64
  end
77
65
 
66
+ protected
67
+
68
+ def set_app(app_or_hash)
69
+ self.app = App.from_hash(api, app_or_hash)
70
+ app.add_app_environment(self)
71
+ app
72
+ end
73
+
74
+ def set_environment(env_or_hash)
75
+ self.environment = Environment.from_hash(api, env_or_hash)
76
+ environment.add_app_environment(self)
77
+ environment
78
+ end
79
+
78
80
  end
79
81
  end
80
82
  end
@@ -1,6 +1,6 @@
1
1
  require 'engineyard-cloud-client/models'
2
+ require 'engineyard-cloud-client/models/recipes'
2
3
  require 'engineyard-cloud-client/errors'
3
- require 'tempfile'
4
4
 
5
5
  module EY
6
6
  class CloudClient
@@ -8,59 +8,6 @@ module EY
8
8
  :username, :app_server_stack_name,
9
9
  :load_balancer_ip_address
10
10
  )
11
- attr_accessor :apps, :account
12
-
13
- def attributes=(attrs)
14
- account_attrs = attrs.delete('account')
15
- apps_attrs = attrs.delete('apps')
16
- instances_attrs = attrs.delete('instances')
17
-
18
- super
19
-
20
- set_account account_attrs if account_attrs
21
- set_apps apps_attrs if apps_attrs
22
- set_instances instances_attrs if instances_attrs
23
- end
24
-
25
- def add_app_environment(app_env)
26
- @app_environments ||= []
27
- existing_app_env = @app_environments.detect { |ae| app_env.environment == ae.environment }
28
- unless existing_app_env
29
- @app_environments << app_env
30
- end
31
- existing_app_env || app_env
32
- end
33
-
34
- def app_environments
35
- @app_environments ||= []
36
- end
37
-
38
- def set_account(account_attrs)
39
- @account = Account.from_hash(api, account_attrs)
40
- @account.add_environment(self)
41
- @account
42
- end
43
-
44
- # Creating an AppEnvironment will come back and call add_app_environment
45
- # (above) to associate this model with the AppEnvironment. (that's why we
46
- # don't save anything here.)
47
- def set_apps(apps_attrs)
48
- (apps_attrs || []).each do |app|
49
- AppEnvironment.from_hash(api, {'app' => app, 'environment' => self})
50
- end
51
- end
52
-
53
- def apps
54
- app_environments.map { |app_env| app_env.app }
55
- end
56
-
57
- def set_instances(instances_attrs)
58
- @instances = load_instances(instances_attrs)
59
- end
60
-
61
- def instances
62
- @instances ||= request_instances
63
- end
64
11
 
65
12
  # Return list of all Environments linked to all current user's accounts
66
13
  def self.all(api)
@@ -108,6 +55,40 @@ module EY
108
55
  response = api.request("/apps/#{app.id}/environments", :method => :post, :params => params)
109
56
  self.from_hash(api, response['environment'])
110
57
  end
58
+ attr_accessor :apps, :account
59
+
60
+ def attributes=(attrs)
61
+ account_attrs = attrs.delete('account')
62
+ apps_attrs = attrs.delete('apps')
63
+ instances_attrs = attrs.delete('instances')
64
+
65
+ super
66
+
67
+ set_account account_attrs if account_attrs
68
+ set_apps apps_attrs if apps_attrs
69
+ set_instances instances_attrs if instances_attrs
70
+ end
71
+
72
+ def add_app_environment(app_env)
73
+ @app_environments ||= []
74
+ existing_app_env = @app_environments.detect { |ae| app_env.environment == ae.environment }
75
+ unless existing_app_env
76
+ @app_environments << app_env
77
+ end
78
+ existing_app_env || app_env
79
+ end
80
+
81
+ def app_environments
82
+ @app_environments ||= []
83
+ end
84
+
85
+ def apps
86
+ app_environments.map { |app_env| app_env.app }
87
+ end
88
+
89
+ def instances
90
+ @instances ||= request_instances
91
+ end
111
92
 
112
93
  def account_name
113
94
  account && account.name
@@ -144,51 +125,61 @@ module EY
144
125
  end
145
126
  alias rebuild update
146
127
 
128
+ def recipes
129
+ Recipes.new(api, self)
130
+ end
131
+
132
+ # See Recipes#run
147
133
  def run_custom_recipes
148
- api.request("/environments/#{id}/run_custom_recipes", :method => :put)
149
- true
134
+ recipes.run
150
135
  end
151
136
 
137
+ # See Recipes#download
152
138
  def download_recipes
153
- tmp = Tempfile.new("recipes")
154
- data = api.request("/environments/#{id}/recipes")
155
- tmp.write(data)
156
- tmp.flush
157
- tmp.close
158
- tmp
139
+ recipes.download
159
140
  end
160
141
 
142
+ # See Recipes#upload_path
161
143
  def upload_recipes_at_path(recipes_path)
162
- recipes_path = Pathname.new(recipes_path)
163
- if recipes_path.exist?
164
- upload_recipes recipes_path.open('rb')
165
- else
166
- raise EY::CloudClient::Error, "Recipes file not found: #{recipes_path}"
167
- end
144
+ recipes.upload_path(recipes_path)
168
145
  end
169
146
 
170
- # Expects a File object opened for binary reading.
171
- # i.e. File.open(path, 'rb')
147
+ # See Recipes#upload
172
148
  def upload_recipes(file_to_upload)
173
- api.request("/environments/#{id}/recipes", {
174
- :method => :post,
175
- :params => {:file => file_to_upload}
176
- })
177
- true
149
+ recipes.upload(file_to_upload)
178
150
  end
179
151
 
180
152
  def shorten_name_for(app)
181
153
  name.gsub(/^#{Regexp.quote(app.name)}_/, '')
182
154
  end
183
155
 
184
- private
156
+ protected
157
+
158
+ def set_account(account_attrs)
159
+ @account = Account.from_hash(api, account_attrs)
160
+ @account.add_environment(self)
161
+ @account
162
+ end
163
+
164
+ # Creating an AppEnvironment will come back and call add_app_environment
165
+ # (above) to associate this model with the AppEnvironment. (that's why we
166
+ # don't save anything here.)
167
+ def set_apps(apps_attrs)
168
+ (apps_attrs || []).each do |app|
169
+ AppEnvironment.from_hash(api, {'app' => app, 'environment' => self})
170
+ end
171
+ end
172
+
173
+ def set_instances(instances_attrs)
174
+ @instances = load_instances(instances_attrs)
175
+ end
185
176
 
186
177
  def request_instances
187
- if instances_count > 0
178
+ if instances_count.zero?
179
+ []
180
+ else
188
181
  instances_attrs = api.request("/environments/#{id}/instances")["instances"]
189
182
  load_instances(instances_attrs)
190
- else
191
- []
192
183
  end
193
184
  end
194
185
 
@@ -0,0 +1,49 @@
1
+ require 'tempfile'
2
+ require 'engineyard-cloud-client/errors'
3
+
4
+ module EY
5
+ class CloudClient
6
+ class Recipes
7
+ attr_reader :api, :environment
8
+
9
+ def initialize(api, environment)
10
+ @api = api
11
+ @environment = environment
12
+ end
13
+
14
+ def run
15
+ api.request("/environments/#{environment.id}/run_custom_recipes", :method => :put)
16
+ true
17
+ end
18
+
19
+ def download
20
+ tmp = Tempfile.new("recipes")
21
+ data = api.request("/environments/#{environment.id}/recipes")
22
+ tmp.write(data)
23
+ tmp.flush
24
+ tmp.close
25
+ tmp
26
+ end
27
+
28
+ def upload_path(recipes_path)
29
+ recipes_path = Pathname.new(recipes_path)
30
+ if recipes_path.exist?
31
+ upload recipes_path.open('rb')
32
+ else
33
+ raise EY::CloudClient::Error, "Recipes file not found: #{recipes_path}"
34
+ end
35
+ end
36
+
37
+ # Expects a File object opened for binary reading.
38
+ # i.e. upload(File.open(recipes_path, 'rb'))
39
+ def upload(file_to_upload)
40
+ api.request("/environments/#{environment.id}/recipes", {
41
+ :method => :post,
42
+ :params => {:file => file_to_upload}
43
+ })
44
+ true
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -16,7 +16,7 @@ module EY::CloudClient::Test
16
16
 
17
17
  def self.load_scenarios
18
18
  response = ::RestClient.get(EY::CloudClient::Test::FakeAwsm.uri.sub(/\/?$/,'/scenarios'))
19
- data = MultiJson.decode(response)
19
+ data = MultiJson.load(response)
20
20
  data['scenarios'].inject({}) do |hsh, scenario|
21
21
  hsh[scenario['name']] = new(scenario)
22
22
  hsh
@@ -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.2'
4
+ VERSION = '1.0.3'
5
5
  end
6
6
  end
7
7
  # Please be aware that the monkeys like tho throw poo sometimes.
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.2
4
+ version: 1.0.3
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-05-29 00:00:00.000000000 Z
12
+ date: 2012-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -284,6 +284,7 @@ files:
284
284
  - lib/engineyard-cloud-client/models/instance.rb
285
285
  - lib/engineyard-cloud-client/models/keypair.rb
286
286
  - lib/engineyard-cloud-client/models/log.rb
287
+ - lib/engineyard-cloud-client/models/recipes.rb
287
288
  - lib/engineyard-cloud-client/models/user.rb
288
289
  - lib/engineyard-cloud-client/models.rb
289
290
  - lib/engineyard-cloud-client/resolver_result.rb
@@ -347,7 +348,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
347
348
  version: '0'
348
349
  segments:
349
350
  - 0
350
- hash: 551294076899789604
351
+ hash: -4133734354650536829
351
352
  required_rubygems_version: !ruby/object:Gem::Requirement
352
353
  none: false
353
354
  requirements:
@@ -356,7 +357,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
356
357
  version: '0'
357
358
  segments:
358
359
  - 0
359
- hash: 551294076899789604
360
+ hash: -4133734354650536829
360
361
  requirements: []
361
362
  rubyforge_project:
362
363
  rubygems_version: 1.8.24