Class: RightScale::Cloud
Overview
Abstract base class for all clouds.
Defined Under Namespace
Classes: ActionResult, CloudError
Constant Summary collapse
- WILDCARD =
wildcard used for some ‘all kinds’ selections.
:*- DEFAULT_CLOUD_METADATA_ROOT_PATH =
default tree-climber root paths for cloud/user metadata. they are basically placeholders for metadata sources which need to distinguish cloud from user but otherwise don’t use real root paths.
"cloud_metadata"- DEFAULT_USER_METADATA_ROOT_PATH =
"user_metadata"- DEFAULT_CLOUD_METADATA_FILE_PREFIX =
default writer output file prefixes are based on EC2 legacy files.
'meta-data'- DEFAULT_USER_METADATA_FILE_PREFIX =
'user-data'- RAW_METADATA_WRITER =
raw metadata writer is a special case and normally only invoked while metadata is being queried from source. it can also be referenced to read back the metadata in raw form.
:raw
Instance Attribute Summary collapse
-
#extended_clouds ⇒ Object
readonly
Returns the value of attribute extended_clouds.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#script_path ⇒ Object
readonly
Returns the value of attribute script_path.
Instance Method Summary collapse
-
#abbreviation(value = nil) ⇒ Object
Getter/setter for abbreviation which also sets default formatter options when an abbreviation is set.
-
#build_metadata(kind) ⇒ Object
Executes a query for metadata and builds a metadata ‘tree’ according to the rules of provider and tree climber.
-
#clear_state ⇒ Object
Attempts to clear any files generated by writers.
-
#create_dependency_type(kind, category, dependency_type = nil) ⇒ Object
Creates the type using options specified by metadata kind, type category and specific type, if given.
-
#default_option(path, default_value) ⇒ Object
Merges the given default option at the given depth in the options hash but only if the value is not set.
-
#dependencies(*args) ⇒ Object
Runtime cloud depedencies (loaded on demand).
-
#dependency_base_paths(*args) ⇒ Object
Base paths for runtime cloud depedencies in order of priority.
-
#extend_cloud(cloud_name) ⇒ Object
Defines a base cloud type which the current instance extends.
-
#extension_script_base_paths(*args) ⇒ Object
Base paths for external scripts which extend methods of cloud object.
-
#fail(message) ⇒ Object
Convenience method for failing to load or execute cloud definition.
-
#finalize_default_options ⇒ Object
Provides final default options after cloud definition(s) have had a chance to set defaults.
-
#initialize(options) ⇒ Cloud
constructor
Initializer.
-
#is_current_cloud? ⇒ Boolean
Determines if the current instance is running on the cloud indicated by this object.
-
#logger ⇒ Object
Syntatic sugar for options, which should always be valid under normal circumstances.
-
#metadata_formatter(type = nil) ⇒ Object
Dependency type for metadata formatter.
-
#metadata_provider(type = nil) ⇒ Object
Dependency type for metadata provider.
-
#metadata_source(type = nil) ⇒ Object
Dependency type for metadata source.
-
#metadata_tree_climber(type = nil) ⇒ Object
Dependency type for metadata tree climber.
-
#metadata_writers(*args) ⇒ Object
Dependency type for metadata writers.
-
#option(path) ⇒ Object
Gets the option given by path, if it exists.
-
#platform ⇒ Object
Convenience method for getting information about the current machine platform.
-
#read_cloud_metadata(writer_type = RAW_METADATA_WRITER, subpath = nil) ⇒ Object
Convenience method for reading only cloud metdata.
-
#read_metadata(kind = :user_metadata, writer_type = RAW_METADATA_WRITER, subpath = nil) ⇒ Object
Reads the generated metadata file of the given kind and writer type.
-
#read_user_metadata(writer_type = RAW_METADATA_WRITER, subpath = nil) ⇒ Object
Convenience method for reading only cloud metdata.
-
#resolve_dependency(dependency_type) ⇒ Object
Just-in-time requires a cloud’s dependency, which should include its relative location (and sub-type) in the dependency name (e.g. ‘metadata_sources/http_metadata_source’ => Sources::HttpMetadataSource).
-
#update_details ⇒ Object
Updates the given node with any cloud-specific detailed information.
-
#write_cloud_metadata ⇒ Object
Convenience method for writing only cloud metdata.
-
#write_metadata(kind = WILDCARD) ⇒ Object
Queries and writes current metadata to file.
-
#write_user_metadata ⇒ Object
Convenience method for writing only user metdata.
Constructor Details
#initialize(options) ⇒ Cloud
Initializer.
Parameters
- options(Hash)
-
options grab bag used to configure cloud and dependencies.
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/clouds/cloud.rb', line 69 def initialize() raise ArgumentError.new("options[:name] is required") unless @name = [:name] raise ArgumentError.new("options[:script_path] is required") unless @script_path = [:script_path] # break options lineage and use Mash to handle keys as strings or tokens. # note that this is not a deep copy as :ohai is an option representing the # full ohai node in at least one use case. @options = Mash.new() @extended_clouds = [] end |
Instance Attribute Details
#extended_clouds ⇒ Object (readonly)
Returns the value of attribute extended_clouds.
52 53 54 |
# File 'lib/clouds/cloud.rb', line 52 def extended_clouds @extended_clouds end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
52 53 54 |
# File 'lib/clouds/cloud.rb', line 52 def name @name end |
#script_path ⇒ Object (readonly)
Returns the value of attribute script_path.
52 53 54 |
# File 'lib/clouds/cloud.rb', line 52 def script_path @script_path end |
Instance Method Details
#abbreviation(value = nil) ⇒ Object
Getter/setter for abbreviation which also sets default formatter options when an abbreviation is set.
117 118 119 120 121 122 123 |
# File 'lib/clouds/cloud.rb', line 117 def abbreviation(value = nil) unless value.to_s.empty? @abbreviation = value.to_s default_option([:cloud_metadata, :metadata_formatter, :formatted_path_prefix], "#{value.to_s.upcase}_") end @abbreviation end |
#build_metadata(kind) ⇒ Object
Executes a query for metadata and builds a metadata ‘tree’ according to the rules of provider and tree climber.
Parameters
- kind(Token)
-
must be one of [:cloud_metadata, :user_metadata]
Return
- metadata(Hash)
-
Hash-like metadata response
392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/clouds/cloud.rb', line 392 def (kind) @metadata_source_instance = create_dependency_type(kind, :metadata_source) unless @metadata_source_instance = create_dependency_type(kind, :metadata_tree_climber) provider = create_dependency_type(kind, :metadata_provider) provider.send(:metadata_source=, @metadata_source_instance) provider.send(:metadata_tree_climber=, ) provider.send(:raw_metadata_writer=, (kind)) # build return provider.send(:build_metadata) end |
#clear_state ⇒ Object
Attempts to clear any files generated by writers.
Return
always true
Raise
- CloudError
-
on failure to clean state
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/clouds/cloud.rb', line 363 def clear_state output_dir_paths = [] [:cloud_metadata, :user_metadata].each do |k| writers = create_dependency_type(k, :metadata_writers, WILDCARD) writers << (k) writers.each { |writer| output_dir_paths << writer.output_dir_path unless output_dir_paths.include?(writer.output_dir_path) } end last_exception = nil output_dir_paths.each do |output_dir_path| begin FileUtils.rm_rf(output_dir_path) if File.directory?(output_dir_path) rescue Exception => e last_exception = e end end fail(last_exception.) if last_exception return ActionResult.new rescue Exception => e return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.}") end |
#create_dependency_type(kind, category, dependency_type = nil) ⇒ Object
Creates the type using options specified by metadata kind, type category and specific type, if given.
Parameters
- kind(Token)
-
must be one of [:cloud_metadata, :user_metadata]
- category(Token)
-
category for dependency class
- type(String|Token)
-
specific type or nil
Return
- dependency(Object)
-
new instance of dependency class
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 |
# File 'lib/clouds/cloud.rb', line 455 def create_dependency_type(kind, category, dependency_type = nil) # support wildcard case for all dependency types in a category. kind = kind.to_sym category = category.to_sym if WILDCARD == dependency_type types = self.send(category) return types.map { |type| create_dependency_type(kind, category, type) } end # get specific type from category on cloud, if necessary. dependency_type = self.send(category) unless dependency_type raise NotImplementedError.new("The #{name.inspect} cloud has not declared a #{category} type.") unless dependency_type dependency_type = dependency_type.to_s = (kind, category, dependency_type) dependency_class = resolve_dependency(dependency_type) return dependency_class.new() end |
#default_option(path, default_value) ⇒ Object
Merges the given default option at the given depth in the options hash but only if the value is not set. Handles subhash merging by giving the existing option key/value pairs precedence.
Parameters
- path(Array|String)
-
path to option as an array of path elements or single
string which may contain forward slashes as element name delimiters.
- default_value(String)
-
default value to conditionally insert/merge or nil
430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
# File 'lib/clouds/cloud.rb', line 430 def default_option(path, default_value) # create subhashes to end of path. = @options path = path.to_s.split('/') unless path.kind_of?(Array) path[0..-2].each { |child| = [child] ||= Mash.new } last_child = path[-1] # ensure any existing options override defaults. if default_value && [last_child].respond_to?(:merge) [last_child] = default_value.dup.merge([last_child]) else [last_child] ||= default_value end end |
#dependencies(*args) ⇒ Object
Runtime cloud depedencies (loaded on demand).
137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/clouds/cloud.rb', line 137 def dependencies(*args) @dependencies ||= [] args.each do |dependency_type| unless @dependencies.include?(dependency_type) # Just-in-time require new dependency resolve_dependency(dependency_type) @dependencies << dependency_type end end @dependencies end |
#dependency_base_paths(*args) ⇒ Object
Base paths for runtime cloud depedencies in order of priority. Defaults to location of cloud module files.
127 128 129 130 131 132 133 134 |
# File 'lib/clouds/cloud.rb', line 127 def dependency_base_paths(*args) @dependency_base_paths ||= [] args.each do |path| path = relative_to_script_path(path) @dependency_base_paths << path unless @dependency_base_paths.include?(path) end @dependency_base_paths end |
#extend_cloud(cloud_name) ⇒ Object
Defines a base cloud type which the current instance extends. The base type is just-in-time evaluated into the current instance. The extended cloud must have been registered successfully.
Parameters
cloud_name(String|Token): name of cloud to extend
Return
always true
Raise
- UnknownCloud
-
on failure to find extended cloud
194 195 196 197 198 199 200 201 202 203 |
# File 'lib/clouds/cloud.rb', line 194 def extend_cloud(cloud_name) cloud_name = CloudFactory.normalize_cloud_name(cloud_name) unless @extended_clouds.include?(cloud_name) @extended_clouds << cloud_name script_path = CloudFactory.instance.registered_script_path(cloud_name) text = File.read(script_path) self.instance_eval(text) end true end |
#extension_script_base_paths(*args) ⇒ Object
Base paths for external scripts which extend methods of cloud object. Names of scripts become instance methods and can override the predefined cloud methods. The factory defaults to using any scripts in “<rs_root_path>/bin/<cloud alias(es)>” directories.
209 210 211 212 213 214 215 216 |
# File 'lib/clouds/cloud.rb', line 209 def extension_script_base_paths(*args) @extension_script_base_paths ||= [] args.each do |path| path = relative_to_script_path(path) @extension_script_base_paths << path unless @extension_script_base_paths.include?(path) end @extension_script_base_paths end |
#fail(message) ⇒ Object
Convenience method for failing to load or execute cloud definition.
Parameters
- message(String)
-
message
Raise
always CloudError
278 279 280 |
# File 'lib/clouds/cloud.rb', line 278 def fail() raise CloudError.new() end |
#finalize_default_options ⇒ Object
Provides final default options after cloud definition(s) have had a chance to set defaults. defaults are first-come-first-served so none should be set by initialize() (as was the case in RightLink v5.7)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/clouds/cloud.rb', line 83 def # writer defaults. default_option([:metadata_writers, :output_dir_path], RightScale::AgentConfig.cloud_state_dir) default_option([:cloud_metadata, :metadata_writers, :file_name_prefix], DEFAULT_CLOUD_METADATA_FILE_PREFIX) default_option([:user_metadata, :metadata_writers, :file_name_prefix], DEFAULT_USER_METADATA_FILE_PREFIX) # metadata roots are referenced by both sources and tree climber, but # legacy RightLink v5.7 behavior was to treat them as separate categories # of options which had to be defaulted separately. for RightLink v5.8+ # ensure cloud definitions only need to set metadata roots for sources # which require them. = option([:cloud_metadata, :metadata_tree_climber, :root_path]) || option([:metadata_source, :cloud_metadata_root_path]) || option(:cloud_metadata_root_path) || DEFAULT_CLOUD_METADATA_ROOT_PATH default_option([:cloud_metadata, :metadata_tree_climber, :root_path], ) default_option([:metadata_source, :cloud_metadata_root_path], ) default_option(:cloud_metadata_root_path, ) # uncategorized option, common to all types = option([:user_metadata, :metadata_tree_climber, :root_path]) || option([:metadata_source, :user_metadata_root_path]) || option(:user_metadata_root_path) || DEFAULT_USER_METADATA_ROOT_PATH default_option([:user_metadata, :metadata_tree_climber, :root_path], ) default_option([:metadata_source, :user_metadata_root_path], ) default_option(:user_metadata_root_path, ) # uncategorized option, common to all types end |
#is_current_cloud? ⇒ Boolean
Determines if the current instance is running on the cloud indicated by this object.
Return
- result(Boolean)
-
true if current cloud, false otherwise
257 258 259 |
# File 'lib/clouds/cloud.rb', line 257 def is_current_cloud? false # clouds cannot self-detect without a specific implementation end |
#logger ⇒ Object
Syntatic sugar for options, which should always be valid under normal circumstances.
113 |
# File 'lib/clouds/cloud.rb', line 113 def logger; @options[:logger]; end |
#metadata_formatter(type = nil) ⇒ Object
Dependency type for metadata formatter
219 220 221 222 |
# File 'lib/clouds/cloud.rb', line 219 def (type = nil) dependencies(type) if type @metadata_formatter ||= type || :metadata_formatter end |
#metadata_provider(type = nil) ⇒ Object
Dependency type for metadata provider
225 226 227 228 |
# File 'lib/clouds/cloud.rb', line 225 def (type = nil) dependencies(type) if type @metadata_provider ||= type || :metadata_provider end |
#metadata_source(type = nil) ⇒ Object
Dependency type for metadata source
231 232 233 234 |
# File 'lib/clouds/cloud.rb', line 231 def (type = nil) dependencies(type) if type @metadata_source ||= type || :metadata_source end |
#metadata_tree_climber(type = nil) ⇒ Object
Dependency type for metadata tree climber
237 238 239 240 |
# File 'lib/clouds/cloud.rb', line 237 def (type = nil) dependencies(type) if type @metadata_tree_climber ||= type || :metadata_tree_climber end |
#metadata_writers(*args) ⇒ Object
Dependency type for metadata writers. Note that the raw writer is automatic (writes raw responses using relative paths while data is being queried).
245 246 247 248 249 250 |
# File 'lib/clouds/cloud.rb', line 245 def (*args) dependencies(*args) @metadata_writers ||= [] args.each { || @metadata_writers << unless @metadata_writers.include?() } @metadata_writers end |
#option(path) ⇒ Object
Gets the option given by path, if it exists.
Parameters
- path(Array|String)
-
path to option as an array of path elements or single
string which may contain forward slashes as element name delimiters.
- default_value(String)
-
default value to conditionally insert/merge or nil
Return
- result(Object)
-
existing option or nil
413 414 415 416 417 418 419 420 |
# File 'lib/clouds/cloud.rb', line 413 def option(path) = @options path = path.to_s.split('/') unless path.kind_of?(Array) path[0..-2].each do |child| return nil unless ( = [child]) && .respond_to?(:has_key?) end [path[-1]] end |
#platform ⇒ Object
Convenience method for getting information about the current machine platform.
Return
- result(Boolean)
-
true if windows
287 288 289 |
# File 'lib/clouds/cloud.rb', line 287 def platform ::RightScale::Platform end |
#read_cloud_metadata(writer_type = RAW_METADATA_WRITER, subpath = nil) ⇒ Object
Convenience method for reading only cloud metdata.
345 |
# File 'lib/clouds/cloud.rb', line 345 def (writer_type = RAW_METADATA_WRITER, subpath = nil); (:cloud_metadata, writer_type, subpath); end |
#read_metadata(kind = :user_metadata, writer_type = RAW_METADATA_WRITER, subpath = nil) ⇒ Object
Reads the generated metadata file of the given kind and writer type.
Parameters
- kind(Symbol)
-
kind of metadata must be one of [:cloud_metadata, :user_metadata]
- writer_type(Symbol)
-
writer_type [RAW_METADATA_WRITER, …]
Return
- result(ActionResult)
-
action result
299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/clouds/cloud.rb', line 299 def (kind = :user_metadata, writer_type = RAW_METADATA_WRITER, subpath = nil) kind = kind.to_sym writer_type = writer_type.to_sym if RAW_METADATA_WRITER == writer_type reader = (kind) else reader = create_dependency_type(kind, :metadata_writers, writer_type) end output = reader.read(subpath) return ActionResult.new(:output => output) rescue Exception => e return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.}") end |
#read_user_metadata(writer_type = RAW_METADATA_WRITER, subpath = nil) ⇒ Object
Convenience method for reading only cloud metdata.
348 |
# File 'lib/clouds/cloud.rb', line 348 def (writer_type = RAW_METADATA_WRITER, subpath = nil); (:user_metadata, writer_type, subpath); end |
#resolve_dependency(dependency_type) ⇒ Object
Just-in-time requires a cloud’s dependency, which should include its relative location (and sub-type) in the dependency name (e.g. ‘metadata_sources/http_metadata_source’ => Sources::HttpMetadataSource). the dependency can also be in the RightScale module namespace because it begin evaluated there.
note that actual instantiation of the dependency is on-demand from the cloud type.
Parameters
- dependency_type(String|Token)
-
snake-case name for dependency type
Return
- dependency(Class)
-
resolved dependency class
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/clouds/cloud.rb', line 163 def resolve_dependency(dependency_type) dependency_class_name = dependency_type.to_s.camelize begin dependency_class = Class.class_eval(dependency_class_name) rescue NameError search_paths = (dependency_base_paths || []) + [File.dirname(__FILE__)] dependency_file_name = dependency_type + ".rb" search_paths.each do |search_path| file_path = File.normalize_path(File.join(search_path, dependency_file_name)) if File.file?(file_path) require File.normalize_path(File.join(search_path, dependency_type)) break end end dependency_class = Class.class_eval(dependency_class_name) end dependency_class end |
#update_details ⇒ Object
Updates the given node with any cloud-specific detailed information. Adds nothing by default. The ohai node can be retreived as option(:ohai) and any details can be added to the option(:ohai) node.
Return
always true
267 268 269 |
# File 'lib/clouds/cloud.rb', line 267 def update_details {} end |
#write_cloud_metadata ⇒ Object
Convenience method for writing only cloud metdata.
351 |
# File 'lib/clouds/cloud.rb', line 351 def ; (:cloud_metadata); end |
#write_metadata(kind = WILDCARD) ⇒ Object
Queries and writes current metadata to file.
Parameters
- kind(Symbol)
-
kind of metadata must be one of [:cloud_metadata, :user_metadata, WILDCARD]
Return
- result(ActionResult)
-
action result
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/clouds/cloud.rb', line 320 def (kind = WILDCARD) kind = kind.to_sym kinds = [:cloud_metadata, :user_metadata].select { |k| WILDCARD == kind || k == kind } kinds.each do |k| formatter = create_dependency_type(k, :metadata_formatter) writers = create_dependency_type(k, :metadata_writers, WILDCARD) = (k) unless .empty? = formatter.() writers.each { |writer| writer.write() } end end return ActionResult.new rescue Exception => e return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.}") ensure # release metadata source after querying all metadata. if @metadata_source_instance = @metadata_source_instance @metadata_source_instance = nil .finish end end |
#write_user_metadata ⇒ Object
Convenience method for writing only user metdata.
354 |
# File 'lib/clouds/cloud.rb', line 354 def ; (:user_metadata); end |