Class: RightScale::Windows::PowershellPipeServer
- Defined in:
- lib/chef/windows/powershell_pipe_server.rb
Overview
Provides a server for a named pipe connection which serves a series of commands to be executed in the powershell context. The final command is expected to be an “exit” statement.
Constant Summary collapse
- LAST_EXIT_CODE_KEY =
Request hash key associated with previous execution exit code
"LastExitCode"- LAST_ERROR_MESSAGE_KEY =
"LastErrorMessage"- NEXT_ACTION_KEY =
Response hash key associated with action to run
:NextAction
Instance Method Summary collapse
-
#initialize(options = {}, &callback) ⇒ PowershellPipeServer
constructor
Initialize pipe server.
-
#request_handler(request_data) ⇒ Object
Handler for next action requests.
-
#request_query(request_data) ⇒ Object
Ready to respond if the next action queue is empty, otherwise continue blocking client.
-
#start ⇒ Object
Starts the pipe server by creating an asynchronous named pipe.
-
#stop ⇒ Object
Stops the pipe server by detaching the eventable from the event machine.
Constructor Details
#initialize(options = {}, &callback) ⇒ PowershellPipeServer
Initialize pipe server
Parameters
- options(String)
-
Name of pipe to connect to (required)
Block
Given block gets called back for each request It should take two arguments:
* First argument is either :is_ready or :respond
calls with :is_ready should return a boolean value set to true if there is a pending command
calls with :respond should return the pending command
* Second argument contains the request data (only set with :respond)
55 56 57 58 59 |
# File 'lib/chef/windows/powershell_pipe_server.rb', line 55 def initialize( = {}, &callback) raise ArgumentError, "Missing required :pipe_name" unless @pipe_name = [:pipe_name] @callback = callback @pipe_eventable = nil end |
Instance Method Details
#request_handler(request_data) ⇒ Object
Handler for next action requests. Expects complete requests and responses to appear serialized as JSON on individual lines (i.e. delimited by newlines). note that JSON text escapes newline characters within string values and normally only includes whitespace for human- readability.
Parameters
- request_data(String)
-
Request data
Returns
- response(String)
-
Request response
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/chef/windows/powershell_pipe_server.rb', line 119 def request_handler(request_data) # assume request_data is a single line with a possible newline trailing. request = JSON.load(request_data.chomp) if 2 == request.keys.size && request.has_key?(LAST_EXIT_CODE_KEY) && request.has_key?(LAST_ERROR_MESSAGE_KEY) # pop the next action from the queue. command = @callback.call(:respond, request) return JSON.dump(NEXT_ACTION_KEY => command) + "\n"; end raise ArgumentError, "Invalid request" rescue Exception => e return JSON.dump(:Error => "#{e.class}: #{e.message}", :Detail => e.backtrace.join("\n")) + "\n" end |
#request_query(request_data) ⇒ Object
Ready to respond if the next action queue is empty, otherwise continue blocking client.
Parameters
- request_data(String)
-
request data
Returns
- result(Boolean)
-
true if response is ready
104 105 106 |
# File 'lib/chef/windows/powershell_pipe_server.rb', line 104 def request_query(request_data) return @callback.call(:is_ready, nil) end |
#start ⇒ Object
Starts the pipe server by creating an asynchronous named pipe. Returns control to the caller after adding the pipe to the event machine.
Return
- true
-
If server was successfully started
- false
-
Otherwise
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/chef/windows/powershell_pipe_server.rb', line 67 def start flags = ::Win32::Pipe::ACCESS_DUPLEX | ::Win32::Pipe::OVERLAPPED pipe = PipeServer.new(@pipe_name, 0, flags) res = true begin = {:target => self, :request_handler => :request_handler, :request_query => :request_query, :pipe => pipe} @pipe_eventable = EM.watch(pipe, PipeServerHandler, ) @pipe_eventable.notify_readable = true rescue Exception => e pipe.close rescue nil RightScale::Log.error("Failed to start pipe server", e, :trace) res = false end res end |
#stop ⇒ Object
Stops the pipe server by detaching the eventable from the event machine.
Return
- true
-
Always return true
90 91 92 93 94 |
# File 'lib/chef/windows/powershell_pipe_server.rb', line 90 def stop @pipe_eventable.force_detach if @pipe_eventable @pipe_eventable = nil true end |