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.
- data/README.rdoc +127 -4
- data/lib/engineyard-cloud-client.rb +1 -1
- data/lib/engineyard-cloud-client/model_registry.rb +2 -2
- data/lib/engineyard-cloud-client/models/app.rb +10 -8
- data/lib/engineyard-cloud-client/models/app_environment.rb +14 -12
- data/lib/engineyard-cloud-client/models/environment.rb +70 -79
- data/lib/engineyard-cloud-client/models/recipes.rb +49 -0
- data/lib/engineyard-cloud-client/test/scenario.rb +1 -1
- data/lib/engineyard-cloud-client/version.rb +1 -1
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -1,7 +1,130 @@
|
|
1
|
-
=
|
1
|
+
= Engine Yard Cloud Client
|
2
2
|
|
3
|
-
|
3
|
+
engineyard-cloud-client contains a Ruby api library to the Engine Yard Cloud API. Extracted from the engineyard gem.
|
4
4
|
|
5
|
-
|
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.
|
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)
|
@@ -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
|
-
|
149
|
-
true
|
134
|
+
recipes.run
|
150
135
|
end
|
151
136
|
|
137
|
+
# See Recipes#download
|
152
138
|
def download_recipes
|
153
|
-
|
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
|
-
|
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
|
-
#
|
171
|
-
# i.e. File.open(path, 'rb')
|
147
|
+
# See Recipes#upload
|
172
148
|
def upload_recipes(file_to_upload)
|
173
|
-
|
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
|
-
|
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
|
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.
|
19
|
+
data = MultiJson.load(response)
|
20
20
|
data['scenarios'].inject({}) do |hsh, scenario|
|
21
21
|
hsh[scenario['name']] = new(scenario)
|
22
22
|
hsh
|
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.
|
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-
|
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:
|
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:
|
360
|
+
hash: -4133734354650536829
|
360
361
|
requirements: []
|
361
362
|
rubyforge_project:
|
362
363
|
rubygems_version: 1.8.24
|