right_link 5.9.0

Sign up to get free protection for your applications and to get access to all the features.
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