engineyard-cloud-client 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/README.rdoc +7 -0
- data/lib/engineyard-cloud-client.rb +149 -0
- data/lib/engineyard-cloud-client/errors.rb +38 -0
- data/lib/engineyard-cloud-client/model_registry.rb +21 -0
- data/lib/engineyard-cloud-client/models.rb +14 -0
- data/lib/engineyard-cloud-client/models/account.rb +38 -0
- data/lib/engineyard-cloud-client/models/api_struct.rb +50 -0
- data/lib/engineyard-cloud-client/models/app.rb +77 -0
- data/lib/engineyard-cloud-client/models/app_environment.rb +85 -0
- data/lib/engineyard-cloud-client/models/deployment.rb +105 -0
- data/lib/engineyard-cloud-client/models/environment.rb +240 -0
- data/lib/engineyard-cloud-client/models/instance.rb +15 -0
- data/lib/engineyard-cloud-client/models/keypair.rb +32 -0
- data/lib/engineyard-cloud-client/models/log.rb +11 -0
- data/lib/engineyard-cloud-client/models/user.rb +11 -0
- data/lib/engineyard-cloud-client/resolver_result.rb +19 -0
- data/lib/engineyard-cloud-client/rest_client_ext.rb +11 -0
- data/lib/engineyard-cloud-client/ruby_ext.rb +9 -0
- data/lib/engineyard-cloud-client/test.rb +31 -0
- data/lib/engineyard-cloud-client/test/fake_awsm.rb +22 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/config.ru +207 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models.rb +9 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/account.rb +13 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/app.rb +24 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/app_environment.rb +19 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/deployments.rb +15 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/environment.rb +25 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/instance.rb +23 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/models/user.rb +15 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/scenarios.rb +325 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/accounts.rabl +2 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/apps.rabl +10 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/base_app_environment.rabl +13 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/base_environment.rabl +4 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/environments.rabl +11 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/instances.rabl +2 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/resolve_app_environments.rabl +7 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/resolve_environments.rabl +7 -0
- data/lib/engineyard-cloud-client/test/fake_awsm/views/user.rabl +2 -0
- data/lib/engineyard-cloud-client/test/scenario.rb +43 -0
- data/lib/engineyard-cloud-client/test/ui.rb +33 -0
- data/lib/engineyard-cloud-client/version.rb +7 -0
- data/spec/engineyard-cloud-client/api_spec.rb +59 -0
- data/spec/engineyard-cloud-client/integration/account_spec.rb +18 -0
- data/spec/engineyard-cloud-client/integration/app_environment_spec.rb +38 -0
- data/spec/engineyard-cloud-client/integration/app_spec.rb +20 -0
- data/spec/engineyard-cloud-client/integration/environment_spec.rb +57 -0
- data/spec/engineyard-cloud-client/integration/user_spec.rb +18 -0
- data/spec/engineyard-cloud-client/models/api_struct_spec.rb +41 -0
- data/spec/engineyard-cloud-client/models/app_spec.rb +64 -0
- data/spec/engineyard-cloud-client/models/environment_spec.rb +300 -0
- data/spec/engineyard-cloud-client/models/instance_spec.rb +44 -0
- data/spec/engineyard-cloud-client/models/keypair_spec.rb +58 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/support/helpers.rb +16 -0
- data/spec/support/matchers.rb +2 -0
- metadata +377 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Engine Yard, Inc
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
= engineyard-cloud-client
|
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.
|
4
|
+
|
5
|
+
See engineyard gem for a usage example. Bother someone if this is released and the documentation is still not updated.
|
6
|
+
|
7
|
+
This is currently unreleased.
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module EY
|
2
|
+
class CloudClient
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'engineyard-cloud-client/ruby_ext'
|
7
|
+
require 'engineyard-cloud-client/model_registry'
|
8
|
+
require 'engineyard-cloud-client/models'
|
9
|
+
require 'engineyard-cloud-client/rest_client_ext'
|
10
|
+
require 'engineyard-cloud-client/resolver_result'
|
11
|
+
require 'engineyard-cloud-client/version'
|
12
|
+
require 'engineyard-cloud-client/errors'
|
13
|
+
require 'multi_json'
|
14
|
+
require 'pp'
|
15
|
+
|
16
|
+
module EY
|
17
|
+
class CloudClient
|
18
|
+
attr_reader :token, :registry
|
19
|
+
attr_accessor :ui
|
20
|
+
|
21
|
+
USER_AGENT_STRING = "EngineYardCloudClient/#{EY::CloudClient::VERSION}"
|
22
|
+
|
23
|
+
def self.endpoint
|
24
|
+
@endpoint
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.endpoint=(endpoint)
|
28
|
+
@endpoint = URI.parse(endpoint)
|
29
|
+
unless @endpoint.absolute?
|
30
|
+
raise BadEndpointError.new(endpoint)
|
31
|
+
end
|
32
|
+
@endpoint
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.default_endpoint!
|
36
|
+
self.endpoint = "https://cloud.engineyard.com/"
|
37
|
+
end
|
38
|
+
default_endpoint!
|
39
|
+
|
40
|
+
def initialize(token, ui)
|
41
|
+
self.token = token
|
42
|
+
self.ui = ui
|
43
|
+
end
|
44
|
+
|
45
|
+
def ==(other)
|
46
|
+
other.is_a?(self.class) && other.token == token
|
47
|
+
end
|
48
|
+
|
49
|
+
def registry
|
50
|
+
@registry ||= ModelRegistry.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def token=(new_token)
|
54
|
+
unless new_token
|
55
|
+
raise ArgumentError, "EY Cloud API token required"
|
56
|
+
end
|
57
|
+
@token = new_token
|
58
|
+
end
|
59
|
+
|
60
|
+
def request(url, opts={})
|
61
|
+
opts[:headers] ||= {}
|
62
|
+
opts[:headers]["X-EY-Cloud-Token"] = token
|
63
|
+
ui.debug("Token", token)
|
64
|
+
self.class.request(url, ui, opts)
|
65
|
+
end
|
66
|
+
|
67
|
+
def resolve_environments(constraints)
|
68
|
+
EY::CloudClient::Environment.resolve(self, constraints)
|
69
|
+
end
|
70
|
+
|
71
|
+
def resolve_app_environments(constraints)
|
72
|
+
EY::CloudClient::AppEnvironment.resolve(self, constraints)
|
73
|
+
end
|
74
|
+
|
75
|
+
def environments
|
76
|
+
@environments ||= EY::CloudClient::Environment.all(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
def apps
|
80
|
+
@apps ||= EY::CloudClient::App.all(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
# TODO: unhaxor
|
84
|
+
# This should load an api endpoint that deals directly in app_deployments
|
85
|
+
def app_environments
|
86
|
+
@app_environments ||= apps.map { |app| app.app_environments }.flatten
|
87
|
+
end
|
88
|
+
|
89
|
+
def current_user
|
90
|
+
EY::CloudClient::User.from_hash(self, request('/current_user')['user'])
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.request(path, ui, opts={})
|
94
|
+
url = self.endpoint + "api/v2#{path}"
|
95
|
+
method = (opts.delete(:method) || 'get').to_s.downcase.to_sym
|
96
|
+
params = opts.delete(:params) || {}
|
97
|
+
headers = opts.delete(:headers) || {}
|
98
|
+
headers["Accept"] ||= "application/json"
|
99
|
+
headers["User-Agent"] = USER_AGENT_STRING
|
100
|
+
|
101
|
+
begin
|
102
|
+
ui.debug("Request", "#{method.to_s.upcase} #{url}")
|
103
|
+
ui.debug("Params", params.inspect)
|
104
|
+
case method
|
105
|
+
when :get, :delete, :head
|
106
|
+
unless params.empty?
|
107
|
+
url.query = RestClient::Payload::UrlEncoded.new(params).to_s
|
108
|
+
end
|
109
|
+
resp = RestClient.send(method, url.to_s, headers)
|
110
|
+
else
|
111
|
+
resp = RestClient.send(method, url.to_s, params, headers)
|
112
|
+
end
|
113
|
+
rescue RestClient::Unauthorized
|
114
|
+
raise InvalidCredentials
|
115
|
+
rescue Errno::ECONNREFUSED
|
116
|
+
raise RequestFailed, "Could not reach the cloud API"
|
117
|
+
rescue RestClient::ResourceNotFound
|
118
|
+
raise ResourceNotFound, "The requested resource could not be found"
|
119
|
+
rescue RestClient::BadGateway
|
120
|
+
raise RequestFailed, "EY Cloud API is temporarily unavailable. Please try again soon."
|
121
|
+
rescue RestClient::RequestFailed => e
|
122
|
+
raise RequestFailed, "#{e.message} #{e.response}"
|
123
|
+
rescue OpenSSL::SSL::SSLError
|
124
|
+
raise RequestFailed, "SSL is misconfigured on your cloud"
|
125
|
+
end
|
126
|
+
|
127
|
+
if resp.body.empty?
|
128
|
+
data = ''
|
129
|
+
elsif resp.headers[:content_type] =~ /application\/json/
|
130
|
+
begin
|
131
|
+
data = MultiJson.decode(resp.body)
|
132
|
+
ui.debug("Response", "\n" + data.pretty_inspect)
|
133
|
+
rescue MultiJson::DecodeError
|
134
|
+
ui.debug("Raw response", resp.body)
|
135
|
+
raise RequestFailed, "Response was not valid JSON."
|
136
|
+
end
|
137
|
+
else
|
138
|
+
data = resp.body
|
139
|
+
end
|
140
|
+
|
141
|
+
data
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.authenticate(email, password, ui)
|
145
|
+
request("/authenticate", ui, { :method => "post", :params => { :email => email, :password => password }})["api_token"]
|
146
|
+
end
|
147
|
+
|
148
|
+
end # API
|
149
|
+
end # EY
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module EY
|
2
|
+
class CloudClient
|
3
|
+
class Error < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
class RequestFailed < Error; end
|
7
|
+
class InvalidCredentials < RequestFailed; end
|
8
|
+
class ResourceNotFound < RequestFailed; end
|
9
|
+
|
10
|
+
class BadEndpointError < Error
|
11
|
+
def initialize(endpoint)
|
12
|
+
super "#{endpoint.inspect} is not a valid endpoint URI. Endpoint must be an absolute URI."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class AttributeRequiredError < Error
|
17
|
+
def initialize(attribute_name, klass = nil)
|
18
|
+
if klass
|
19
|
+
super "Attribute '#{attribute_name}' of class #{klass} is required for this action."
|
20
|
+
else
|
21
|
+
super "Attribute '#{attribute_name}' is required for this action."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class NoBridgeError < Error
|
27
|
+
def initialize(env_name)
|
28
|
+
super "The environment '#{env_name}' does not have a master instance."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class BadBridgeStatusError < Error
|
33
|
+
def initialize(bridge_status, endpoint)
|
34
|
+
super %|Application master's status is not "running" (green); it is "#{bridge_status}". Go to #{endpoint} to address this problem.|
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EY
|
2
|
+
class CloudClient
|
3
|
+
class ModelRegistry
|
4
|
+
def initialize
|
5
|
+
@registry = Hash.new { |h,k| h[k] = {} }
|
6
|
+
end
|
7
|
+
|
8
|
+
def find(klass, id)
|
9
|
+
if id
|
10
|
+
@registry[klass][id]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(klass, obj)
|
15
|
+
if obj.respond_to?(:id) && id = obj.id
|
16
|
+
@registry[klass][id] = obj
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module EY
|
2
|
+
class CloudClient
|
3
|
+
require 'engineyard-cloud-client/models/api_struct'
|
4
|
+
require 'engineyard-cloud-client/models/account'
|
5
|
+
require 'engineyard-cloud-client/models/app'
|
6
|
+
require 'engineyard-cloud-client/models/app_environment'
|
7
|
+
require 'engineyard-cloud-client/models/deployment'
|
8
|
+
require 'engineyard-cloud-client/models/environment'
|
9
|
+
require 'engineyard-cloud-client/models/log'
|
10
|
+
require 'engineyard-cloud-client/models/instance'
|
11
|
+
require 'engineyard-cloud-client/models/keypair'
|
12
|
+
require 'engineyard-cloud-client/models/user'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'engineyard-cloud-client/models/api_struct'
|
2
|
+
|
3
|
+
module EY
|
4
|
+
class CloudClient
|
5
|
+
class Account < ApiStruct.new(:id, :name)
|
6
|
+
|
7
|
+
def self.all(api)
|
8
|
+
self.from_array(api, api.request('/accounts')["accounts"])
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_app(app)
|
12
|
+
@apps ||= []
|
13
|
+
existing_app = @apps.detect { |a| app.id == a.id }
|
14
|
+
unless existing_app
|
15
|
+
@apps << app
|
16
|
+
end
|
17
|
+
existing_app || app
|
18
|
+
end
|
19
|
+
|
20
|
+
def apps
|
21
|
+
@apps ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_environment(environment)
|
25
|
+
@environments ||= []
|
26
|
+
existing_environment = @environments.detect { |env| environment.id == env.id }
|
27
|
+
unless existing_environment
|
28
|
+
@environments << environment
|
29
|
+
end
|
30
|
+
existing_environment || environment
|
31
|
+
end
|
32
|
+
|
33
|
+
def environments
|
34
|
+
@environments ||= []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module EY
|
2
|
+
class CloudClient
|
3
|
+
class ApiStruct < Struct
|
4
|
+
def self.new(*args, &block)
|
5
|
+
args = [:api] | args
|
6
|
+
super(*args) do |*block_args|
|
7
|
+
block.call(*block_args) if block
|
8
|
+
|
9
|
+
def self.from_array(api, array, common_values = {})
|
10
|
+
if array
|
11
|
+
array.map do |values|
|
12
|
+
from_hash(api, values.merge(common_values))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_hash(api, attrs_or_struct)
|
18
|
+
return nil unless attrs_or_struct
|
19
|
+
|
20
|
+
if attrs_or_struct.respond_to?(:attributes=)
|
21
|
+
# already a model
|
22
|
+
obj = attrs_or_struct
|
23
|
+
elsif obj = api.registry.find(self, attrs_or_struct['id'])
|
24
|
+
obj.attributes = attrs_or_struct
|
25
|
+
else
|
26
|
+
obj = new(api, attrs_or_struct)
|
27
|
+
api.registry.set(self, obj)
|
28
|
+
end
|
29
|
+
obj
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(api, attrs)
|
35
|
+
self.api = api
|
36
|
+
self.attributes = attrs
|
37
|
+
end
|
38
|
+
|
39
|
+
def attributes=(attrs)
|
40
|
+
attrs.each do |key, val|
|
41
|
+
setter = :"#{key}="
|
42
|
+
if respond_to?(setter)
|
43
|
+
send(setter, val)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'engineyard-cloud-client/errors'
|
2
|
+
require 'engineyard-cloud-client/models'
|
3
|
+
|
4
|
+
module EY
|
5
|
+
class CloudClient
|
6
|
+
class App < ApiStruct.new(:id, :name, :repository_uri, :app_type_id)
|
7
|
+
|
8
|
+
attr_reader :app_environments, :account
|
9
|
+
|
10
|
+
# Return list of all Apps linked to all current user's accounts
|
11
|
+
def self.all(api)
|
12
|
+
self.from_array(api, api.request('/apps')["apps"])
|
13
|
+
end
|
14
|
+
|
15
|
+
# An everything-you-need helper to create an App
|
16
|
+
# If successful, returns new App
|
17
|
+
# If unsuccessful, raises +EY::CloudClient::RequestFailed+
|
18
|
+
#
|
19
|
+
# Usage
|
20
|
+
# App.create(api,
|
21
|
+
# account: account # requires: account.id
|
22
|
+
# name: "myapp",
|
23
|
+
# repository_uri: "git@github.com:mycompany/myapp.git",
|
24
|
+
# app_type_id: "rails3",
|
25
|
+
# )
|
26
|
+
#
|
27
|
+
# NOTE: Syntax above is for Ruby 1.9. In Ruby 1.8, keys must all be strings.
|
28
|
+
def self.create(api, attrs = {})
|
29
|
+
account = attrs.delete("account")
|
30
|
+
params = attrs.dup # no default fields
|
31
|
+
raise EY::CloudClient::AttributeRequiredError.new("account", EY::CloudClient::Account) unless account
|
32
|
+
raise EY::CloudClient::AttributeRequiredError.new("name") unless params["name"]
|
33
|
+
raise EY::CloudClient::AttributeRequiredError.new("repository_uri") unless params["repository_uri"]
|
34
|
+
raise EY::CloudClient::AttributeRequiredError.new("app_type_id") unless params["app_type_id"]
|
35
|
+
response = api.request("/accounts/#{account.id}/apps", :method => :post, :params => {"app" => params})
|
36
|
+
from_hash(api, response['app'])
|
37
|
+
end
|
38
|
+
|
39
|
+
def account_name
|
40
|
+
account && account.name
|
41
|
+
end
|
42
|
+
|
43
|
+
def environments
|
44
|
+
(app_environments || []).map { |app_env| app_env.environment }
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_app_environment(app_env)
|
48
|
+
@app_environments ||= []
|
49
|
+
existing_app_env = @app_environments.detect { |ae| app_env.environment == ae.environment }
|
50
|
+
unless existing_app_env
|
51
|
+
@app_environments << app_env
|
52
|
+
end
|
53
|
+
existing_app_env || app_env
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_account(account_attrs)
|
57
|
+
@account = Account.from_hash(api, account_attrs)
|
58
|
+
@account.add_app(self)
|
59
|
+
@account
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_environments(environments_attrs)
|
63
|
+
(environments_attrs || []).each do |env|
|
64
|
+
AppEnvironment.from_hash(api, {'app' => self, 'environment' => env})
|
65
|
+
end
|
66
|
+
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
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'launchy'
|
2
|
+
require 'engineyard-cloud-client/models'
|
3
|
+
require 'engineyard-cloud-client/errors'
|
4
|
+
|
5
|
+
module EY
|
6
|
+
class CloudClient
|
7
|
+
class AppEnvironment < ApiStruct.new(:id, :app, :environment, :uri, :domain_name, :migrate_command, :migrate)
|
8
|
+
|
9
|
+
# Return a constrained list of app_environments given a set of constraints like:
|
10
|
+
#
|
11
|
+
# * app_name
|
12
|
+
# * account_name
|
13
|
+
# * environment_name
|
14
|
+
# * remotes: An array of git remote URIs
|
15
|
+
#
|
16
|
+
def self.resolve(api, constraints)
|
17
|
+
clean_constraints = constraints.reject { |k,v| v.nil? }
|
18
|
+
params = {'constraints' => clean_constraints}
|
19
|
+
response = api.request("/app_environments/resolve", :method => :get, :params => params)['resolver']
|
20
|
+
matches = from_array(api, response['matches'])
|
21
|
+
ResolverResult.new(api, matches, response['errors'], response['suggestions'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(api, attrs)
|
25
|
+
super
|
26
|
+
|
27
|
+
raise ArgumentError, 'AppEnvironment created without app!' unless app
|
28
|
+
raise ArgumentError, 'AppEnvironment created without environment!' unless environment
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_app(app_or_hash)
|
32
|
+
self.app = App.from_hash(api, app_or_hash)
|
33
|
+
app.add_app_environment(self)
|
34
|
+
app
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_environment(env_or_hash)
|
38
|
+
self.environment = Environment.from_hash(api, env_or_hash)
|
39
|
+
environment.add_app_environment(self)
|
40
|
+
environment
|
41
|
+
end
|
42
|
+
|
43
|
+
def attributes=(attrs)
|
44
|
+
app_attrs = attrs.delete('app')
|
45
|
+
environment_attrs = attrs.delete('environment')
|
46
|
+
super
|
47
|
+
set_app app_attrs if app_attrs
|
48
|
+
set_environment environment_attrs if environment_attrs
|
49
|
+
end
|
50
|
+
|
51
|
+
def account_name
|
52
|
+
app.account_name
|
53
|
+
end
|
54
|
+
|
55
|
+
def app_name
|
56
|
+
app.name
|
57
|
+
end
|
58
|
+
|
59
|
+
def environment_name
|
60
|
+
environment.name
|
61
|
+
end
|
62
|
+
|
63
|
+
def repository_uri
|
64
|
+
app.repository_uri
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_hierarchy_str
|
68
|
+
[account_name, app_name, environment_name].join('/')
|
69
|
+
end
|
70
|
+
|
71
|
+
def last_deployment
|
72
|
+
Deployment.last(api, self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def new_deployment(attrs)
|
76
|
+
Deployment.from_hash(api, attrs.merge(:app_environment => self))
|
77
|
+
end
|
78
|
+
|
79
|
+
def short_environment_name
|
80
|
+
environment.name.gsub(/^#{Regexp.quote(app.name)}_/, '')
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|