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