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,46 @@
1
+ /////////////////////////////////////////////////////////////////////////
2
+ // Copyright (c) 2010-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
+
24
+ Overview
25
+ --------
26
+
27
+ Runs a server for the get-NextAction cmdlet's named pipe which serves out the next action from a text file.
28
+
29
+
30
+
31
+ Debugging from Visual Studio
32
+ ----------------------------
33
+ VS 2008 C# projects appear not to allow variable substitution in debug command
34
+ lines (as has been allowed previously by C++ projects). This is likely to
35
+ improve in future, but in the meantime hardcode the .dll path (which gets
36
+ saved in your personal "ChefNodeCmdlet.csproj.user" file and is never checked
37
+ into source control).
38
+
39
+ See ChefNodeCmdlet\ReadMe.txt for details of debugging the client piece of get-NextAction (from a separate IDE instance).
40
+
41
+ Example:
42
+
43
+ Choose "Start project" for "Start Action"
44
+
45
+ Command line arguments:
46
+ -pn next_action_testing -na c:\temp\next-action.txt
@@ -0,0 +1,68 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+ <PropertyGroup>
4
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6
+ <ProductVersion>9.0.30729</ProductVersion>
7
+ <SchemaVersion>2.0</SchemaVersion>
8
+ <ProjectGuid>{9AF14C55-5808-4335-9BAA-74BD8DE5205B}</ProjectGuid>
9
+ <OutputType>Exe</OutputType>
10
+ <AppDesignerFolder>Properties</AppDesignerFolder>
11
+ <RootNamespace>TestNextActionCmdlet</RootNamespace>
12
+ <AssemblyName>TestNextActionCmdlet</AssemblyName>
13
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
14
+ <FileAlignment>512</FileAlignment>
15
+ </PropertyGroup>
16
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
17
+ <DebugSymbols>true</DebugSymbols>
18
+ <DebugType>full</DebugType>
19
+ <Optimize>false</Optimize>
20
+ <OutputPath>$(SolutionDir)\$(Configuration)</OutputPath>
21
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
22
+ <ErrorReport>prompt</ErrorReport>
23
+ <WarningLevel>4</WarningLevel>
24
+ </PropertyGroup>
25
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26
+ <DebugType>pdbonly</DebugType>
27
+ <Optimize>true</Optimize>
28
+ <OutputPath>$(SolutionDir)\$(Configuration)</OutputPath>
29
+ <DefineConstants>TRACE</DefineConstants>
30
+ <ErrorReport>prompt</ErrorReport>
31
+ <WarningLevel>4</WarningLevel>
32
+ </PropertyGroup>
33
+ <ItemGroup>
34
+ <Reference Include="System" />
35
+ <Reference Include="System.Core">
36
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
37
+ </Reference>
38
+ <Reference Include="System.Xml.Linq">
39
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
40
+ </Reference>
41
+ <Reference Include="System.Data.DataSetExtensions">
42
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
43
+ </Reference>
44
+ <Reference Include="System.Data" />
45
+ <Reference Include="System.Xml" />
46
+ </ItemGroup>
47
+ <ItemGroup>
48
+ <Compile Include="Program.cs" />
49
+ <Compile Include="Properties\AssemblyInfo.cs" />
50
+ </ItemGroup>
51
+ <ItemGroup>
52
+ <ProjectReference Include="..\ChefNodeCmdlet\ChefNodeCmdlet.csproj">
53
+ <Project>{F421745A-3ADE-473A-83DE-C7A3DF1B9557}</Project>
54
+ <Name>ChefNodeCmdlet</Name>
55
+ </ProjectReference>
56
+ </ItemGroup>
57
+ <ItemGroup>
58
+ <Content Include="ReadMe.txt" />
59
+ </ItemGroup>
60
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
61
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
62
+ Other similar extension points exist, see Microsoft.Common.targets.
63
+ <Target Name="BeforeBuild">
64
+ </Target>
65
+ <Target Name="AfterBuild">
66
+ </Target>
67
+ -->
68
+ </Project>
@@ -0,0 +1,463 @@
1
+ #
2
+ # Copyright (c) 2010-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
+ require 'rubygems'
23
+ require File.normalize_path(File.join(File.dirname(__FILE__), 'pipe_server'))
24
+ require 'json'
25
+ require 'set'
26
+
27
+ module RightScale
28
+
29
+ module Windows
30
+
31
+ # Provides a server for a named pipe connection which serves data from a
32
+ # node structure organized as a hierarchy of hashes to privitives, arrays
33
+ # and subhashes. complex types can also appear but will be served out as
34
+ # hashes without type. caution should be used not to use complex types which
35
+ # have circular references.
36
+ class ChefNodeServer
37
+
38
+ include RightSupport::Ruby::EasySingleton
39
+
40
+ CHEF_NODE_PIPE_NAME = 'chef_node_D1D6B540-5125-4c00-8ABF-412417774DD5'
41
+ COMMAND_KEY = "Command"
42
+ PATH_KEY = "Path"
43
+ NODE_VALUE_KEY = "NodeValue"
44
+
45
+ attr_reader :node
46
+ attr_accessor :current_resource
47
+ attr_accessor :new_resource
48
+
49
+ # Starts the pipe server by creating an asynchronous named pipe. Returns
50
+ # control to the caller after adding the pipe to the event machine.
51
+ #
52
+ # === Parameters
53
+ # options[:node](Node):: Chef node, required
54
+ #
55
+ # === Return
56
+ # true:: If server was successfully started
57
+ # false:: Otherwise
58
+ def start(options)
59
+ return true if @pipe_eventable # Idempotent
60
+
61
+ Log.debug("[ChefNodeServer] - Starting")
62
+ @node = options[:node] || {}
63
+ @pipe_eventable = nil
64
+ @current_resource = nil
65
+ @new_resource = nil
66
+
67
+ flags = ::Win32::Pipe::ACCESS_DUPLEX | ::Win32::Pipe::OVERLAPPED
68
+ pipe = PipeServer.new(CHEF_NODE_PIPE_NAME, 0, flags)
69
+ res = true
70
+ begin
71
+ options = {:target => self,
72
+ :request_handler => :request_handler,
73
+ :pipe => pipe}
74
+ @pipe_eventable = EM.watch(pipe, PipeServerHandler, options)
75
+ @pipe_eventable.notify_readable = true
76
+ rescue Exception => e
77
+ pipe.close rescue nil
78
+ res = false
79
+ end
80
+ Log.debug("[ChefNodeServer] - Started = #{res}")
81
+ res
82
+ end
83
+
84
+ # Stops the pipe server by detaching the eventable from the event machine.
85
+ #
86
+ # === Return
87
+ # true:: Always return true
88
+ def stop
89
+ Log.debug("[ChefNodeServer] - Stopping - need to stop = #{!@pipe_eventable.nil?}")
90
+ @pipe_eventable.force_detach if @pipe_eventable
91
+ @pipe_eventable = nil
92
+ true
93
+ end
94
+
95
+ # Handler for data node requests. Expects complete requests and responses
96
+ # to appear serialized as JSON on individual lines (i.e. delimited by
97
+ # newlines). note that JSON text escapes newline characters within string
98
+ # values and normally only includes whitespace for human-readability.
99
+ def request_handler(request_data)
100
+ # assume request_data is a single line with a possible newline trailing.
101
+ request = JSON.load(request_data.chomp)
102
+ if request.has_key?(COMMAND_KEY)
103
+ handler = REQUEST_HANDLERS[request[COMMAND_KEY]]
104
+ Log.debug("handler = #{handler}")
105
+ return self.send(handler, request) if handler
106
+ end
107
+ raise "Invalid request"
108
+ rescue Exception => e
109
+ return JSON.dump( { :Error => "#{e.class}: #{e.message}", :Detail => e.backtrace.join("\n") } ) + "\n"
110
+ end
111
+
112
+ private
113
+
114
+ REQUEST_HANDLERS = {"GetChefNodeRequest" => :handle_get_chef_node_request,
115
+ "SetChefNodeRequest" => :handle_set_chef_node_request,
116
+ "GetCurrentResourceRequest" => :handle_get_current_resource_request,
117
+ "SetCurrentResourceRequest" => :handle_set_current_resource_request,
118
+ "GetNewResourceRequest" => :handle_get_new_resource_request,
119
+ "SetNewResourceRequest" => :handle_set_new_resource_request }
120
+
121
+ # exception for a circular reference in node structure.
122
+ class CircularReferenceException < StandardError
123
+ def initialize(message)
124
+ super(message)
125
+ end
126
+ end
127
+
128
+ # exception for an invalid path.
129
+ class InvalidPathException < StandardError
130
+ def initialize(message)
131
+ super(message)
132
+ end
133
+ end
134
+
135
+ # Handles a Get-ChefNode request by finding the node matching the path,
136
+ # normalizing and then JSONing the data out.
137
+ #
138
+ # === Parameters
139
+ # request(Hash):: hash containing the following parameters:
140
+ #
141
+ # PATH_KEY(Array):: array of path elements
142
+ #
143
+ # === Returns
144
+ # response(String):: JSON structure containing found value or error
145
+ def handle_get_chef_node_request(request)
146
+ return handle_get_from_hash_request(request, @node)
147
+ end
148
+
149
+ # Handles a Set-ChefNode request by attempting to build the hash hierarchy
150
+ # to the requested path depth and the inserting the given value.
151
+ #
152
+ # === Parameters
153
+ # request(Hash):: hash containing the following parameters:
154
+ #
155
+ # PATH_KEY(Array):: array of path elements
156
+ #
157
+ # NODE_VALUE_KEY(Object):: node value to set
158
+ #
159
+ # === Returns
160
+ # response(String):: JSON structure containing acknowledgement or error
161
+ def handle_set_chef_node_request(request)
162
+ handle_set_into_hash_request(request, @node)
163
+ end
164
+
165
+ # Handles a Get-CurrentResource request.
166
+ #
167
+ # === Parameters
168
+ # request(Hash):: hash containing the following parameters:
169
+ #
170
+ # === Returns
171
+ # response(String):: JSON structure containing current resource or error
172
+ def handle_get_current_resource_request(request)
173
+ return handle_get_resource_request(request, @current_resource)
174
+ end
175
+
176
+ # Handles a Set-CurrentResource request.
177
+ #
178
+ # === Parameters
179
+ # request(Hash):: hash containing the following parameters:
180
+ #
181
+ # === Returns
182
+ # response(String):: empty JSON structure or error.
183
+ def handle_set_current_resource_request(request)
184
+ return handle_set_resource_request(request, @current_resource)
185
+ end
186
+
187
+ # Handles a Get-NewResource request.
188
+ #
189
+ # === Parameters
190
+ # request(Hash):: hash containing the following parameters:
191
+ #
192
+ # PATH_KEY(Array):: array of path elements
193
+ #
194
+ # === Returns
195
+ # response(String):: JSON structure containing new resource or error
196
+ def handle_get_new_resource_request(request)
197
+ handle_get_resource_request(request, @new_resource)
198
+ end
199
+
200
+ # Handles a Set-NewResource request.
201
+ #
202
+ # === Parameters
203
+ # request(Hash):: hash containing no additional parameters.
204
+ #
205
+ # PATH_KEY(Array):: array of path elements
206
+ #
207
+ # NODE_VALUE_KEY(Object):: node value to set
208
+ #
209
+ # === Returns
210
+ # response(String):: empty JSON structure or error.
211
+ def handle_set_new_resource_request(request)
212
+ return handle_set_resource_request(request, @new_resource)
213
+ end
214
+
215
+ # Handles a get from hash request by normalizing and then JSONing
216
+ # the current resource, if any.
217
+ #
218
+ # === Parameters
219
+ # request(Hash):: hash containing no additional parameters.
220
+ #
221
+ # hash(Hash):: a hash or hash-like object containing data to query.
222
+ #
223
+ # === Returns
224
+ # response(String):: JSON structure containing current resource or error
225
+ def handle_get_from_hash_request(request, hash)
226
+ raise "Missing required Path parameter" unless path = request[PATH_KEY]
227
+ node_value = get_node_value_from_hash(path, hash) rescue nil
228
+ node_value = normalize_node_value(node_value)
229
+ return JSON.dump( { :Path => path, :NodeValue => node_value } )
230
+ end
231
+
232
+ # Handles a set into hash request.
233
+ #
234
+ # === Parameters
235
+ # request(Hash):: hash containing no additional parameters.
236
+ #
237
+ # hash(Hash):: a hash or hash-like object containing data to query.
238
+ #
239
+ # === Returns
240
+ # response(String):: JSON structure containing current resource or error
241
+ def handle_set_into_hash_request(request, hash)
242
+ raise "Missing required Path parameter" unless path = request[PATH_KEY]
243
+ raise "Missing required NodeValue parameter" unless request.has_key?(NODE_VALUE_KEY) # value can be nil
244
+ node_value = request[NODE_VALUE_KEY]
245
+ set_node_value_into_hash(path, hash, node_value)
246
+ return JSON.dump( { :Path => path } )
247
+ end
248
+
249
+ # Handles a get resource request by normalizing and then JSONing
250
+ # the current resource, if any.
251
+ #
252
+ # === Parameters
253
+ # request(Hash):: hash containing no additional parameters.
254
+ #
255
+ # resource(Object):: resource for response.
256
+ #
257
+ # === Returns
258
+ # response(String):: JSON structure containing current resource or error
259
+ def handle_get_resource_request(request, resource)
260
+ # note that Chef::Resource and subclasses support :to_hash which will
261
+ # give us the interesting instance variables.
262
+ if resource && resource.respond_to?(:to_hash)
263
+ resource = resource.to_hash
264
+ resource = Mash.new(resource) unless resource.kind_of?(Mash)
265
+ end
266
+ return handle_get_from_hash_request(request, resource)
267
+ end
268
+
269
+ # Handles a set resource request by attempting to set member variables or
270
+ # set hash pairs depending on type.
271
+ #
272
+ # === Parameters
273
+ # request(Hash):: hash containing the following parameters:
274
+ #
275
+ # resource(Object):: resource object to modify by request.
276
+ #
277
+ # === Returns
278
+ # response(String):: JSON structure containing acknowledgement or error
279
+ def handle_set_resource_request(request, resource)
280
+ # resource may or may not support hash insertion, but we can reuse the
281
+ # generic code which parses parameters and inserts into a new hash.
282
+ hash = {}
283
+ result = handle_set_into_hash_request(request, hash)
284
+
285
+ # note that Chef::Resource and subclasses support :to_hash no :from_hash
286
+ # and so have to set instance variables by mutator. we also want to
287
+ # support hash types which will likely support both :has_key? and
288
+ # :to_hash so check for :has_key? first.
289
+ if resource.respond_to?(:has_key?)
290
+ hash.each do |key, value|
291
+ # note it is non-trivial here to determine if keys are supposed to
292
+ # be tokens or strings, so always use Mash-like objects for such
293
+ # resources.
294
+ resource[key] = value
295
+ end
296
+ elsif resource.respond_to?(:to_hash)
297
+ # set any instance variables by public mutator (which may fail due
298
+ # to validation, etc.).
299
+ hash.each do |key, value|
300
+ # Chef resources normally implement validating accessor/mutator
301
+ # single methods which take either nil for get or the value to
302
+ # set, but also check the name= method for completeness.
303
+ name_equals_sym = (key + "=").to_sym
304
+ if resource.respond_to?(name_equals_sym)
305
+ Log.debug("calling resource.#{name_equals_sym} #{value.inspect[0,64]}") if Log.debug?
306
+ resource.send(name_equals_sym, value)
307
+ else
308
+ Log.debug("calling resource.#{key} #{value.inspect[0,64]}") if Log.debug?
309
+
310
+ resource.send(key.to_sym, value)
311
+ end
312
+ end
313
+ else
314
+ raise "Resource of type #{resource.class} cannot be modified."
315
+ end
316
+
317
+ return result
318
+ end
319
+
320
+ # Queries the node value given by path from the node for this server.
321
+ #
322
+ # === Parameters
323
+ # path(Array):: array containing path elements.
324
+ #
325
+ # hash(Hash):: hash or hash-like object to query.
326
+ #
327
+ # === Returns
328
+ # node_value(Object):: node value from path or nil
329
+ def get_node_value_from_hash(path, hash)
330
+ # special case for the empty path element
331
+ return hash if (1 == path.length && path[0].to_s.length == 0)
332
+
333
+ node_by_path = node_by_path_statement(path)
334
+ result = instance_eval node_by_path
335
+ Log.debug("#{node_by_path} = #{result.inspect[0,64]}") if Log.debug?
336
+ return result
337
+ end
338
+
339
+ # Inserts the node value given by path into the node for this server,
340
+ # replacing any existing value.
341
+ #
342
+ # === Parameters
343
+ # path(Array):: array containing path elements.
344
+ #
345
+ # hash(Hash):: hash or hash-like object to query.
346
+ #
347
+ # node_value(Object):: value to insert.
348
+ #
349
+ # === Return
350
+ # true:: Always return true
351
+ def set_node_value_into_hash(path, hash, node_value)
352
+ # build up hash structure incrementally to avoid forcing the caller to
353
+ # explicitly insert all of the hashes described by the path.
354
+ raise InvalidPathException, "Cannot set the root node" if (path.empty? || path[0].empty?)
355
+ parent_path = []
356
+ path[0..-2].each do |element|
357
+ raise InvalidPathException, "At least one path element was empty" if element.empty?
358
+ parent_path << element
359
+ parent_node = get_node_value_from_hash(parent_path, hash)
360
+ if parent_node.nil? || false == parent_node.respond_to?(:has_key?)
361
+ node_by_path = node_by_path_statement(parent_path)
362
+ instance_eval "#{node_by_path} = {}"
363
+ end
364
+ end
365
+
366
+ # insert node value.
367
+ node_by_path = node_by_path_statement(path)
368
+ instance_eval "#{node_by_path} = node_value"
369
+
370
+ true
371
+ end
372
+
373
+ # Generates an evaluatable statement for querying Chef node by path.
374
+ #
375
+ # === Parameters
376
+ # path(Array):: array containing path elements.
377
+ def node_by_path_statement(path)
378
+ return "hash[\"#{path.join('"]["')}\"]"
379
+ end
380
+
381
+ # Nnormalizes the given node value to produce simple containers, hashes
382
+ # and primitives for JSON serialization. Also detects circular references.
383
+ #
384
+ # === Parameters
385
+ # node_value(Object):: value to normalize
386
+ #
387
+ # node_value_set(Set):: set used for circular reference detection.
388
+ #
389
+ # === Returns
390
+ # normal_value(Object):: normalized value
391
+ def normalize_node_value(node_value)
392
+ normalize_node_value3(node_value, [], Set.new)
393
+ end
394
+
395
+ # Recursively normalizes the given node value to produce simple
396
+ # containers, hashes and primitives for JSON serialization. Also detects
397
+ # circular references.
398
+ #
399
+ # === Parameters
400
+ # node_value(Object):: value to normalize
401
+ #
402
+ # depth(Array):: current depth of hash keys or empty
403
+ #
404
+ # node_value_set(Set):: set used for circular reference detection.
405
+ #
406
+ # === Returns
407
+ # normal_value(Object):: normalized value
408
+ def normalize_node_value3(node_value, depth, node_value_set)
409
+ return nil if node_value.nil?
410
+ case node_value
411
+ when FalseClass, TrueClass, Numeric, String
412
+ # primitives can appear repeatedly but are not a circular reference.
413
+ return node_value
414
+ when Array
415
+ # arrays can contain circular references.
416
+ if node_value_set.add?(node_value.object_id)
417
+ result = []
418
+ node_value.each { |array_value| result << normalize_node_value3(array_value, depth, node_value_set) }
419
+ return result
420
+ else
421
+ raise CircularReferenceException, "Circular reference detected at depth = #{depth.join(', ')}"
422
+ end
423
+ when Chef::Node
424
+ # the Chef root node is a special case because we don't want to return
425
+ # the entire node in a JSON stream. only return the root keys.
426
+ result = []
427
+ node_value.each { |key, value| result << key.to_s }
428
+ return result
429
+ else
430
+ # note that the root node (i.e. Chef::Node) does not respond to
431
+ # has_key? but otherwise behaves like a hash.
432
+ if node_value.respond_to?(:has_key?) || node_value.kind_of?(Chef::Node)
433
+ # hashes can contain circular references.
434
+ if node_value_set.add?(node_value.object_id)
435
+ result = {}
436
+ node_value.each do |key, value|
437
+ depth.push key
438
+ begin
439
+ # recursion.
440
+ result[key.to_s] = normalize_node_value3(value, depth, node_value_set)
441
+ ensure
442
+ depth.pop
443
+ end
444
+ end
445
+ return result
446
+ else
447
+ Log.debug("Handling circular reference for hash by responding with key set at depth = #{depth.join(', ')}")
448
+ result = []
449
+ node_value.each { |key, value| result << key.to_s }
450
+ return result
451
+ end
452
+ else
453
+ # currently ignoring complex types except for converting them to
454
+ # string value.
455
+ return node_value.to_s
456
+ end
457
+ end
458
+ end
459
+ end
460
+
461
+ end
462
+
463
+ end