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.
Files changed (199) hide show
  1. data/actors/agent_manager.rb +88 -0
  2. data/actors/instance_scheduler.rb +321 -0
  3. data/actors/instance_services.rb +64 -0
  4. data/actors/instance_setup.rb +567 -0
  5. data/bin/cloud +25 -0
  6. data/bin/cook_runner +44 -0
  7. data/bin/deploy +120 -0
  8. data/bin/enroll +385 -0
  9. data/bin/rad +32 -0
  10. data/bin/rchk +29 -0
  11. data/bin/rnac +39 -0
  12. data/bin/rs_connect +33 -0
  13. data/bin/rs_log_level +31 -0
  14. data/bin/rs_ohai +28 -0
  15. data/bin/rs_reenroll +31 -0
  16. data/bin/rs_run_recipe +34 -0
  17. data/bin/rs_run_right_script +34 -0
  18. data/bin/rs_shutdown +33 -0
  19. data/bin/rs_tag +33 -0
  20. data/bin/rs_thunk +33 -0
  21. data/bin/rstat +31 -0
  22. data/bin/system +16 -0
  23. data/ext/Rakefile +18 -0
  24. data/init/config.yml +5 -0
  25. data/init/init.rb +79 -0
  26. data/lib/chef/ohai_setup.rb +51 -0
  27. data/lib/chef/plugins/cloud.rb +91 -0
  28. data/lib/chef/plugins/cloudstack.rb +23 -0
  29. data/lib/chef/plugins/ec2.rb +23 -0
  30. data/lib/chef/plugins/linux/block_device2.rb +24 -0
  31. data/lib/chef/plugins/rackspace.rb +23 -0
  32. data/lib/chef/plugins/rightscale.rb +125 -0
  33. data/lib/chef/plugins/windows/network.rb +114 -0
  34. data/lib/chef/plugins.rb +74 -0
  35. data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
  36. data/lib/chef/providers/dns_resource.rb +100 -0
  37. data/lib/chef/providers/executable_schedule_provider.rb +70 -0
  38. data/lib/chef/providers/executable_schedule_resource.rb +144 -0
  39. data/lib/chef/providers/remote_recipe_provider.rb +86 -0
  40. data/lib/chef/providers/remote_recipe_resource.rb +101 -0
  41. data/lib/chef/providers/right_link_tag_provider.rb +73 -0
  42. data/lib/chef/providers/right_link_tag_resource.rb +59 -0
  43. data/lib/chef/providers/right_script_provider.rb +190 -0
  44. data/lib/chef/providers/right_script_resource.rb +113 -0
  45. data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
  46. data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
  47. data/lib/chef/providers/server_collection_provider.rb +66 -0
  48. data/lib/chef/providers/server_collection_resource.rb +93 -0
  49. data/lib/chef/providers/windows/powershell_provider.rb +151 -0
  50. data/lib/chef/providers/windows/powershell_resource.rb +111 -0
  51. data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
  52. data/lib/chef/right_providers.rb +55 -0
  53. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
  54. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
  55. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
  56. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
  57. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
  58. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
  59. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
  60. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
  61. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
  62. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
  63. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
  64. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
  65. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
  66. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
  67. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
  68. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
  69. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
  70. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
  71. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
  72. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
  73. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
  74. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  75. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
  76. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
  77. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
  78. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
  79. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
  80. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
  81. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
  82. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
  83. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
  84. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
  85. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
  86. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
  87. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
  88. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
  89. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
  90. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
  91. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
  92. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
  93. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  94. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
  95. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
  96. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
  97. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
  98. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
  99. data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
  100. data/lib/chef/windows/chef_node_server.rb +463 -0
  101. data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
  102. data/lib/chef/windows/pipe_server.rb +283 -0
  103. data/lib/chef/windows/powershell_host.rb +285 -0
  104. data/lib/chef/windows/powershell_pipe_server.rb +136 -0
  105. data/lib/chef/windows/powershell_provider_base.rb +92 -0
  106. data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
  107. data/lib/clouds/cloud.rb +557 -0
  108. data/lib/clouds/cloud_factory.rb +250 -0
  109. data/lib/clouds/cloud_utilities.rb +244 -0
  110. data/lib/clouds/clouds/azure.rb +106 -0
  111. data/lib/clouds/clouds/cloudstack.rb +114 -0
  112. data/lib/clouds/clouds/ec2.rb +113 -0
  113. data/lib/clouds/clouds/eucalyptus.rb +46 -0
  114. data/lib/clouds/clouds/google.rb +102 -0
  115. data/lib/clouds/clouds/none.rb +76 -0
  116. data/lib/clouds/clouds/openstack.rb +30 -0
  117. data/lib/clouds/clouds/rackspace-ng.rb +54 -0
  118. data/lib/clouds/clouds/rackspace.rb +78 -0
  119. data/lib/clouds/clouds/softlayer.rb +91 -0
  120. data/lib/clouds/metadata_formatter.rb +108 -0
  121. data/lib/clouds/metadata_provider.rb +128 -0
  122. data/lib/clouds/metadata_source.rb +87 -0
  123. data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
  124. data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
  125. data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
  126. data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
  127. data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
  128. data/lib/clouds/metadata_tree_climber.rb +144 -0
  129. data/lib/clouds/metadata_writer.rb +155 -0
  130. data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
  131. data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
  132. data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
  133. data/lib/clouds/register_clouds.rb +34 -0
  134. data/lib/clouds.rb +32 -0
  135. data/lib/gem_dependencies.rb +83 -0
  136. data/lib/git_hooks/commit-msg.rb +7 -0
  137. data/lib/instance/agent_config.rb +168 -0
  138. data/lib/instance/agent_watcher.rb +233 -0
  139. data/lib/instance/audit_cook_stub.rb +104 -0
  140. data/lib/instance/audit_proxy.rb +247 -0
  141. data/lib/instance/bundle_queue.rb +104 -0
  142. data/lib/instance/cook/agent_connection.rb +109 -0
  143. data/lib/instance/cook/audit_logger.rb +165 -0
  144. data/lib/instance/cook/audit_stub.rb +142 -0
  145. data/lib/instance/cook/ca-bundle.crt +2794 -0
  146. data/lib/instance/cook/chef_state.rb +211 -0
  147. data/lib/instance/cook/cook.rb +306 -0
  148. data/lib/instance/cook/cook_state.rb +298 -0
  149. data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
  150. data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
  151. data/lib/instance/cook/executable_sequence.rb +765 -0
  152. data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
  153. data/lib/instance/cook/repose_downloader.rb +349 -0
  154. data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
  155. data/lib/instance/cook.rb +41 -0
  156. data/lib/instance/downloader.rb +208 -0
  157. data/lib/instance/duplicable.rb +67 -0
  158. data/lib/instance/exceptions.rb +49 -0
  159. data/lib/instance/executable_sequence_proxy.rb +278 -0
  160. data/lib/instance/instance_commands.rb +577 -0
  161. data/lib/instance/instance_state.rb +633 -0
  162. data/lib/instance/json_utilities.rb +102 -0
  163. data/lib/instance/login_manager.rb +533 -0
  164. data/lib/instance/login_user_manager.rb +522 -0
  165. data/lib/instance/message_encoder.rb +118 -0
  166. data/lib/instance/multi_thread_bundle_queue.rb +232 -0
  167. data/lib/instance/operation_context.rb +60 -0
  168. data/lib/instance/options_bag.rb +65 -0
  169. data/lib/instance/payload_formatter.rb +46 -0
  170. data/lib/instance/policy.rb +53 -0
  171. data/lib/instance/policy_audit.rb +100 -0
  172. data/lib/instance/policy_manager.rb +146 -0
  173. data/lib/instance/reenroll_manager.rb +104 -0
  174. data/lib/instance/right_scripts_cookbook.rb +181 -0
  175. data/lib/instance/shutdown_request.rb +221 -0
  176. data/lib/instance/single_thread_bundle_queue.rb +189 -0
  177. data/lib/instance/volume_management.rb +450 -0
  178. data/lib/instance.rb +50 -0
  179. data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
  180. data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
  181. data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
  182. data/lib/repo_conf_generators/rightscale_key.pub +17 -0
  183. data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
  184. data/lib/repo_conf_generators.rb +30 -0
  185. data/lib/run_shell.rb +28 -0
  186. data/scripts/agent_checker.rb +571 -0
  187. data/scripts/agent_controller.rb +247 -0
  188. data/scripts/agent_deployer.rb +148 -0
  189. data/scripts/bundle_runner.rb +336 -0
  190. data/scripts/cloud_controller.rb +176 -0
  191. data/scripts/log_level_manager.rb +142 -0
  192. data/scripts/ohai_runner.rb +33 -0
  193. data/scripts/reenroller.rb +193 -0
  194. data/scripts/server_importer.rb +293 -0
  195. data/scripts/shutdown_client.rb +183 -0
  196. data/scripts/system_configurator.rb +367 -0
  197. data/scripts/tagger.rb +381 -0
  198. data/scripts/thunker.rb +356 -0
  199. metadata +418 -0
@@ -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