Class: Isomorfeus::Puppetmaster::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/isomorfeus/puppetmaster/server.rb,
lib/isomorfeus/puppetmaster/server/checker.rb,
lib/isomorfeus/puppetmaster/server/middleware.rb,
lib/isomorfeus/puppetmaster/server/executor_middleware.rb

Defined Under Namespace

Classes: Checker, ExecutorMiddleware, Middleware, Timer

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, port: Isomorfeus::Puppetmaster.server_port, host: Isomorfeus::Puppetmaster.server_host, extra_middleware: []) ⇒ Server

Returns a new instance of Server.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/isomorfeus/puppetmaster/server.rb', line 35

def initialize(app,
               port: Isomorfeus::Puppetmaster.server_port,
               host: Isomorfeus::Puppetmaster.server_host,
               extra_middleware: [])
  @app = app
  @extra_middleware = extra_middleware
  @request_key = Isomorfeus::Puppetmaster::Server::ExecutorMiddleware.class_variable_get(:@@request_key)
  unless @request_key
    @request_key = SecureRandom.alphanumeric(128)
    Isomorfeus::Puppetmaster::Server::ExecutorMiddleware.class_variable_set(:@@request_key, @request_key)
  end
  @extra_middleware << Isomorfeus::Puppetmaster::Server::ExecutorMiddleware
  @server_thread = nil # suppress warnings

  @host = host
  @port = port
  @port ||= Isomorfeus::Puppetmaster::Server.ports[port_key]
  @port ||= find_available_port(host)
  @checker = Isomorfeus::Puppetmaster::Server::Checker.new(@host, @port)

  @server_proc = proc do |app, port, host, **options|
    begin
      require 'rack'
      require 'rackup'
      require 'rack/handler'
      require 'iodine'
      require 'iodine/version'
      require 'rack/handler/iodine'
    rescue LoadError
      raise LoadError, "Unable to load 'iodine' as server."
    end
    Iodine.patch_rack
    Iodine::Rack.run(app, { Host: host, Port: port }.merge(options))
  end
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



33
34
35
# File 'lib/isomorfeus/puppetmaster/server.rb', line 33

def app
  @app
end

#hostObject (readonly)

Returns the value of attribute host.



33
34
35
# File 'lib/isomorfeus/puppetmaster/server.rb', line 33

def host
  @host
end

#portObject (readonly)

Returns the value of attribute port.



33
34
35
# File 'lib/isomorfeus/puppetmaster/server.rb', line 33

def port
  @port
end

Class Method Details

.portsObject



29
30
31
# File 'lib/isomorfeus/puppetmaster/server.rb', line 29

def self.ports
  @ports ||= {}
end

Instance Method Details

#bootObject



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/isomorfeus/puppetmaster/server.rb', line 128

def boot
  unless responsive?
    Isomorfeus::Puppetmaster::Server.ports[port_key] = port

    @server_thread = Thread.new do
      @server_proc.call(middleware, port, host)
    end

    timer = Isomorfeus::Puppetmaster::Server::Timer.new(expire_in: 60)
    until responsive?
      raise 'Rack application timed out during boot' if timer.expired?

      @server_thread.join(0.1)
    end
  end

  self
end

#errorObject



74
75
76
# File 'lib/isomorfeus/puppetmaster/server.rb', line 74

def error
  middleware.error
end

#on_server(ruby_source = '', file = nil, line = nil, &block) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/isomorfeus/puppetmaster/server.rb', line 78

def on_server(ruby_source = '', file = nil, line = nil, &block)
  ruby_source, file, line = Isomorfeus::Puppetmaster.block_source_code(&block) if block_given?
  request_hash = { 'key' => @request_key, 'code' => ruby_source, 'file' => file, 'line' => line }
  response = if using_ssl?
               http = Net::HTTP.start(@host, @port, { use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE })
               http.post('/__executor__', Oj.dump(request_hash, mode: :strict))
             else
               http = Net::HTTP.start(@host, @port)
               http.post('/__executor__', Oj.dump(request_hash, mode: :strict))
             end
  if response.code == '200'
    result_hash = Oj.load(response.body, circular: true)
    if result_hash.key?('error')
      error = RuntimeError.new(result_hash['error'])
      error.set_backtrace(result_hash['backtrace'])
      raise error
    end
    result_hash['result']
  else
    raise 'A error occurred.'
  end
end

#reset_error!Object



70
71
72
# File 'lib/isomorfeus/puppetmaster/server.rb', line 70

def reset_error!
  middleware.clear_error
end

#responsive?Boolean

Returns:

  • (Boolean)


109
110
111
112
113
114
115
116
117
# File 'lib/isomorfeus/puppetmaster/server.rb', line 109

def responsive?
  return false if @server_thread.nil? || @server_thread.join(0)

  res = @checker.request { |http| http.get('/__identify__') }

  return res.body == app.object_id.to_s if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
rescue SystemCallError, Net::ReadTimeout, OpenSSL::SSL::SSLError
  false
end

#schemeObject



105
106
107
# File 'lib/isomorfeus/puppetmaster/server.rb', line 105

def scheme
  using_ssl? ? 'https' : 'http'
end

#using_ssl?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/isomorfeus/puppetmaster/server.rb', line 101

def using_ssl?
  @checker.ssl?
end

#wait_for_pending_requestsObject



119
120
121
122
123
124
125
126
# File 'lib/isomorfeus/puppetmaster/server.rb', line 119

def wait_for_pending_requests
  timer = Isomorfeus::Puppetmaster::Server::Timer.new(expire_in: 60)
  while pending_requests?
    raise 'Requests did not finish in 60 seconds' if timer.expired?

    sleep 0.01
  end
end