right_link 5.9.0
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/actors/agent_manager.rb +88 -0
- data/actors/instance_scheduler.rb +321 -0
- data/actors/instance_services.rb +64 -0
- data/actors/instance_setup.rb +567 -0
- data/bin/cloud +25 -0
- data/bin/cook_runner +44 -0
- data/bin/deploy +120 -0
- data/bin/enroll +385 -0
- data/bin/rad +32 -0
- data/bin/rchk +29 -0
- data/bin/rnac +39 -0
- data/bin/rs_connect +33 -0
- data/bin/rs_log_level +31 -0
- data/bin/rs_ohai +28 -0
- data/bin/rs_reenroll +31 -0
- data/bin/rs_run_recipe +34 -0
- data/bin/rs_run_right_script +34 -0
- data/bin/rs_shutdown +33 -0
- data/bin/rs_tag +33 -0
- data/bin/rs_thunk +33 -0
- data/bin/rstat +31 -0
- data/bin/system +16 -0
- data/ext/Rakefile +18 -0
- data/init/config.yml +5 -0
- data/init/init.rb +79 -0
- data/lib/chef/ohai_setup.rb +51 -0
- data/lib/chef/plugins/cloud.rb +91 -0
- data/lib/chef/plugins/cloudstack.rb +23 -0
- data/lib/chef/plugins/ec2.rb +23 -0
- data/lib/chef/plugins/linux/block_device2.rb +24 -0
- data/lib/chef/plugins/rackspace.rb +23 -0
- data/lib/chef/plugins/rightscale.rb +125 -0
- data/lib/chef/plugins/windows/network.rb +114 -0
- data/lib/chef/plugins.rb +74 -0
- data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
- data/lib/chef/providers/dns_resource.rb +100 -0
- data/lib/chef/providers/executable_schedule_provider.rb +70 -0
- data/lib/chef/providers/executable_schedule_resource.rb +144 -0
- data/lib/chef/providers/remote_recipe_provider.rb +86 -0
- data/lib/chef/providers/remote_recipe_resource.rb +101 -0
- data/lib/chef/providers/right_link_tag_provider.rb +73 -0
- data/lib/chef/providers/right_link_tag_resource.rb +59 -0
- data/lib/chef/providers/right_script_provider.rb +190 -0
- data/lib/chef/providers/right_script_resource.rb +113 -0
- data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
- data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
- data/lib/chef/providers/server_collection_provider.rb +66 -0
- data/lib/chef/providers/server_collection_resource.rb +93 -0
- data/lib/chef/providers/windows/powershell_provider.rb +151 -0
- data/lib/chef/providers/windows/powershell_resource.rb +111 -0
- data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
- data/lib/chef/right_providers.rb +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
- data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
- data/lib/chef/windows/chef_node_server.rb +463 -0
- data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
- data/lib/chef/windows/pipe_server.rb +283 -0
- data/lib/chef/windows/powershell_host.rb +285 -0
- data/lib/chef/windows/powershell_pipe_server.rb +136 -0
- data/lib/chef/windows/powershell_provider_base.rb +92 -0
- data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
- data/lib/clouds/cloud.rb +557 -0
- data/lib/clouds/cloud_factory.rb +250 -0
- data/lib/clouds/cloud_utilities.rb +244 -0
- data/lib/clouds/clouds/azure.rb +106 -0
- data/lib/clouds/clouds/cloudstack.rb +114 -0
- data/lib/clouds/clouds/ec2.rb +113 -0
- data/lib/clouds/clouds/eucalyptus.rb +46 -0
- data/lib/clouds/clouds/google.rb +102 -0
- data/lib/clouds/clouds/none.rb +76 -0
- data/lib/clouds/clouds/openstack.rb +30 -0
- data/lib/clouds/clouds/rackspace-ng.rb +54 -0
- data/lib/clouds/clouds/rackspace.rb +78 -0
- data/lib/clouds/clouds/softlayer.rb +91 -0
- data/lib/clouds/metadata_formatter.rb +108 -0
- data/lib/clouds/metadata_provider.rb +128 -0
- data/lib/clouds/metadata_source.rb +87 -0
- data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
- data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
- data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
- data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
- data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
- data/lib/clouds/metadata_tree_climber.rb +144 -0
- data/lib/clouds/metadata_writer.rb +155 -0
- data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
- data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
- data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
- data/lib/clouds/register_clouds.rb +34 -0
- data/lib/clouds.rb +32 -0
- data/lib/gem_dependencies.rb +83 -0
- data/lib/git_hooks/commit-msg.rb +7 -0
- data/lib/instance/agent_config.rb +168 -0
- data/lib/instance/agent_watcher.rb +233 -0
- data/lib/instance/audit_cook_stub.rb +104 -0
- data/lib/instance/audit_proxy.rb +247 -0
- data/lib/instance/bundle_queue.rb +104 -0
- data/lib/instance/cook/agent_connection.rb +109 -0
- data/lib/instance/cook/audit_logger.rb +165 -0
- data/lib/instance/cook/audit_stub.rb +142 -0
- data/lib/instance/cook/ca-bundle.crt +2794 -0
- data/lib/instance/cook/chef_state.rb +211 -0
- data/lib/instance/cook/cook.rb +306 -0
- data/lib/instance/cook/cook_state.rb +298 -0
- data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
- data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
- data/lib/instance/cook/executable_sequence.rb +765 -0
- data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
- data/lib/instance/cook/repose_downloader.rb +349 -0
- data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
- data/lib/instance/cook.rb +41 -0
- data/lib/instance/downloader.rb +208 -0
- data/lib/instance/duplicable.rb +67 -0
- data/lib/instance/exceptions.rb +49 -0
- data/lib/instance/executable_sequence_proxy.rb +278 -0
- data/lib/instance/instance_commands.rb +577 -0
- data/lib/instance/instance_state.rb +633 -0
- data/lib/instance/json_utilities.rb +102 -0
- data/lib/instance/login_manager.rb +533 -0
- data/lib/instance/login_user_manager.rb +522 -0
- data/lib/instance/message_encoder.rb +118 -0
- data/lib/instance/multi_thread_bundle_queue.rb +232 -0
- data/lib/instance/operation_context.rb +60 -0
- data/lib/instance/options_bag.rb +65 -0
- data/lib/instance/payload_formatter.rb +46 -0
- data/lib/instance/policy.rb +53 -0
- data/lib/instance/policy_audit.rb +100 -0
- data/lib/instance/policy_manager.rb +146 -0
- data/lib/instance/reenroll_manager.rb +104 -0
- data/lib/instance/right_scripts_cookbook.rb +181 -0
- data/lib/instance/shutdown_request.rb +221 -0
- data/lib/instance/single_thread_bundle_queue.rb +189 -0
- data/lib/instance/volume_management.rb +450 -0
- data/lib/instance.rb +50 -0
- data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
- data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
- data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
- data/lib/repo_conf_generators/rightscale_key.pub +17 -0
- data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
- data/lib/repo_conf_generators.rb +30 -0
- data/lib/run_shell.rb +28 -0
- data/scripts/agent_checker.rb +571 -0
- data/scripts/agent_controller.rb +247 -0
- data/scripts/agent_deployer.rb +148 -0
- data/scripts/bundle_runner.rb +336 -0
- data/scripts/cloud_controller.rb +176 -0
- data/scripts/log_level_manager.rb +142 -0
- data/scripts/ohai_runner.rb +33 -0
- data/scripts/reenroller.rb +193 -0
- data/scripts/server_importer.rb +293 -0
- data/scripts/shutdown_client.rb +183 -0
- data/scripts/system_configurator.rb +367 -0
- data/scripts/tagger.rb +381 -0
- data/scripts/thunker.rb +356 -0
- metadata +418 -0
data/lib/clouds/cloud.rb
ADDED
@@ -0,0 +1,557 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require 'extlib'
|
25
|
+
|
26
|
+
module RightScale
|
27
|
+
|
28
|
+
# Abstract base class for all clouds.
|
29
|
+
class Cloud
|
30
|
+
|
31
|
+
# wildcard used for some 'all kinds' selections.
|
32
|
+
WILDCARD = :*
|
33
|
+
|
34
|
+
# default tree-climber root paths for cloud/user metadata. they are basically
|
35
|
+
# placeholders for metadata sources which need to distinguish cloud from user
|
36
|
+
# but otherwise don't use real root paths.
|
37
|
+
DEFAULT_CLOUD_METADATA_ROOT_PATH = "cloud_metadata"
|
38
|
+
DEFAULT_USER_METADATA_ROOT_PATH = "user_metadata"
|
39
|
+
|
40
|
+
# default writer output file prefixes are based on EC2 legacy files.
|
41
|
+
DEFAULT_CLOUD_METADATA_FILE_PREFIX = 'meta-data'
|
42
|
+
DEFAULT_USER_METADATA_FILE_PREFIX = 'user-data'
|
43
|
+
|
44
|
+
# raw metadata writer is a special case and normally only invoked while
|
45
|
+
# metadata is being queried from source. it can also be referenced to read
|
46
|
+
# back the metadata in raw form.
|
47
|
+
RAW_METADATA_WRITER = :raw
|
48
|
+
|
49
|
+
# exceptions
|
50
|
+
class CloudError < Exception; end
|
51
|
+
|
52
|
+
attr_reader :name, :script_path, :extended_clouds
|
53
|
+
|
54
|
+
# Return type for any cloud action (e.g. write_metadata).
|
55
|
+
class ActionResult
|
56
|
+
attr_reader :error, :exitstatus, :output
|
57
|
+
|
58
|
+
def initialize(options = {})
|
59
|
+
@error = options[:error]
|
60
|
+
@exitstatus = options[:exitstatus] || 0
|
61
|
+
@output = options[:output]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Initializer.
|
66
|
+
#
|
67
|
+
# === Parameters
|
68
|
+
# options(Hash):: options grab bag used to configure cloud and dependencies.
|
69
|
+
def initialize(options)
|
70
|
+
raise ArgumentError.new("options[:name] is required") unless @name = options[:name]
|
71
|
+
raise ArgumentError.new("options[:script_path] is required") unless @script_path = options[:script_path]
|
72
|
+
|
73
|
+
# break options lineage and use Mash to handle keys as strings or tokens.
|
74
|
+
# note that this is not a deep copy as :ohai is an option representing the
|
75
|
+
# full ohai node in at least one use case.
|
76
|
+
@options = Mash.new(options)
|
77
|
+
@extended_clouds = []
|
78
|
+
end
|
79
|
+
|
80
|
+
# Provides final default options after cloud definition(s) have had a chance
|
81
|
+
# to set defaults. defaults are first-come-first-served so none should be
|
82
|
+
# set by initialize() (as was the case in RightLink v5.7)
|
83
|
+
def finalize_default_options
|
84
|
+
# writer defaults.
|
85
|
+
default_option([:metadata_writers, :output_dir_path], RightScale::AgentConfig.cloud_state_dir)
|
86
|
+
default_option([:cloud_metadata, :metadata_writers, :file_name_prefix], DEFAULT_CLOUD_METADATA_FILE_PREFIX)
|
87
|
+
default_option([:user_metadata, :metadata_writers, :file_name_prefix], DEFAULT_USER_METADATA_FILE_PREFIX)
|
88
|
+
|
89
|
+
# metadata roots are referenced by both sources and tree climber, but
|
90
|
+
# legacy RightLink v5.7 behavior was to treat them as separate categories
|
91
|
+
# of options which had to be defaulted separately. for RightLink v5.8+
|
92
|
+
# ensure cloud definitions only need to set metadata roots for sources
|
93
|
+
# which require them.
|
94
|
+
cloud_metadata_root_path = option([:cloud_metadata, :metadata_tree_climber, :root_path]) ||
|
95
|
+
option([:metadata_source, :cloud_metadata_root_path]) ||
|
96
|
+
option(:cloud_metadata_root_path) ||
|
97
|
+
DEFAULT_CLOUD_METADATA_ROOT_PATH
|
98
|
+
default_option([:cloud_metadata, :metadata_tree_climber, :root_path], cloud_metadata_root_path)
|
99
|
+
default_option([:metadata_source, :cloud_metadata_root_path], cloud_metadata_root_path)
|
100
|
+
default_option(:cloud_metadata_root_path, cloud_metadata_root_path) # uncategorized option, common to all types
|
101
|
+
|
102
|
+
user_metadata_root_path = option([:user_metadata, :metadata_tree_climber, :root_path]) ||
|
103
|
+
option([:metadata_source, :user_metadata_root_path]) ||
|
104
|
+
option(:user_metadata_root_path) ||
|
105
|
+
DEFAULT_USER_METADATA_ROOT_PATH
|
106
|
+
default_option([:user_metadata, :metadata_tree_climber, :root_path], user_metadata_root_path)
|
107
|
+
default_option([:metadata_source, :user_metadata_root_path], user_metadata_root_path)
|
108
|
+
default_option(:user_metadata_root_path, user_metadata_root_path) # uncategorized option, common to all types
|
109
|
+
end
|
110
|
+
|
111
|
+
# Syntatic sugar for options[:logger], which should always be valid under
|
112
|
+
# normal circumstances.
|
113
|
+
def logger; @options[:logger]; end
|
114
|
+
|
115
|
+
# Getter/setter for abbreviation which also sets default formatter options
|
116
|
+
# when an abbreviation is set.
|
117
|
+
def abbreviation(value = nil)
|
118
|
+
unless value.to_s.empty?
|
119
|
+
@abbreviation = value.to_s
|
120
|
+
default_option([:cloud_metadata, :metadata_formatter, :formatted_path_prefix], "#{value.to_s.upcase}_")
|
121
|
+
end
|
122
|
+
@abbreviation
|
123
|
+
end
|
124
|
+
|
125
|
+
# Base paths for runtime cloud depedencies in order of priority. Defaults
|
126
|
+
# to location of cloud module files.
|
127
|
+
def dependency_base_paths(*args)
|
128
|
+
@dependency_base_paths ||= []
|
129
|
+
args.each do |path|
|
130
|
+
path = relative_to_script_path(path)
|
131
|
+
@dependency_base_paths << path unless @dependency_base_paths.include?(path)
|
132
|
+
end
|
133
|
+
@dependency_base_paths
|
134
|
+
end
|
135
|
+
|
136
|
+
# Runtime cloud depedencies (loaded on demand).
|
137
|
+
def dependencies(*args)
|
138
|
+
@dependencies ||= []
|
139
|
+
args.each do |dependency_type|
|
140
|
+
unless @dependencies.include?(dependency_type)
|
141
|
+
# Just-in-time require new dependency
|
142
|
+
resolve_dependency(dependency_type)
|
143
|
+
@dependencies << dependency_type
|
144
|
+
end
|
145
|
+
end
|
146
|
+
@dependencies
|
147
|
+
end
|
148
|
+
|
149
|
+
# Just-in-time requires a cloud's dependency, which should include its
|
150
|
+
# relative location (and sub-type) in the dependency name
|
151
|
+
# (e.g. 'metadata_sources/http_metadata_source' => Sources::HttpMetadataSource).
|
152
|
+
# the dependency can also be in the RightScale module namespace because it
|
153
|
+
# begin evaluated there.
|
154
|
+
#
|
155
|
+
# note that actual instantiation of the dependency is on-demand from the
|
156
|
+
# cloud type.
|
157
|
+
#
|
158
|
+
# === Parameters
|
159
|
+
# dependency_type(String|Token):: snake-case name for dependency type
|
160
|
+
#
|
161
|
+
# === Return
|
162
|
+
# dependency(Class):: resolved dependency class
|
163
|
+
def resolve_dependency(dependency_type)
|
164
|
+
dependency_class_name = dependency_type.to_s.camelize
|
165
|
+
begin
|
166
|
+
dependency_class = Class.class_eval(dependency_class_name)
|
167
|
+
rescue NameError
|
168
|
+
search_paths = (dependency_base_paths || []) + [File.dirname(__FILE__)]
|
169
|
+
dependency_file_name = dependency_type + ".rb"
|
170
|
+
search_paths.each do |search_path|
|
171
|
+
file_path = File.normalize_path(File.join(search_path, dependency_file_name))
|
172
|
+
if File.file?(file_path)
|
173
|
+
require File.normalize_path(File.join(search_path, dependency_type))
|
174
|
+
break
|
175
|
+
end
|
176
|
+
end
|
177
|
+
dependency_class = Class.class_eval(dependency_class_name)
|
178
|
+
end
|
179
|
+
dependency_class
|
180
|
+
end
|
181
|
+
|
182
|
+
# Defines a base cloud type which the current instance extends. The base
|
183
|
+
# type is just-in-time evaluated into the current instance. The extended
|
184
|
+
# cloud must have been registered successfully.
|
185
|
+
#
|
186
|
+
# === Parameters
|
187
|
+
# cloud_name(String|Token): name of cloud to extend
|
188
|
+
#
|
189
|
+
# === Return
|
190
|
+
# always true
|
191
|
+
#
|
192
|
+
# === Raise
|
193
|
+
# UnknownCloud:: on failure to find extended cloud
|
194
|
+
def extend_cloud(cloud_name)
|
195
|
+
cloud_name = CloudFactory.normalize_cloud_name(cloud_name)
|
196
|
+
unless @extended_clouds.include?(cloud_name)
|
197
|
+
@extended_clouds << cloud_name
|
198
|
+
script_path = CloudFactory.instance.registered_script_path(cloud_name)
|
199
|
+
text = File.read(script_path)
|
200
|
+
self.instance_eval(text)
|
201
|
+
end
|
202
|
+
true
|
203
|
+
end
|
204
|
+
|
205
|
+
# Base paths for external scripts which extend methods of cloud object.
|
206
|
+
# Names of scripts become instance methods and can override the predefined
|
207
|
+
# cloud methods. The factory defaults to using any scripts in
|
208
|
+
# "<rs_root_path>/bin/<cloud alias(es)>" directories.
|
209
|
+
def extension_script_base_paths(*args)
|
210
|
+
@extension_script_base_paths ||= []
|
211
|
+
args.each do |path|
|
212
|
+
path = relative_to_script_path(path)
|
213
|
+
@extension_script_base_paths << path unless @extension_script_base_paths.include?(path)
|
214
|
+
end
|
215
|
+
@extension_script_base_paths
|
216
|
+
end
|
217
|
+
|
218
|
+
# Dependency type for metadata formatter
|
219
|
+
def metadata_formatter(type = nil)
|
220
|
+
dependencies(type) if type
|
221
|
+
@metadata_formatter ||= type || :metadata_formatter
|
222
|
+
end
|
223
|
+
|
224
|
+
# Dependency type for metadata provider
|
225
|
+
def metadata_provider(type = nil)
|
226
|
+
dependencies(type) if type
|
227
|
+
@metadata_provider ||= type || :metadata_provider
|
228
|
+
end
|
229
|
+
|
230
|
+
# Dependency type for metadata source
|
231
|
+
def metadata_source(type = nil)
|
232
|
+
dependencies(type) if type
|
233
|
+
@metadata_source ||= type || :metadata_source
|
234
|
+
end
|
235
|
+
|
236
|
+
# Dependency type for metadata tree climber
|
237
|
+
def metadata_tree_climber(type = nil)
|
238
|
+
dependencies(type) if type
|
239
|
+
@metadata_tree_climber ||= type || :metadata_tree_climber
|
240
|
+
end
|
241
|
+
|
242
|
+
# Dependency type for metadata writers. Note that the raw writer is
|
243
|
+
# automatic (writes raw responses using relative paths while data is being
|
244
|
+
# queried).
|
245
|
+
def metadata_writers(*args)
|
246
|
+
dependencies(*args)
|
247
|
+
@metadata_writers ||= []
|
248
|
+
args.each { |metadata_writer| @metadata_writers << metadata_writer unless @metadata_writers.include?(metadata_writer) }
|
249
|
+
@metadata_writers
|
250
|
+
end
|
251
|
+
|
252
|
+
# Determines if the current instance is running on the cloud indicated by
|
253
|
+
# this object.
|
254
|
+
#
|
255
|
+
# === Return
|
256
|
+
# result(Boolean):: true if current cloud, false otherwise
|
257
|
+
def is_current_cloud?
|
258
|
+
false # clouds cannot self-detect without a specific implementation
|
259
|
+
end
|
260
|
+
|
261
|
+
# Updates the given node with any cloud-specific detailed information. Adds
|
262
|
+
# nothing by default. The ohai node can be retreived as option(:ohai) and
|
263
|
+
# any details can be added to the option(:ohai)[name] node.
|
264
|
+
#
|
265
|
+
# === Return
|
266
|
+
# always true
|
267
|
+
def update_details
|
268
|
+
{}
|
269
|
+
end
|
270
|
+
|
271
|
+
# Convenience method for failing to load or execute cloud definition.
|
272
|
+
#
|
273
|
+
# === Parameters
|
274
|
+
# message(String):: message
|
275
|
+
#
|
276
|
+
# === Raise
|
277
|
+
# always CloudError
|
278
|
+
def fail(message)
|
279
|
+
raise CloudError.new(message)
|
280
|
+
end
|
281
|
+
|
282
|
+
# Convenience method for getting information about the current machine
|
283
|
+
# platform.
|
284
|
+
#
|
285
|
+
# === Return
|
286
|
+
# result(Boolean):: true if windows
|
287
|
+
def platform
|
288
|
+
::RightScale::Platform
|
289
|
+
end
|
290
|
+
|
291
|
+
# Reads the generated metadata file of the given kind and writer type.
|
292
|
+
#
|
293
|
+
# === Parameters
|
294
|
+
# kind(Symbol):: kind of metadata must be one of [:cloud_metadata, :user_metadata]
|
295
|
+
# writer_type(Symbol):: writer_type [RAW_METADATA_WRITER, ...]
|
296
|
+
#
|
297
|
+
# === Return
|
298
|
+
# result(ActionResult):: action result
|
299
|
+
def read_metadata(kind = :user_metadata, writer_type = RAW_METADATA_WRITER, subpath = nil)
|
300
|
+
kind = kind.to_sym
|
301
|
+
writer_type = writer_type.to_sym
|
302
|
+
if RAW_METADATA_WRITER == writer_type
|
303
|
+
reader = raw_metadata_writer(kind)
|
304
|
+
else
|
305
|
+
reader = create_dependency_type(kind, :metadata_writers, writer_type)
|
306
|
+
end
|
307
|
+
output = reader.read(subpath)
|
308
|
+
return ActionResult.new(:output => output)
|
309
|
+
rescue Exception => e
|
310
|
+
return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.message}")
|
311
|
+
end
|
312
|
+
|
313
|
+
# Queries and writes current metadata to file.
|
314
|
+
#
|
315
|
+
# === Parameters
|
316
|
+
# kind(Symbol):: kind of metadata must be one of [:cloud_metadata, :user_metadata, WILDCARD]
|
317
|
+
#
|
318
|
+
# === Return
|
319
|
+
# result(ActionResult):: action result
|
320
|
+
def write_metadata(kind = WILDCARD)
|
321
|
+
kind = kind.to_sym
|
322
|
+
kinds = [:cloud_metadata, :user_metadata].select { |k| WILDCARD == kind || k == kind }
|
323
|
+
kinds.each do |k|
|
324
|
+
formatter = create_dependency_type(k, :metadata_formatter)
|
325
|
+
writers = create_dependency_type(k, :metadata_writers, WILDCARD)
|
326
|
+
metadata = build_metadata(k)
|
327
|
+
unless metadata.empty?
|
328
|
+
metadata = formatter.format_metadata(metadata)
|
329
|
+
writers.each { |writer| writer.write(metadata) }
|
330
|
+
end
|
331
|
+
end
|
332
|
+
return ActionResult.new
|
333
|
+
rescue Exception => e
|
334
|
+
return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.message}")
|
335
|
+
ensure
|
336
|
+
# release metadata source after querying all metadata.
|
337
|
+
if @metadata_source_instance
|
338
|
+
temp_metadata_source = @metadata_source_instance
|
339
|
+
@metadata_source_instance = nil
|
340
|
+
temp_metadata_source.finish
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
# Convenience method for reading only cloud metdata.
|
345
|
+
def read_cloud_metadata(writer_type = RAW_METADATA_WRITER, subpath = nil); read_metadata(:cloud_metadata, writer_type, subpath); end
|
346
|
+
|
347
|
+
# Convenience method for reading only cloud metdata.
|
348
|
+
def read_user_metadata(writer_type = RAW_METADATA_WRITER, subpath = nil); read_metadata(:user_metadata, writer_type, subpath); end
|
349
|
+
|
350
|
+
# Convenience method for writing only cloud metdata.
|
351
|
+
def write_cloud_metadata; write_metadata(:cloud_metadata); end
|
352
|
+
|
353
|
+
# Convenience method for writing only user metdata.
|
354
|
+
def write_user_metadata; write_metadata(:user_metadata); end
|
355
|
+
|
356
|
+
# Attempts to clear any files generated by writers.
|
357
|
+
#
|
358
|
+
# === Return
|
359
|
+
# always true
|
360
|
+
#
|
361
|
+
# === Raise
|
362
|
+
# CloudError:: on failure to clean state
|
363
|
+
def clear_state
|
364
|
+
output_dir_paths = []
|
365
|
+
[:cloud_metadata, :user_metadata].each do |k|
|
366
|
+
writers = create_dependency_type(k, :metadata_writers, WILDCARD)
|
367
|
+
writers << raw_metadata_writer(k)
|
368
|
+
writers.each { |writer| output_dir_paths << writer.output_dir_path unless output_dir_paths.include?(writer.output_dir_path) }
|
369
|
+
end
|
370
|
+
last_exception = nil
|
371
|
+
output_dir_paths.each do |output_dir_path|
|
372
|
+
begin
|
373
|
+
FileUtils.rm_rf(output_dir_path) if File.directory?(output_dir_path)
|
374
|
+
rescue Exception => e
|
375
|
+
last_exception = e
|
376
|
+
end
|
377
|
+
end
|
378
|
+
fail(last_exception.message) if last_exception
|
379
|
+
return ActionResult.new
|
380
|
+
rescue Exception => e
|
381
|
+
return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.message}")
|
382
|
+
end
|
383
|
+
|
384
|
+
# Executes a query for metadata and builds a metadata 'tree' according to
|
385
|
+
# the rules of provider and tree climber.
|
386
|
+
#
|
387
|
+
# === Parameters
|
388
|
+
# kind(Token):: must be one of [:cloud_metadata, :user_metadata]
|
389
|
+
#
|
390
|
+
# === Return
|
391
|
+
# metadata(Hash):: Hash-like metadata response
|
392
|
+
def build_metadata(kind)
|
393
|
+
@metadata_source_instance = create_dependency_type(kind, :metadata_source) unless @metadata_source_instance
|
394
|
+
metadata_tree_climber = create_dependency_type(kind, :metadata_tree_climber)
|
395
|
+
provider = create_dependency_type(kind, :metadata_provider)
|
396
|
+
provider.send(:metadata_source=, @metadata_source_instance)
|
397
|
+
provider.send(:metadata_tree_climber=, metadata_tree_climber)
|
398
|
+
provider.send(:raw_metadata_writer=, raw_metadata_writer(kind))
|
399
|
+
|
400
|
+
# build
|
401
|
+
return provider.send(:build_metadata)
|
402
|
+
end
|
403
|
+
|
404
|
+
# Gets the option given by path, if it exists.
|
405
|
+
#
|
406
|
+
# === Parameters
|
407
|
+
# path(Array|String):: path to option as an array of path elements or single
|
408
|
+
# string which may contain forward slashes as element name delimiters.
|
409
|
+
# default_value(String):: default value to conditionally insert/merge or nil
|
410
|
+
#
|
411
|
+
# === Return
|
412
|
+
# result(Object):: existing option or nil
|
413
|
+
def option(path)
|
414
|
+
options = @options
|
415
|
+
path = path.to_s.split('/') unless path.kind_of?(Array)
|
416
|
+
path[0..-2].each do |child|
|
417
|
+
return nil unless (options = options[child]) && options.respond_to?(:has_key?)
|
418
|
+
end
|
419
|
+
options[path[-1]]
|
420
|
+
end
|
421
|
+
|
422
|
+
# Merges the given default option at the given depth in the options hash
|
423
|
+
# but only if the value is not set. Handles subhash merging by giving the
|
424
|
+
# existing option key/value pairs precedence.
|
425
|
+
#
|
426
|
+
# === Parameters
|
427
|
+
# path(Array|String):: path to option as an array of path elements or single
|
428
|
+
# string which may contain forward slashes as element name delimiters.
|
429
|
+
# default_value(String):: default value to conditionally insert/merge or nil
|
430
|
+
def default_option(path, default_value)
|
431
|
+
# create subhashes to end of path.
|
432
|
+
options = @options
|
433
|
+
path = path.to_s.split('/') unless path.kind_of?(Array)
|
434
|
+
path[0..-2].each { |child| options = options[child] ||= Mash.new }
|
435
|
+
last_child = path[-1]
|
436
|
+
|
437
|
+
# ensure any existing options override defaults.
|
438
|
+
if default_value && options[last_child].respond_to?(:merge)
|
439
|
+
options[last_child] = default_value.dup.merge(options[last_child])
|
440
|
+
else
|
441
|
+
options[last_child] ||= default_value
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# Creates the type using options specified by metadata kind, type category
|
446
|
+
# and specific type, if given.
|
447
|
+
#
|
448
|
+
# === Parameters
|
449
|
+
# kind(Token):: must be one of [:cloud_metadata, :user_metadata]
|
450
|
+
# category(Token):: category for dependency class
|
451
|
+
# type(String|Token):: specific type or nil
|
452
|
+
#
|
453
|
+
# === Return
|
454
|
+
# dependency(Object):: new instance of dependency class
|
455
|
+
def create_dependency_type(kind, category, dependency_type = nil)
|
456
|
+
# support wildcard case for all dependency types in a category.
|
457
|
+
kind = kind.to_sym
|
458
|
+
category = category.to_sym
|
459
|
+
if WILDCARD == dependency_type
|
460
|
+
types = self.send(category)
|
461
|
+
return types.map { |type| create_dependency_type(kind, category, type) }
|
462
|
+
end
|
463
|
+
|
464
|
+
# get specific type from category on cloud, if necessary.
|
465
|
+
dependency_type = self.send(category) unless dependency_type
|
466
|
+
raise NotImplementedError.new("The #{name.inspect} cloud has not declared a #{category} type.") unless dependency_type
|
467
|
+
dependency_type = dependency_type.to_s
|
468
|
+
|
469
|
+
options = resolve_options(kind, category, dependency_type)
|
470
|
+
dependency_class = resolve_dependency(dependency_type)
|
471
|
+
return dependency_class.new(options)
|
472
|
+
end
|
473
|
+
|
474
|
+
protected
|
475
|
+
|
476
|
+
# Resolve options to pass to new object, giving precedency to most
|
477
|
+
# specific options based on kind, category and type.
|
478
|
+
#
|
479
|
+
# === Parameters
|
480
|
+
# kind(Token):: must be one of [:cloud_metadata, :user_metadata]
|
481
|
+
# category(Token):: category for dependency class
|
482
|
+
# type(String|Token):: specific type
|
483
|
+
#
|
484
|
+
# === Return
|
485
|
+
# options(Hash):: resolved options
|
486
|
+
def resolve_options(kind, category, type)
|
487
|
+
# remove any module reference for type when finding options.
|
488
|
+
type = type.to_s.gsub(/^.*\//, '').to_sym
|
489
|
+
options = @options[category] ? Mash.new(@options[category]) : Mash.new
|
490
|
+
options = options.merge(@options[category][type]) if @options[category] && @options[category][type]
|
491
|
+
if @options[kind] && @options[kind][category]
|
492
|
+
options = options.merge(@options[kind][category])
|
493
|
+
options = options.merge(@options[kind][category][type]) if @options[kind][category][type]
|
494
|
+
end
|
495
|
+
|
496
|
+
# set special options which should be available to all categories.
|
497
|
+
options[:cloud] = self
|
498
|
+
options[:logger] ||= @options[:logger]
|
499
|
+
options[:cloud_metadata_root_path] ||= @options[:cloud_metadata_root_path]
|
500
|
+
options[:user_metadata_root_path] ||= @options[:user_metadata_root_path]
|
501
|
+
|
502
|
+
return options
|
503
|
+
end
|
504
|
+
|
505
|
+
# Creates the internal-use raw metadata writer.
|
506
|
+
def raw_metadata_writer(kind)
|
507
|
+
options = resolve_options(kind, :metadata_writers, RAW_METADATA_WRITER)
|
508
|
+
return MetadataWriter.new(options)
|
509
|
+
end
|
510
|
+
|
511
|
+
# Called internally to execute a cloud extension script with the given
|
512
|
+
# command-line arguments, if any. It is generally assumed scripts will not
|
513
|
+
# exit until finished and will read any instance-specific information from
|
514
|
+
# the system or from the output of write_metadata.
|
515
|
+
#
|
516
|
+
# === Parameters
|
517
|
+
# script_path(String):: path to script to execute
|
518
|
+
# arguments(Array):: arguments for script command line or empty
|
519
|
+
#
|
520
|
+
# === Return
|
521
|
+
# result(ActionResult):: action result
|
522
|
+
def execute_script(script_path, *arguments)
|
523
|
+
# If we are running a ruby script, use our own interpreter
|
524
|
+
if File.extname(script_path) == '.rb'
|
525
|
+
cmd = ::RightScale::Platform.shell.format_executable_command(
|
526
|
+
RightScale::AgentConfig.ruby_cmd,
|
527
|
+
*([script_path] + arguments))
|
528
|
+
else
|
529
|
+
cmd = ::RightScale::Platform.shell.format_shell_command(
|
530
|
+
script_path,
|
531
|
+
*arguments)
|
532
|
+
end
|
533
|
+
output = `#{cmd}`
|
534
|
+
return ActionResult.new(:exitstatus => $?.exitstatus, :output => output)
|
535
|
+
rescue Exception => e
|
536
|
+
return ActionResult.new(:exitstatus => 1, :error => "ERROR: #{e.message}")
|
537
|
+
end
|
538
|
+
|
539
|
+
# make the given path relative to this cloud's DSL script path only if the
|
540
|
+
# path is not already absolute.
|
541
|
+
#
|
542
|
+
# === Parameters
|
543
|
+
# path(String):: absolute or relative path
|
544
|
+
#
|
545
|
+
# === Return
|
546
|
+
# result(String):: absolute path
|
547
|
+
def relative_to_script_path(path)
|
548
|
+
path = path.gsub("\\", '/')
|
549
|
+
unless path == File.expand_path(path)
|
550
|
+
path = File.normalize_path(File.join(File.dirname(@script_path), path))
|
551
|
+
end
|
552
|
+
path
|
553
|
+
end
|
554
|
+
|
555
|
+
end # Cloud
|
556
|
+
|
557
|
+
end # RightScale
|