Skip to content

Commit

Permalink
#5 new cli install ssl.
Browse files Browse the repository at this point in the history
  • Loading branch information
filiplajszczak authored and caseneuve committed Mar 13, 2021
1 parent 9c998f0 commit 3a0d7ca
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 13 deletions.
55 changes: 52 additions & 3 deletions cli/webapp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/python3
import getpass
from enum import Enum
from pathlib import Path

import typer

Expand Down Expand Up @@ -104,12 +105,60 @@ def delete_logs(
webapp.delete_log(log_type, int(i))
else:
webapp.delete_log(log_type, int(log_index))
typer.echo(snakesay('All done!'))
typer.echo(snakesay("All done!"))


@app.command()
def install_ssl():
raise NotImplementedError
def install_ssl(
domain_name: str = typer.Argument(
...,
help="Domain name, eg www.mydomain.com",
),
certificate_file: Path = typer.Argument(
...,
exists=True,
file_okay=True,
readable=True,
resolve_path=True,
help="The name of the file containing the combined certificate in PEM format (normally a number of blocks, "
'each one starting "BEGIN CERTIFICATE" and ending "END CERTIFICATE")',
),
private_key_file: Path = typer.Argument(
...,
exists=True,
file_okay=True,
readable=True,
resolve_path=True,
help="The name of the file containing the private key in PEM format (a file with one block, "
'starting with something like "BEGIN PRIVATE KEY" and ending with something like "END PRIVATE KEY")',
),
suppress_reload: bool = typer.Option(
False,
help="The website will need to be reloaded in order to activate the new certificate/key combination "
"-- this happens by default, use this option to suppress it.",
),
):
with open(certificate_file, "r") as f:
certificate = f.read()

with open(private_key_file, "r") as f:
private_key = f.read()

webapp = Webapp(domain_name)
webapp.set_ssl(certificate, private_key)
if not suppress_reload:
webapp.reload()

ssl_details = webapp.get_ssl_info()
typer.echo(
snakesay(
"That's all set up now :-)\n"
f"Your new certificate for {domain_name} will expire\n"
f"on {ssl_details['not_after'].date().isoformat()},\n"
"so shortly before then you should renew it\n"
"and install the new certificate."
)
)


@app.command()
Expand Down
79 changes: 69 additions & 10 deletions tests/test_cli_webapp.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import getpass
import tempfile
from datetime import datetime
from unittest.mock import call

import pytest
from dateutil.tz import tzutc
from typer.testing import CliRunner

from cli.webapp import app
Expand All @@ -20,6 +23,17 @@ def mock_webapp(mocker):
return mock_webapp


@pytest.fixture(name="file_with_content")
def fixture_file_with_content():
def file_with_content(content):
filename = tempfile.NamedTemporaryFile(mode="w", encoding="utf8").name
with open(filename, "w") as f:
f.write(content)
return filename

return file_with_content


def test_create_calls_all_stuff_in_right_order(mocker):
mock_project = mocker.patch("cli.webapp.Project")

Expand Down Expand Up @@ -50,16 +64,6 @@ def test_create_calls_all_stuff_in_right_order(mocker):
)


def test_reload(mock_webapp):
domain_name = "foo.bar.baz"

result = runner.invoke(app, ["reload", "-d", domain_name])

assert f"{domain_name} has been reloaded" in result.stdout
mock_webapp.assert_called_once_with(domain_name)
assert mock_webapp.return_value.method_calls == [call.reload()]


def test_delete_all_logs(mock_webapp):
domain_name = "foo.bar.baz"

Expand Down Expand Up @@ -134,3 +138,58 @@ def test_delete_all_current_logs(mock_webapp):
call("server", 0),
]
assert "All done!" in result.stdout


def test_install_ssl_with_default_reload(mock_webapp, file_with_content):
mock_webapp.return_value.get_ssl_info.return_value = {
"not_after": datetime(2018, 8, 24, 17, 16, 23, tzinfo=tzutc())
}
domain_name = "foo.bar.baz"
certificate = "certificate"
certificate_file = file_with_content(certificate)
private_key = "private_key"
private_key_file = file_with_content(private_key)

result = runner.invoke(
app,
["install-ssl", "foo.bar.baz", certificate_file, private_key_file],
)

mock_webapp.assert_called_once_with(domain_name)
mock_webapp.return_value.set_ssl.assert_called_once_with(certificate, private_key)
mock_webapp.return_value.reload.assert_called_once()
assert f"for {domain_name}" in result.stdout
assert "2018-08-24," in result.stdout


def test_install_ssl_with_reload_suppressed(mock_webapp, file_with_content):
domain_name = "foo.bar.baz"
certificate = "certificate"
certificate_file = file_with_content(certificate)
private_key = "private_key"
private_key_file = file_with_content(private_key)

runner.invoke(
app,
[
"install-ssl",
"foo.bar.baz",
certificate_file,
private_key_file,
"--suppress-reload",
],
)

mock_webapp.assert_called_once_with(domain_name)
mock_webapp.return_value.set_ssl.assert_called_once_with(certificate, private_key)
mock_webapp.return_value.reload.assert_not_called()


def test_reload(mock_webapp):
domain_name = "foo.bar.baz"

result = runner.invoke(app, ["reload", "-d", domain_name])

assert f"{domain_name} has been reloaded" in result.stdout
mock_webapp.assert_called_once_with(domain_name)
assert mock_webapp.return_value.method_calls == [call.reload()]

0 comments on commit 3a0d7ca

Please sign in to comment.