engineyard-cloud-client 1.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.md +46 -0
- data/{README.rdoc → README.md} +26 -3
- data/lib/engineyard-cloud-client/models/app_environment.rb +16 -0
- data/lib/engineyard-cloud-client/models/deployment.rb +24 -0
- data/lib/engineyard-cloud-client/models/environment.rb +6 -2
- data/lib/engineyard-cloud-client/models/instance.rb +7 -0
- data/lib/engineyard-cloud-client/test/fake_awsm.rb +1 -1
- data/lib/engineyard-cloud-client/test/fake_awsm/config.ru +22 -22
- data/lib/engineyard-cloud-client/test/fake_awsm/models/deployment.rb +19 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/scenario.rabl +2 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/scenarios.rabl +2 -0
- data/lib/engineyard-cloud-client/version.rb +1 -1
- data/spec/engineyard-cloud-client/integration/deployment_spec.rb +29 -0
- data/spec/spec_helper.rb +1 -1
- metadata +12 -25
data/ChangeLog.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# ChangeLog
|
2
|
+
|
3
|
+
## NEXT
|
4
|
+
|
5
|
+
*
|
6
|
+
|
7
|
+
## v1.0.8 (2013-02-14)
|
8
|
+
|
9
|
+
* Loosen the multi\_json gem version requirement to allow 1.0 compatible security fixes.
|
10
|
+
|
11
|
+
## v1.0.7 (2012-10-25)
|
12
|
+
|
13
|
+
* Send serverside\_version to the deployment API when starting a deploy.
|
14
|
+
|
15
|
+
## v1.0.6 (2012-08-20)
|
16
|
+
|
17
|
+
*
|
18
|
+
|
19
|
+
## v1.0.5 (2012-08-14)
|
20
|
+
|
21
|
+
*
|
22
|
+
|
23
|
+
## v1.0.4 (2012-08-14)
|
24
|
+
|
25
|
+
* Send input\_ref to deployments in the extra config.
|
26
|
+
* Use Connection object to take over for all api communication, simplifying the CloudClient class.
|
27
|
+
* Interface for creating a CloudClient has changed to support new Connection class.
|
28
|
+
|
29
|
+
## v1.0.3 (2012-06-13)
|
30
|
+
|
31
|
+
*
|
32
|
+
|
33
|
+
## v1.0.2 (2012-05-29)
|
34
|
+
|
35
|
+
*
|
36
|
+
|
37
|
+
## v1.0.1 (2012-05-22)
|
38
|
+
|
39
|
+
* Includes fixes for deployment test harness used by this gem and engineyard gem
|
40
|
+
|
41
|
+
## v1.0.0 (2012-05-22)
|
42
|
+
|
43
|
+
* First attempt at a real release.
|
44
|
+
* Provides all the functionality that is needed for engineyard gem to operate.
|
45
|
+
* Like Torchwood, The Colbert Report, and The Cleveland Show, start CloudClient's new life as a spin-off.
|
46
|
+
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,6 +1,29 @@
|
|
1
|
-
|
1
|
+
# Engine Yard Cloud Client
|
2
2
|
|
3
|
-
engineyard-cloud-client contains a Ruby api library to the Engine Yard Cloud API. Extracted from the engineyard gem.
|
3
|
+
engineyard-cloud-client contains a Ruby api library to the Engine Yard Cloud API. Extracted from the [engineyard gem](https://github.com/engineyard/engineyard).
|
4
|
+
|
5
|
+
## Use at your own risk
|
6
|
+
|
7
|
+
At this time, cloud-client is not documented for public use. It was created to
|
8
|
+
be used by the engineyard gem with the hopes of eventually providing a public
|
9
|
+
api client, but it's still in its infancy.
|
10
|
+
|
11
|
+
If you would like to use this gem directly instead of interfacing with the
|
12
|
+
engineyard gem, you will likely be on your own. We may be available to answer
|
13
|
+
questions about the gem, but the gem itself is not currently a supported public
|
14
|
+
interface to Engine Yard Cloud.
|
15
|
+
|
16
|
+
This gem accesses API actions that can alter your dashboard and settings. If
|
17
|
+
used incorrectly, it could lead to problems. As we work towards making this a
|
18
|
+
reliable public client, the interface may change.
|
19
|
+
|
20
|
+
If you intend to use this gem, please lock to an exact version and pay close
|
21
|
+
attention to newly released versions and changes to the interface.
|
22
|
+
|
23
|
+
Please [open github issues](https://github.com/engineyard/engineyard-cloud-client/issues)
|
24
|
+
for any problems you encounter.
|
25
|
+
|
26
|
+
## Usage
|
4
27
|
|
5
28
|
Setup:
|
6
29
|
|
@@ -112,7 +135,7 @@ Instances:
|
|
112
135
|
instance.hostname # => "ec2-1-2-3-4.compute-1.amazonaws.com"
|
113
136
|
instance.public_hostname # => "ec2-1-2-3-4.compute-1.amazonaws.com" # alias of hostname
|
114
137
|
|
115
|
-
|
138
|
+
## Debugging:
|
116
139
|
|
117
140
|
When $DEBUG is set, display debug information to the ui object using the #debug method. The API commands will print internal request information:
|
118
141
|
|
@@ -62,10 +62,26 @@ module EY
|
|
62
62
|
Deployment.last(api, self)
|
63
63
|
end
|
64
64
|
|
65
|
+
# Create a new, unsaved, Deployment record.
|
66
|
+
#
|
67
|
+
# Call start on the return object to indicate to EY Cloud that you
|
68
|
+
# will be starting a deployment using your own connection to your
|
69
|
+
# servers. This is the way that the engineyard gem does deployments.
|
65
70
|
def new_deployment(attrs)
|
66
71
|
Deployment.from_hash(api, attrs.merge(:app_environment => self))
|
67
72
|
end
|
68
73
|
|
74
|
+
# Trigger a deployment on the api side.
|
75
|
+
#
|
76
|
+
# This is like hitting the deploy button on the web interface.
|
77
|
+
#
|
78
|
+
# Returns a started deployment that will run from EY Cloud automatically.
|
79
|
+
# Load the deployment again to see when it finishes. This action returns
|
80
|
+
# immediately before the deployment is complete.
|
81
|
+
def deploy(attrs)
|
82
|
+
Deployment.deploy(api, self, attrs)
|
83
|
+
end
|
84
|
+
|
69
85
|
protected
|
70
86
|
|
71
87
|
def set_app(app_or_hash)
|
@@ -27,6 +27,10 @@ module EY
|
|
27
27
|
dep
|
28
28
|
end
|
29
29
|
|
30
|
+
def self.deploy(api, app_environment, attrs)
|
31
|
+
Deployment.from_hash(api, attrs.merge(:app_environment => app_environment)).deploy
|
32
|
+
end
|
33
|
+
|
30
34
|
def app
|
31
35
|
app_environment.app
|
32
36
|
end
|
@@ -60,6 +64,10 @@ module EY
|
|
60
64
|
@config ||= {'input_ref' => ref, 'deployed_by' => deployed_by}.merge(extra_config)
|
61
65
|
end
|
62
66
|
|
67
|
+
# Tell EY Cloud that you will be starting a deploy yourself.
|
68
|
+
#
|
69
|
+
# The name for this method isn't great. It's a relic of how the deploy
|
70
|
+
# ran before it ever told EY Cloud that is was running a deploy at all.
|
63
71
|
def start
|
64
72
|
params = {
|
65
73
|
:migrate => migrate,
|
@@ -70,6 +78,21 @@ module EY
|
|
70
78
|
post_to_api(params)
|
71
79
|
end
|
72
80
|
|
81
|
+
# Tell EY Cloud to deploy on our behalf.
|
82
|
+
#
|
83
|
+
# Deploy is different from start in that it triggers the deploy remotely.
|
84
|
+
# This is almost exactly equivalent to pressing the deploy button on the
|
85
|
+
# dashboard. No output will be returned.
|
86
|
+
def deploy
|
87
|
+
params = {
|
88
|
+
:migrate => migrate,
|
89
|
+
:ref => ref,
|
90
|
+
}
|
91
|
+
params[:serverside_version] = serverside_version if serverside_version
|
92
|
+
params[:migrate_command] = migrate_command if migrate
|
93
|
+
update_with_response api.post(collection_uri + "/deploy", 'deployment' => params)
|
94
|
+
end
|
95
|
+
|
73
96
|
def output
|
74
97
|
@output ||= StringIO.new
|
75
98
|
end
|
@@ -95,6 +118,7 @@ module EY
|
|
95
118
|
response['deployment'].each do |key,val|
|
96
119
|
send("#{key}=", val) if respond_to?("#{key}=")
|
97
120
|
end
|
121
|
+
self
|
98
122
|
end
|
99
123
|
|
100
124
|
private
|
@@ -114,8 +114,12 @@ module EY
|
|
114
114
|
Log.from_array(api, api.get("/environments/#{id}/logs")["logs"])
|
115
115
|
end
|
116
116
|
|
117
|
+
def provisioned_instances
|
118
|
+
instances.select { |inst| inst.provisioned? }
|
119
|
+
end
|
120
|
+
|
117
121
|
def deploy_to_instances
|
118
|
-
|
122
|
+
provisioned_instances.select { |inst| inst.has_app_code? }
|
119
123
|
end
|
120
124
|
|
121
125
|
def bridge
|
@@ -125,7 +129,7 @@ module EY
|
|
125
129
|
def bridge!(ignore_bad_bridge = false)
|
126
130
|
if bridge.nil?
|
127
131
|
raise NoBridgeError.new(name)
|
128
|
-
elsif !ignore_bad_bridge && bridge.
|
132
|
+
elsif !ignore_bad_bridge && !bridge.running?
|
129
133
|
raise BadBridgeStatusError.new(bridge.status, api.endpoint)
|
130
134
|
end
|
131
135
|
bridge
|
@@ -10,6 +10,13 @@ module EY
|
|
10
10
|
!["db_master", "db_slave"].include?(role.to_s)
|
11
11
|
end
|
12
12
|
|
13
|
+
def running?
|
14
|
+
status == "running"
|
15
|
+
end
|
16
|
+
|
17
|
+
def provisioned?
|
18
|
+
hostname && role && status != "starting" # not foolproof, but help throw out bad instances
|
19
|
+
end
|
13
20
|
end
|
14
21
|
end
|
15
22
|
end
|
@@ -15,7 +15,7 @@ module EY::CloudClient::Test
|
|
15
15
|
unless system("ruby -c '#{config_ru}' > /dev/null")
|
16
16
|
raise SyntaxError, "There is a syntax error in fake_awsm/config.ru! FIX IT!"
|
17
17
|
end
|
18
|
-
@server = RealWeb.start_server_in_fork(config_ru)
|
18
|
+
@server = RealWeb.start_server_in_fork(config_ru, :timeout => 5)
|
19
19
|
@server.base_uri.to_s
|
20
20
|
end
|
21
21
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'sinatra/base'
|
3
|
-
require '
|
3
|
+
require 'multi_json'
|
4
4
|
require 'rabl'
|
5
5
|
require 'gitable'
|
6
6
|
require 'ey_resolver'
|
@@ -33,6 +33,12 @@ class FakeAwsm < Sinatra::Base
|
|
33
33
|
@user = Scenario::Base.new.user
|
34
34
|
end
|
35
35
|
|
36
|
+
helpers do
|
37
|
+
def json(data)
|
38
|
+
MultiJson.dump(data)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
36
42
|
before do
|
37
43
|
if env['PATH_INFO'] =~ %r#/api/v2#
|
38
44
|
user_agent = env['HTTP_USER_AGENT']
|
@@ -55,32 +61,18 @@ class FakeAwsm < Sinatra::Base
|
|
55
61
|
end
|
56
62
|
|
57
63
|
get "/scenario" do
|
58
|
-
|
59
|
-
unless
|
64
|
+
found_scenario = SCENARIOS.detect { |scen| scen.user.name == params[:scenario] }
|
65
|
+
unless found_scenario
|
60
66
|
status(404)
|
61
|
-
return {"ok" => "false", "message" => "wtf is the #{params[:scenario]} scenario?"}
|
67
|
+
return json({"ok" => "false", "message" => "wtf is the #{params[:scenario]} scenario?"})
|
62
68
|
end
|
63
|
-
|
64
|
-
|
65
|
-
"scenario" => {
|
66
|
-
"email" => user.email,
|
67
|
-
"password" => user.password,
|
68
|
-
"api_token" => user.api_token,
|
69
|
-
}
|
70
|
-
}.to_json
|
69
|
+
@scenario = found_scenario.user
|
70
|
+
render :rabl, :scenario, :format => "json"
|
71
71
|
end
|
72
72
|
|
73
73
|
get "/scenarios" do
|
74
|
-
scenarios = SCENARIOS.map
|
75
|
-
|
76
|
-
{
|
77
|
-
:name => user.name,
|
78
|
-
:email => user.email,
|
79
|
-
:password => user.password,
|
80
|
-
:api_token => user.api_token,
|
81
|
-
}
|
82
|
-
end
|
83
|
-
{'scenarios' => scenarios}.to_json
|
74
|
+
@scenarios = SCENARIOS.map { |scen| scen.user }
|
75
|
+
render :rabl, :scenarios, :format => "json"
|
84
76
|
end
|
85
77
|
|
86
78
|
get "/api/v2/current_user" do
|
@@ -203,6 +195,14 @@ class FakeAwsm < Sinatra::Base
|
|
203
195
|
render :rabl, :deployment, :format => "json"
|
204
196
|
end
|
205
197
|
|
198
|
+
post "/api/v2/apps/:app_id/environments/:environment_id/deployments/deploy" do
|
199
|
+
app_env = @user.accounts.apps.get(params[:app_id]).app_environments.first(:environment_id => params[:environment_id])
|
200
|
+
@deployment = app_env.deployments.create(params[:deployment])
|
201
|
+
@deployment.deploy
|
202
|
+
response['Location'] = "/api/v2/apps/#{params[:app_id]}/environments/#{params[:environment_id]}/deployments/#{@deployment.id}"
|
203
|
+
render :rabl, :deployment, :format => "json"
|
204
|
+
end
|
205
|
+
|
206
206
|
get "/api/v2/apps/:app_id/environments/:environment_id/deployments/last" do
|
207
207
|
app_env = @user.accounts.apps.get(params[:app_id]).app_environments.first(:environment_id => params[:environment_id])
|
208
208
|
@deployment = app_env.deployments.last
|
@@ -3,6 +3,8 @@ require 'dm-core'
|
|
3
3
|
class Deployment
|
4
4
|
include DataMapper::Resource
|
5
5
|
|
6
|
+
AWSM_SERVERSIDE_VERSION = '2.0.0.awsm'
|
7
|
+
|
6
8
|
property :id, Serial
|
7
9
|
property :created_at, DateTime
|
8
10
|
property :finished_at, DateTime
|
@@ -29,6 +31,23 @@ class Deployment
|
|
29
31
|
"resolved-#{ref}"
|
30
32
|
end
|
31
33
|
|
34
|
+
# pretend to trigger a deploy
|
35
|
+
#
|
36
|
+
# this deploy will be instant, unlike real deploys
|
37
|
+
#
|
38
|
+
def deploy
|
39
|
+
unless serverside_version
|
40
|
+
# only set serverside version if it's not set, to imitate the api
|
41
|
+
# behavior of choosing its own serverside version if one is not
|
42
|
+
# sent
|
43
|
+
update :serverside_version => AWSM_SERVERSIDE_VERSION
|
44
|
+
end
|
45
|
+
finished!(
|
46
|
+
:successful => true,
|
47
|
+
:output => 'Deployment triggered by the API'
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
32
51
|
def finished?
|
33
52
|
finished_at != nil
|
34
53
|
end
|
@@ -56,6 +56,35 @@ describe EY::CloudClient::AppEnvironment do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
describe "triggering an api deploy" do
|
60
|
+
before do
|
61
|
+
@api = scenario_cloud_client "Multiple Ambiguous Accounts"
|
62
|
+
result = EY::CloudClient::AppEnvironment.resolve(@api, 'app_name' => 'rails232app', 'environment_name' => 'giblets', 'account_name' => 'main')
|
63
|
+
result.should be_one_match
|
64
|
+
@app_env = result.matches.first
|
65
|
+
end
|
66
|
+
|
67
|
+
it "triggers a deployment (assumes that deploys happen instantly, which they don't)" do
|
68
|
+
deployment = @app_env.deploy({
|
69
|
+
:ref => 'master',
|
70
|
+
:migrate => true,
|
71
|
+
:migrate_command => 'rake migrate',
|
72
|
+
:extra_config => {'extra' => 'config'},
|
73
|
+
})
|
74
|
+
deployment.config.should == {'input_ref' => 'master', 'deployed_by' => 'Multiple Ambiguous Accounts', 'extra' => 'config'}
|
75
|
+
deployment.commit.should =~ /[0-9a-f]{40}/
|
76
|
+
deployment.resolved_ref.should_not be_nil
|
77
|
+
deployment.created_at.should_not be_nil
|
78
|
+
deployment.finished_at.should_not be_nil
|
79
|
+
deployment.should be_finished
|
80
|
+
|
81
|
+
found_dep = @app_env.last_deployment
|
82
|
+
found_dep.id.should == deployment.id
|
83
|
+
found_dep.should be_finished
|
84
|
+
found_dep.serverside_version.should == '2.0.0.awsm' # uses the awsm version if one is not sent.
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
59
88
|
describe "last deployment" do
|
60
89
|
before do
|
61
90
|
@api = scenario_cloud_client "Linked App"
|
data/spec/spec_helper.rb
CHANGED
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.8
|
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:
|
12
|
+
date: 2013-02-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
37
|
+
version: '1.6'
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
45
|
+
version: '1.6'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: rspec
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,22 +75,6 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: rdoc
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
78
|
- !ruby/object:Gem::Dependency
|
95
79
|
name: fakeweb
|
96
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,7 +130,7 @@ dependencies:
|
|
146
130
|
requirements:
|
147
131
|
- - ~>
|
148
132
|
- !ruby/object:Gem::Version
|
149
|
-
version: 0.
|
133
|
+
version: 1.0.1
|
150
134
|
type: :development
|
151
135
|
prerelease: false
|
152
136
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -154,7 +138,7 @@ dependencies:
|
|
154
138
|
requirements:
|
155
139
|
- - ~>
|
156
140
|
- !ruby/object:Gem::Version
|
157
|
-
version: 0.
|
141
|
+
version: 1.0.1
|
158
142
|
- !ruby/object:Gem::Dependency
|
159
143
|
name: dm-core
|
160
144
|
requirement: !ruby/object:Gem::Requirement
|
@@ -313,6 +297,8 @@ files:
|
|
313
297
|
- lib/engineyard-cloud-client/test/fake_awsm/views/keypairs.rabl
|
314
298
|
- lib/engineyard-cloud-client/test/fake_awsm/views/resolve_app_environments.rabl
|
315
299
|
- lib/engineyard-cloud-client/test/fake_awsm/views/resolve_environments.rabl
|
300
|
+
- lib/engineyard-cloud-client/test/fake_awsm/views/scenario.rabl
|
301
|
+
- lib/engineyard-cloud-client/test/fake_awsm/views/scenarios.rabl
|
316
302
|
- lib/engineyard-cloud-client/test/fake_awsm/views/user.rabl
|
317
303
|
- lib/engineyard-cloud-client/test/fake_awsm.rb
|
318
304
|
- lib/engineyard-cloud-client/test/scenario.rb
|
@@ -320,7 +306,8 @@ files:
|
|
320
306
|
- lib/engineyard-cloud-client/version.rb
|
321
307
|
- lib/engineyard-cloud-client.rb
|
322
308
|
- LICENSE
|
323
|
-
- README.
|
309
|
+
- README.md
|
310
|
+
- ChangeLog.md
|
324
311
|
- spec/engineyard-cloud-client/api_spec.rb
|
325
312
|
- spec/engineyard-cloud-client/integration/account_spec.rb
|
326
313
|
- spec/engineyard-cloud-client/integration/app_environment_spec.rb
|
@@ -351,7 +338,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
351
338
|
version: '0'
|
352
339
|
segments:
|
353
340
|
- 0
|
354
|
-
hash: -
|
341
|
+
hash: -1071401773858451620
|
355
342
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
356
343
|
none: false
|
357
344
|
requirements:
|
@@ -360,7 +347,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
360
347
|
version: '0'
|
361
348
|
segments:
|
362
349
|
- 0
|
363
|
-
hash: -
|
350
|
+
hash: -1071401773858451620
|
364
351
|
requirements: []
|
365
352
|
rubyforge_project:
|
366
353
|
rubygems_version: 1.8.24
|