Replace all uses of runner.isolated_filesystem, refs #1406

pull/1418/head
Simon Willison 2021-07-31 11:49:08 -07:00
rodzic 96b1d0b7b4
commit ff253f5242
3 zmienionych plików z 284 dodań i 292 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
from click.testing import CliRunner from click.testing import CliRunner
from datasette import cli from datasette import cli
from unittest import mock from unittest import mock
import os
import pathlib import pathlib
import pytest import pytest
@ -32,12 +33,12 @@ def test_package(mock_call, mock_which, tmp_path_factory):
runner = CliRunner() runner = CliRunner()
capture = CaptureDockerfile() capture = CaptureDockerfile()
mock_call.side_effect = capture mock_call.side_effect = capture
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke(cli.cli, ["package", "test.db", "--secret", "sekrit"]) result = runner.invoke(cli.cli, ["package", "test.db", "--secret", "sekrit"])
assert 0 == result.exit_code assert 0 == result.exit_code
mock_call.assert_has_calls([mock.call(["docker", "build", "."])]) mock_call.assert_has_calls([mock.call(["docker", "build", "."])])
assert EXPECTED_DOCKERFILE.format(port=8001) == capture.captured assert EXPECTED_DOCKERFILE.format(port=8001) == capture.captured
@ -48,11 +49,11 @@ def test_package_with_port(mock_call, mock_which, tmp_path_factory):
capture = CaptureDockerfile() capture = CaptureDockerfile()
mock_call.side_effect = capture mock_call.side_effect = capture
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, ["package", "test.db", "-p", "8080", "--secret", "sekrit"] cli.cli, ["package", "test.db", "-p", "8080", "--secret", "sekrit"]
) )
assert 0 == result.exit_code assert 0 == result.exit_code
assert EXPECTED_DOCKERFILE.format(port=8080) == capture.captured assert EXPECTED_DOCKERFILE.format(port=8080) == capture.captured

Wyświetl plik

