Class: EY::CloudClient::Environment
- Inherits:
-
Object
- Object
- EY::CloudClient::Environment
- Defined in:
- lib/engineyard-cloud-client/models/environment.rb
Instance Attribute Summary collapse
-
#account ⇒ Object
Returns the value of attribute account.
-
#apps ⇒ Object
Returns the value of attribute apps.
Class Method Summary collapse
-
.all(api) ⇒ Object
Return list of all Environments linked to all current user’s accounts.
-
.by_name(api, environment_name, account_name = nil) ⇒ Object
Accepts an api object, environment name and optional account name and returns the best matching environment for the given constraints.
-
.create(api, attrs = {}) ⇒ Object
Usage Environment.create(api, { app: app, # requires: app.id name: ‘myapp_production’, region: ‘us-west-1’, # default: us-east-1 app_server_stack_name: ‘nginx_thin’, # default: nginx_passenger3 framework_env: ‘staging’ # default: production cluster_configuration: { configuration: ‘single’ # default: single, cluster, custom } }).
-
.resolve(api, constraints) ⇒ Object
Return a constrained list of environments given a set of constraints like:.
Instance Method Summary collapse
- #account_name ⇒ Object
- #add_app_environment(app_env) ⇒ Object
-
#add_instance(opts) ⇒ Object
Throws a POST request at the API to /add_instances and adds one instance to this environment.
- #app_environments ⇒ Object
- #attributes=(attrs) ⇒ Object
- #bridge ⇒ Object
- #bridge!(ignore_bad_bridge = false) ⇒ Object
- #deploy_to_instances ⇒ Object
-
#download_recipes ⇒ Object
See Recipes#download.
- #hierarchy_name ⇒ Object
-
#instance_by_id(id) ⇒ Object
Gets an instance’s Amazon ID by its “id” attribute as reported by AWSM.
- #instances ⇒ Object
- #logs ⇒ Object
- #provisioned_instances ⇒ Object
- #recipes ⇒ Object
-
#remove_instance(instance) ⇒ Object
Sends a request to the API to remove the instance specified by its “provisioned_id” (Amazon ID).
-
#run_custom_recipes ⇒ Object
See Recipes#run.
- #shorten_name_for(app) ⇒ Object
- #ssh_username=(user) ⇒ Object
- #update ⇒ Object (also: #rebuild)
-
#upload_recipes(file_to_upload) ⇒ Object
See Recipes#upload.
-
#upload_recipes_at_path(recipes_path) ⇒ Object
See Recipes#upload_path.
Instance Attribute Details
#account ⇒ Object
Returns the value of attribute account.
101 102 103 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 101 def account @account end |
#apps ⇒ Object
Returns the value of attribute apps.
101 102 103 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 101 def apps @apps end |
Class Method Details
.all(api) ⇒ Object
Return list of all Environments linked to all current user’s accounts
21 22 23 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 21 def self.all(api) self.from_array(api, api.get("/environments", "no_instances" => "true")["environments"]) end |
.by_name(api, environment_name, account_name = nil) ⇒ Object
Accepts an api object, environment name and optional account name and returns the best matching environment for the given constraints.
This is a shortcut for resolve_environments. Raises if nothing is found or if more than one environment is found.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 45 def self.by_name(api, environment_name, account_name=nil) constraints = { :environment_name => environment_name, :account_name => account_name, } resolver = resolve(api, constraints) resolver.one_match { |match| return match } resolver.no_matches do |errors, suggestions| = nil if suggestions.any? = "Suggestions found:\n" suggestions.sourt_by{|suggest| suggest['account_name']}.each do |suggest| << "\t#{suggest['account_name']}/#{suggest['env_name']}\n" end end raise ResourceNotFound.new([errors,].compact.join("\n").strip) end resolver.many_matches do |matches| = "Multiple environments possible, please be more specific:\n" matches.sort_by {|env| env.account}.each do |env| << "\t#{env.account.name}/#{env.name}\n" end raise MultipleMatchesError.new() end end |
.create(api, attrs = {}) ⇒ Object
Usage Environment.create(api, {
app: app, # requires: app.id
name: 'myapp_production',
region: 'us-west-1', # default: us-east-1
app_server_stack_name: 'nginx_thin', # default: nginx_passenger3
framework_env: 'staging' # default: production
cluster_configuration: {
configuration: 'single' # default: single, cluster, custom
}
})
NOTE: Syntax above is for Ruby 1.9. In Ruby 1.8, keys must all be strings.
TODO - allow any attribute to be sent through that the API might allow; e.g. region, ruby_version, stack_label
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 90 def self.create(api, attrs={}) app = attrs.delete("app") cluster_configuration = attrs.delete('cluster_configuration') raise EY::CloudClient::AttributeRequiredError.new("app", EY::CloudClient::App) unless app raise EY::CloudClient::AttributeRequiredError.new("name") unless attrs["name"] params = {"environment" => attrs.dup} unpack_cluster_configuration(params, cluster_configuration) response = api.post("/apps/#{app.id}/environments", params) self.from_hash(api, response['environment']) end |
.resolve(api, constraints) ⇒ Object
Return a constrained list of environments given a set of constraints like:
-
app_name: app name full or partial match string
-
account_name: account name full or partial match string
-
environment_name: environment name full or partial match string
-
remotes: An array of git remote URIs
32 33 34 35 36 37 38 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 32 def self.resolve(api, constraints) clean_constraints = constraints.reject { |k,v| v.nil? } params = {'constraints' => clean_constraints} response = api.get("/environments/resolve", params)['resolver'] matches = from_array(api, response['matches']) ResolverResult.new(api, matches, response['errors'], response['suggestions']) end |
Instance Method Details
#account_name ⇒ Object
136 137 138 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 136 def account_name account && account.name end |
#add_app_environment(app_env) ⇒ Object
115 116 117 118 119 120 121 122 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 115 def add_app_environment(app_env) @app_environments ||= [] existing_app_env = @app_environments.detect { |ae| app_env.environment == ae.environment } unless existing_app_env @app_environments << app_env end existing_app_env || app_env end |
#add_instance(opts) ⇒ Object
Throws a POST request at the API to /add_instances and adds one instance to this environment.
Usage example:
api = EY::CloudClient.new(token: ‘your token here’) env = api.environment_by_name(‘your_env_name’)
env.add_instance(role: “app”) env.add_instance(role: “util”, name: “foo”)
Note that the role for an instance MUST be either “app” or “util”. No other value is acceptable. The “name” parameter can be anything, but it only applies to utility instances.
Note also that if you add a util instance, you must specify a name. This method will raise if you don’t.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 225 def add_instance(opts) unless %w[app util].include?(opts[:role].to_s) # Fail immediately because we don't have valid arguments. raise InvalidInstanceRole, "Instance role must be one of: app, util" end # Sanitize the name to remove whitespace if there is any if opts[:name] name = opts[:name].gsub(/\s+/, '') end if opts[:role] == 'util' unless name && name.length > 0 raise InvalidInstanceName, "When specifying a util instance you must also specify a name." end end # We know opts[:role] is right, name can be passed straight to the API. # Return the response body for error output, logging, etc. return api.post("/environments/#{id}/add_instances", :request => { "role" => opts[:role], "name" => opts[:name] }) end |
#app_environments ⇒ Object
124 125 126 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 124 def app_environments @app_environments ||= [] end |
#attributes=(attrs) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 103 def attributes=(attrs) account_attrs = attrs.delete('account') apps_attrs = attrs.delete('apps') instances_attrs = attrs.delete('instances') super set_account account_attrs if account_attrs set_apps apps_attrs if apps_attrs set_instances instances_attrs if instances_attrs end |
#bridge ⇒ Object
160 161 162 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 160 def bridge @bridge ||= instances.detect { |inst| inst.bridge? } end |
#bridge!(ignore_bad_bridge = false) ⇒ Object
164 165 166 167 168 169 170 171 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 164 def bridge!(ignore_bad_bridge = false) if bridge.nil? raise NoBridgeError.new(name) elsif !ignore_bad_bridge && !bridge.running? raise BadBridgeStatusError.new(bridge.status, api.endpoint) end bridge end |
#deploy_to_instances ⇒ Object
156 157 158 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 156 def deploy_to_instances provisioned_instances.select { |inst| inst.has_app_code? } end |
#download_recipes ⇒ Object
See Recipes#download
189 190 191 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 189 def download_recipes recipes.download end |
#hierarchy_name ⇒ Object
140 141 142 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 140 def hierarchy_name [account_name, name].join(" / ") end |
#instance_by_id(id) ⇒ Object
Gets an instance’s Amazon ID by its “id” attribute as reported by AWSM. When an instance is added via the API, the JSON that’s returned contains an “id” attribute for that instance. Developers may save that ID so they can later discover an instance’s Amazon ID. This is because, when an instance object is first created (see #add_instance above), its Amazon ID isn’t yet known. The object is created, and then later provisioned, so you can’t get an Amazon ID until after provisioning has taken place. This method allows you to send an ID to it, and then returns the instance object that corresponds to that ID, which will have an Amazon ID with it if the instance has been provisioned at the time the environment information was read.
Note that the ID passed in must be an integer.
Usage example:
api = EY::CloudClient.new(token: 'token')
env = api.environment_by_name('my_env')
env.instance_by_id(12345)
=> <EY::CloudClient::Instance ...>
272 273 274 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 272 def instance_by_id(id) instances.detect { |x| x.id == id } # ID should always be unique end |
#instances ⇒ Object
132 133 134 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 132 def instances @instances ||= request_instances end |
#logs ⇒ Object
148 149 150 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 148 def logs Log.from_array(api, api.get("/environments/#{id}/logs")["logs"]) end |
#provisioned_instances ⇒ Object
152 153 154 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 152 def provisioned_instances instances.select { |inst| inst.provisioned? } end |
#recipes ⇒ Object
179 180 181 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 179 def recipes Recipes.new(api, self) end |
#remove_instance(instance) ⇒ Object
Sends a request to the API to remove the instance specified by its “provisioned_id” (Amazon ID).
Usage example:
api = EY::CloudClient.new(token: 'token')
env = api.environment_by_name('my_app_production')
bad_instance = env.instance_by_id(12345) # instance ID should be saved upon creation
env.remove_instance(bad_instance)
Warnings/caveats:
+ The API is responsible for actually removing this instance. All this
does is send an appropriate request to the API.
+ You should look carefully at the API response JSON to see whether or
not the API accepted or rejected your request. If it accepted the
request, that instance *should* be removed as soon as possible.
+ Note that this is a client that talks to an API, which talks to an
API, which talks to an API. Ultimately the IaaS provider API has the
final say on whether or not to remove an instance, so a failure there
can definitely affect how things work at every point down the line.
+ If the instance you pass in doesn’t exist in the live cloud
environment you're working on, the status should be rejected and thus
the instance won't be removed (because *that* instance isn't there).
This is important to keep in mind for scheduled/auto scaling; if
for some reason the automatically added instance is removed before
a "scale down" event that you might trigger, you may wind up with an
unknown/unexpected number of instances in your environment.
+ Only works for app/util instances. Raises an error if you pass one
that isn't valid.
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 307 def remove_instance(instance) unless instance raise ArgumentError, "A argument of type Instance was expected. Got #{instance.inspect}" end # Check to make sure that we have a valid instance role here first. unless %w[app util].include?(instance.role) raise InvalidInstanceRole, "Removing instances is only supported for app, util instances" end # Check to be sure that instance is actually provisioned # TODO: Rip out the amazon_id stuff when we have IaaS agnosticism nailed down unless instance.amazon_id && instance.provisioned? raise InstanceNotProvisioned, "Instance is not provisioned or is in unusual state." end response = api.post("/environments/#{id}/remove_instances", :request => { :provisioned_id => instance.amazon_id, :role => instance.role, :name => instance.name }) # Reset instances so they are fresh if they are requested again. @instances = nil # Return the response. return response end |
#run_custom_recipes ⇒ Object
See Recipes#run
184 185 186 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 184 def run_custom_recipes recipes.run end |
#shorten_name_for(app) ⇒ Object
203 204 205 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 203 def shorten_name_for(app) name.gsub(/^#{Regexp.quote(app.name)}_/, '') end |
#ssh_username=(user) ⇒ Object
144 145 146 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 144 def ssh_username=(user) self.username = user end |
#update ⇒ Object Also known as: rebuild
173 174 175 176 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 173 def update api.put("/environments/#{id}/update_instances") true # raises on failure end |
#upload_recipes(file_to_upload) ⇒ Object
See Recipes#upload
199 200 201 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 199 def upload_recipes(file_to_upload) recipes.upload(file_to_upload) end |
#upload_recipes_at_path(recipes_path) ⇒ Object
See Recipes#upload_path
194 195 196 |
# File 'lib/engineyard-cloud-client/models/environment.rb', line 194 def upload_recipes_at_path(recipes_path) recipes.upload_path(recipes_path) end |