engineyard-cloud-client 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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