@ -2,6 +2,7 @@ from click.testing import CliRunner
from datasette import cli from datasette import cli
from unittest import mock from unittest import mock
import json import json
import os
import pytest import pytest
import textwrap import textwrap
@ -11,12 +12,12 @@ import textwrap
def test_publish_cloudrun_requires_gcloud(mock_which, tmp_path_factory): def test_publish_cloudrun_requires_gcloud(mock_which, tmp_path_factory):
mock_which.return_value = False mock_which.return_value = False
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke(cli.cli, ["publish", "cloudrun", "test.db"]) result = runner.invoke(cli.cli, ["publish", "cloudrun", "test.db"])
assert result.exit_code == 1 assert result.exit_code == 1
assert "Publishing to Google Cloud requires gcloud" in result.output assert "Publishing to Google Cloud requires gcloud" in result.output
@mock.patch("shutil.which") @mock.patch("shutil.which")
@ -42,39 +43,32 @@ def test_publish_cloudrun_prompts_for_service(
mock_output.return_value = "myproject" mock_output.return_value = "myproject"
mock_which.return_value = True mock_which.return_value = True
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, ["publish", "cloudrun", "test.db"], input="input-service" cli.cli, ["publish", "cloudrun", "test.db"], input="input-service"
) )
assert ( assert (
""" "Please provide a service name for this deployment\n\n"
Please provide a service name for this deployment "Using an existing service name will over-write it\n\n"
"Your existing services:\n\n"
Using an existing service name will over-write it " existing - created 2019-01-01 - http://www.example.com/\n\n"
"Service name: input-service"
Your existing services: ) == result.output.strip()
assert 0 == result.exit_code
existing - created 2019-01-01 - http://www.example.com/ tag = "gcr.io/myproject/datasette"
mock_call.assert_has_calls(
Service name: input-service [
""".strip() mock.call(f"gcloud builds submit --tag {tag}", shell=True),
== result.output.strip() mock.call(
) "gcloud run deploy --allow-unauthenticated --platform=managed --image {} input-service".format(
assert 0 == result.exit_code tag
tag = "gcr.io/myproject/datasette"
mock_call.assert_has_calls(
[
mock.call(f"gcloud builds submit --tag {tag}", shell=True),
mock.call(
"gcloud run deploy --allow-unauthenticated --platform=managed --image {} input-service".format(
tag
),
shell=True,
), ),
] shell=True,
) ),
]
)
@pytest.mark.serial @pytest.mark.serial
@ -85,25 +79,25 @@ def test_publish_cloudrun(mock_call, mock_output, mock_which, tmp_path_factory):
mock_output.return_value = "myproject" mock_output.return_value = "myproject"
mock_which.return_value = True mock_which.return_value = True
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, ["publish", "cloudrun", "test.db", "--service", "test"] cli.cli, ["publish", "cloudrun", "test.db", "--service", "test"]
) )
assert 0 == result.exit_code assert 0 == result.exit_code
tag = f"gcr.io/{mock_output.return_value}/datasette" tag = f"gcr.io/{mock_output.return_value}/datasette"
mock_call.assert_has_calls( mock_call.assert_has_calls(
[ [
mock.call(f"gcloud builds submit --tag {tag}", shell=True), mock.call(f"gcloud builds submit --tag {tag}", shell=True),
mock.call( mock.call(
"gcloud run deploy --allow-unauthenticated --platform=managed --image {} test".format( "gcloud run deploy --allow-unauthenticated --platform=managed --image {} test".format(
tag tag
),
shell=True,
), ),
] shell=True,
) ),
]
)
@pytest.mark.serial @pytest.mark.serial
@ -126,29 +120,29 @@ def test_publish_cloudrun_memory(
mock_output.return_value = "myproject" mock_output.return_value = "myproject"
mock_which.return_value = True mock_which.return_value = True
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, cli.cli,
["publish", "cloudrun", "test.db", "--service", "test", "--memory", memory], ["publish", "cloudrun", "test.db", "--service", "test", "--memory", memory],
) )
if should_fail: if should_fail:
assert 2 == result.exit_code assert 2 == result.exit_code
return return
assert 0 == result.exit_code assert 0 == result.exit_code
tag = f"gcr.io/{mock_output.return_value}/datasette" tag = f"gcr.io/{mock_output.return_value}/datasette"
mock_call.assert_has_calls( mock_call.assert_has_calls(
[ [
mock.call(f"gcloud builds submit --tag {tag}", shell=True), mock.call(f"gcloud builds submit --tag {tag}", shell=True),
mock.call( mock.call(
"gcloud run deploy --allow-unauthenticated --platform=managed --image {} test --memory {}".format( "gcloud run deploy --allow-unauthenticated --platform=managed --image {} test --memory {}".format(
tag, memory tag, memory
),
shell=True,
), ),
] shell=True,
) ),
]
)
@pytest.mark.serial @pytest.mark.serial
@ -162,74 +156,74 @@ def test_publish_cloudrun_plugin_secrets(
mock_output.return_value = "myproject" mock_output.return_value = "myproject"
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
with open("metadata.yml", "w") as fp: with open("metadata.yml", "w") as fp:
fp.write( fp.write(
textwrap.dedent( textwrap.dedent(
"""
title: Hello from metadata YAML
plugins:
datasette-auth-github:
foo: bar
""" """
).strip() title: Hello from metadata YAML
) plugins:
result = runner.invoke( datasette-auth-github:
cli.cli, foo: bar
[ """
"publish", ).strip()
"cloudrun",
"test.db",
"--metadata",
"metadata.yml",
"--service",
"datasette",
"--plugin-secret",
"datasette-auth-github",
"client_id",
"x-client-id",
"--show-files",
"--secret",
"x-secret",
],
) )
assert result.exit_code == 0 result = runner.invoke(
dockerfile = ( cli.cli,
result.output.split("==== Dockerfile ====\n")[1] [
.split("\n====================\n")[0] "publish",
.strip() "cloudrun",
) "test.db",
expected = textwrap.dedent( "--metadata",
r""" "metadata.yml",
FROM python:3.8 "--service",
COPY . /app "datasette",
WORKDIR /app "--plugin-secret",
"datasette-auth-github",
"client_id",
"x-client-id",
"--show-files",
"--secret",
"x-secret",
],
)
assert result.exit_code == 0
dockerfile = (
result.output.split("==== Dockerfile ====\n")[1]
.split("\n====================\n")[0]
.strip()
)
expected = textwrap.dedent(
r"""
FROM python:3.8
COPY . /app
WORKDIR /app
ENV DATASETTE_AUTH_GITHUB_CLIENT_ID 'x-client-id' ENV DATASETTE_AUTH_GITHUB_CLIENT_ID 'x-client-id'
ENV DATASETTE_SECRET 'x-secret' ENV DATASETTE_SECRET 'x-secret'
RUN pip install -U datasette RUN pip install -U datasette
RUN datasette inspect test.db --inspect-file inspect-data.json RUN datasette inspect test.db --inspect-file inspect-data.json
ENV PORT 8001 ENV PORT 8001
EXPOSE 8001 EXPOSE 8001
CMD datasette serve --host 0.0.0.0 -i test.db --cors --inspect-file inspect-data.json --metadata metadata.json --setting force_https_urls on --port $PORT""" CMD datasette serve --host 0.0.0.0 -i test.db --cors --inspect-file inspect-data.json --metadata metadata.json --setting force_https_urls on --port $PORT"""
).strip() ).strip()
assert expected == dockerfile assert expected == dockerfile
metadata = ( metadata = (
result.output.split("=== metadata.json ===\n")[1] result.output.split("=== metadata.json ===\n")[1]
.split("\n==== Dockerfile ====\n")[0] .split("\n==== Dockerfile ====\n")[0]
.strip() .strip()
) )
assert { assert {
"title": "Hello from metadata YAML", "title": "Hello from metadata YAML",
"plugins": { "plugins": {
"datasette-auth-github": { "datasette-auth-github": {
"foo": "bar", "client_id": {"$env": "DATASETTE_AUTH_GITHUB_CLIENT_ID"},
"client_id": {"$env": "DATASETTE_AUTH_GITHUB_CLIENT_ID"}, "foo": "bar",
}
}, },
} == json.loads(metadata) },
} == json.loads(metadata)
@pytest.mark.serial @pytest.mark.serial
@ -243,51 +237,51 @@ def test_publish_cloudrun_apt_get_install(
mock_output.return_value = "myproject" mock_output.return_value = "myproject"
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, cli.cli,
[ [
"publish", "publish",
"cloudrun", "cloudrun",
"test.db", "test.db",
"--service", "--service",
"datasette", "datasette",
"--show-files", "--show-files",
"--secret", "--secret",
"x-secret", "x-secret",
"--apt-get-install", "--apt-get-install",
"ripgrep", "ripgrep",
"--spatialite", "--spatialite",
], ],
) )
assert result.exit_code == 0 assert result.exit_code == 0
dockerfile = ( dockerfile = (
result.output.split("==== Dockerfile ====\n")[1] result.output.split("==== Dockerfile ====\n")[1]
.split("\n====================\n")[0] .split("\n====================\n")[0]
.strip() .strip()
) )
expected = textwrap.dedent( expected = textwrap.dedent(
r""" r"""
FROM python:3.8 FROM python:3.8
COPY . /app COPY . /app
WORKDIR /app WORKDIR /app
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y ripgrep python3-dev gcc libsqlite3-mod-spatialite && \ apt-get install -y ripgrep python3-dev gcc libsqlite3-mod-spatialite && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
ENV DATASETTE_SECRET 'x-secret' ENV DATASETTE_SECRET 'x-secret'
ENV SQLITE_EXTENSIONS '/usr/lib/x86_64-linux-gnu/mod_spatialite.so' ENV SQLITE_EXTENSIONS '/usr/lib/x86_64-linux-gnu/mod_spatialite.so'
RUN pip install -U datasette RUN pip install -U datasette
RUN datasette inspect test.db --inspect-file inspect-data.json RUN datasette inspect test.db --inspect-file inspect-data.json
ENV PORT 8001 ENV PORT 8001
EXPOSE 8001 EXPOSE 8001
CMD datasette serve --host 0.0.0.0 -i test.db --cors --inspect-file inspect-data.json --setting force_https_urls on --port $PORT CMD datasette serve --host 0.0.0.0 -i test.db --cors --inspect-file inspect-data.json --setting force_https_urls on --port $PORT
""" """
).strip() ).strip()
assert expected == dockerfile assert expected == dockerfile
@pytest.mark.serial @pytest.mark.serial
@ -312,32 +306,32 @@ def test_publish_cloudrun_extra_options(
mock_output.return_value = "myproject" mock_output.return_value = "myproject"
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, cli.cli,
[ [
"publish", "publish",
"cloudrun", "cloudrun",
"test.db", "test.db",
"--service", "--service",
"datasette", "datasette",
"--show-files", "--show-files",
"--extra-options", "--extra-options",
extra_options, extra_options,
], ],
) )
assert result.exit_code == 0 assert result.exit_code == 0
dockerfile = ( dockerfile = (
result.output.split("==== Dockerfile ====\n")[1] result.output.split("==== Dockerfile ====\n")[1]
.split("\n====================\n")[0] .split("\n====================\n")[0]
.strip() .strip()
) )
last_line = dockerfile.split("\n")[-1] last_line = dockerfile.split("\n")[-1]
extra_options = ( extra_options = (
last_line.split("--inspect-file inspect-data.json")[1] last_line.split("--inspect-file inspect-data.json")[1]
.split("--port")[0] .split("--port")[0]
.strip() .strip()
) )
assert extra_options == expected assert extra_options == expected

