Skip to content

Commit

Permalink
Add ssl support to the control_cli
Browse files Browse the repository at this point in the history
If I have a server running:

```sh
bundle exec bin/puma test/rackup/hello.ru \
  --control-url="ssl://127.0.0.1:9000?key=examples/puma/puma_keypair.pem&cert=examples/puma/cert_puma.pem" \
  --control-token="token"
```

This commit will allow me to restart that server (or run any other
control cli command) with:

```sh
bundle exec bin/pumactl restart \
  --control-url="ssl://127.0.0.1:9000" \
  --control-token="token"
```

Before this commit the pumactl restart command would have raised an
error: `"Invalid scheme: ssl"`
  • Loading branch information
composerinteralia committed Oct 24, 2019
1 parent 14782fd commit 18ef7d0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 14 deletions.
2 changes: 1 addition & 1 deletion History.md
Expand Up @@ -3,7 +3,7 @@
* Features
* Strip whitespace at end of HTTP headers (#2010)
* Optimize HTTP parser for JRuby (#2012)
* Add SSL support for the control app (#2046)
* Add SSL support for the control app and cli (#2046, #2052)

* Bugfixes
* Fix Errno::EINVAL when SSL is enabled and browser rejects cert (#1564)
Expand Down
6 changes: 6 additions & 0 deletions lib/puma/control_cli.rb
Expand Up @@ -141,6 +141,12 @@ def send_request

# create server object by scheme
server = case uri.scheme
when "ssl"
require 'openssl'
OpenSSL::SSL::SSLSocket.new(
TCPSocket.new(uri.host, uri.port),
OpenSSL::SSL::SSLContext.new
).tap(&:connect)
when "tcp"
TCPSocket.new uri.host, uri.port
when "unix"
Expand Down
58 changes: 45 additions & 13 deletions test/test_pumactl.rb
@@ -1,9 +1,12 @@
require_relative "helper"
require_relative "helpers/config_file"
require_relative "helpers/ssl"

require 'puma/control_cli'

class TestPumaControlCli < TestConfigFileBase
include SSLHelper

def setup
# use a pipe to get info across thread boundary
@wait, @ready = IO.pipe
Expand Down Expand Up @@ -132,24 +135,53 @@ def test_control_url_and_status

wait_booted

s = TCPSocket.new host, 9292
s << "GET / HTTP/1.0\r\n\r\n"
body = s.read
assert_match "200 OK", body
assert_match "embedded app", body
assert_app_running host
assert_command_cli_output opts + ["status"], "Puma is started"
assert_command_cli_output opts + ["halt"], "Command halt sent success"

status_cmd = Puma::ControlCLI.new(opts + ["status"])
out, _ = capture_subprocess_io do
status_cmd.run
assert_kind_of Thread, t.join, "server didn't stop"
end

def test_control_ssl
host = "127.0.0.1"
port = find_open_port
url = "ssl://#{host}:#{port}?#{ssl_query}"

opts = [
"--control-url", url,
"--control-token", "ctrl",
"--config-file", "test/config/app.rb",
]

control_cli = Puma::ControlCLI.new (opts + ["start"]), @ready, @ready
t = Thread.new do
control_cli.run
end
assert_match "Puma is started\n", out

shutdown_cmd = Puma::ControlCLI.new(opts + ["halt"])
wait_booted

assert_app_running host
assert_command_cli_output opts + ["status"], "Puma is started"
assert_command_cli_output opts + ["halt"], "Command halt sent success"

assert_kind_of Thread, t.join, "server didn't stop"
end

private

def assert_command_cli_output(options, expected_out)
cmd = Puma::ControlCLI.new(options)
out, _ = capture_subprocess_io do
shutdown_cmd.run
cmd.run
end
assert_match "Command halt sent success\n", out
assert_match expected_out, out
end

assert_kind_of Thread, t.join, "server didn't stop"
def assert_app_running(host)
s = TCPSocket.new host, 9292
s << "GET / HTTP/1.0\r\n\r\n"
body = s.read
assert_match "200 OK", body
assert_match "embedded app", body
end
end

0 comments on commit 18ef7d0

Please sign in to comment.