Wyświetl plik

@ -1,6 +1,7 @@
from click.testing import CliRunner from click.testing import CliRunner
from datasette import cli from datasette import cli
from unittest import mock from unittest import mock
import os
import pytest import pytest
@ -9,12 +10,12 @@ import pytest
def test_publish_heroku_requires_heroku(mock_which, tmp_path_factory): def test_publish_heroku_requires_heroku(mock_which, tmp_path_factory):
mock_which.return_value = False mock_which.return_value = False
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke(cli.cli, ["publish", "heroku", "test.db"]) result = runner.invoke(cli.cli, ["publish", "heroku", "test.db"])
assert result.exit_code == 1 assert result.exit_code == 1
assert "Publishing to Heroku requires heroku" in result.output assert "Publishing to Heroku requires heroku" in result.output
@pytest.mark.serial @pytest.mark.serial
@ -27,11 +28,11 @@ def test_publish_heroku_installs_plugin(
mock_which.return_value = True mock_which.return_value = True
mock_check_output.side_effect = lambda s: {"['heroku', 'plugins']": b""}[repr(s)] mock_check_output.side_effect = lambda s: {"['heroku', 'plugins']": b""}[repr(s)]
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("t.db", "w") as fp: with open("t.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke(cli.cli, ["publish", "heroku", "t.db"], input="y\n") result = runner.invoke(cli.cli, ["publish", "heroku", "t.db"], input="y\n")
assert 0 != result.exit_code assert 0 != result.exit_code
mock_check_output.assert_has_calls( mock_check_output.assert_has_calls(
[mock.call(["heroku", "plugins"]), mock.call(["heroku", "apps:list", "--json"])] [mock.call(["heroku", "plugins"]), mock.call(["heroku", "apps:list", "--json"])]
) )
@ -61,28 +62,26 @@ def test_publish_heroku(mock_call, mock_check_output, mock_which, tmp_path_facto
"['heroku', 'apps:create', 'datasette', '--json']": b'{"name": "f"}', "['heroku', 'apps:create', 'datasette', '--json']": b'{"name": "f"}',
}[repr(s)] }[repr(s)]
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(cli.cli, ["publish", "heroku", "test.db", "--tar", "gtar"])
cli.cli, ["publish", "heroku", "test.db", "--tar", "gtar"] assert 0 == result.exit_code, result.output
) mock_call.assert_has_calls(
assert 0 == result.exit_code, result.output [
mock_call.assert_has_calls( mock.call(
[ [
mock.call( "heroku",
[ "builds:create",
"heroku", "-a",
"builds:create", "f",
"-a", "--include-vcs-ignore",
"f", "--tar",
"--include-vcs-ignore", "gtar",
"--tar", ]
"gtar", ),
] ]
), )
]
)
@pytest.mark.serial @pytest.mark.serial
@ -99,35 +98,33 @@ def test_publish_heroku_plugin_secrets(
"['heroku', 'apps:create', 'datasette', '--json']": b'{"name": "f"}', "['heroku', 'apps:create', 'datasette', '--json']": b'{"name": "f"}',
}[repr(s)] }[repr(s)]
runner = CliRunner() runner = CliRunner()
with runner.isolated_filesystem(tmp_path_factory.mktemp("runner")): os.chdir(tmp_path_factory.mktemp("runner"))
with open("test.db", "w") as fp: with open("test.db", "w") as fp:
fp.write("data") fp.write("data")
result = runner.invoke( result = runner.invoke(
cli.cli, cli.cli,
[ [
"publish", "publish",
"heroku", "heroku",
"test.db", "test.db",
"--plugin-secret", "--plugin-secret",
"datasette-auth-github", "datasette-auth-github",
"client_id", "client_id",
"x-client-id", "x-client-id",
], ],
) )
assert 0 == result.exit_code, result.output assert 0 == result.exit_code, result.output
mock_call.assert_has_calls( mock_call.assert_has_calls(
[ [
mock.call( mock.call(
[ [
"heroku", "heroku",
"config:set", "config:set",
"-a", "-a",
"f", "f",
"DATASETTE_AUTH_GITHUB_CLIENT_ID=x-client-id", "DATASETTE_AUTH_GITHUB_CLIENT_ID=x-client-id",
] ]
), ),
mock.call( mock.call(["heroku", "builds:create", "-a", "f", "--include-vcs-ignore"]),
["heroku", "builds:create", "-a", "f", "--include-vcs-ignore"] ]
), )
]
)