Compare commits

..

15 Commits

Author SHA1 Message Date
forest c0bc65ed3d create TestHTTPClient that uses werkzueg test client, tests are passing 2021-07-31 15:28:42 -05:00
forest 6d52f56d27 documenting the janky tests logs situation 2021-07-27 14:49:10 -05:00
forest f5640a1d01 getting unit tests to log properly 2021-07-27 14:44:10 -05:00
forest 45d7e2c62e breaking up after abusive relationship with logger 2021-07-27 14:28:42 -05:00
forest 56b00934be trying to do CaptureLogOutputDuringTestsFilter (but no worky yet) 2021-07-27 13:56:58 -05:00
forest aa67a1e1b2 blah failed attempts at getting tests to log 2021-07-27 13:28:49 -05:00
forest 3fb8254c15 add debug test log 2021-07-27 12:50:50 -05:00
forest 8a4794a344 trying to get tests to pass with hub_model=capsulflask 2021-07-27 12:48:48 -05:00
forest 4cf11798aa remove redundant get_vms() and add testing documentation from pull
request
2021-07-27 12:02:48 -05:00
3wc e1867eb430 Fix capsul create tests, post-test cleanup, tidy merge 2021-07-23 13:40:00 +02:00
forest 62c7355b4c ensure that app is defined in app.py to fix login link logging issues.
also shuffled some things around for cleanliness
2021-07-23 03:02:17 +02:00
3wc 202d0aefff Disable VM creation check for the moment 2021-07-23 03:02:17 +02:00
3wc 01478dfd87 Add SSH key tests 2021-07-23 03:02:17 +02:00
3wc a4837aff87 Initial console tests
NB capsul create isn't working properly, see #83
2021-07-23 03:02:17 +02:00
3wc ecc8f885fa Basic testing using flask-testing
This commit makes it possible to override settings during tests, by
switching capsulflask/__init__.py to a "create_app" pattern, and using
`dotenv_values` instead of `load_dotenv`.

The create_app() method returns a Flask app instance, to give
more control over when to initialise the app. This allows setting
environment variables in test files.

Then, use dotenv_values to override loaded .env variables with ones from
the environment, so that tests can set `POSTGRES_CONNECTION_PARAMETERS`
and `SPOKE_MODEL` (possibly others in future..).

Inital tests for the "landing" pages, and login / activation, are
included.
2021-07-23 03:02:15 +02:00
18 changed files with 27 additions and 59 deletions

View File

@ -1,11 +0,0 @@
# Optional, default `mock`
#SPOKE_MODEL=shell-scripts
# Optional, default `0`
#FLASK_DEBUG=0
# Optional, default `http://localhost:5000`
#BASE_URL=http://localhost:5000
# Optional, default `qemu:///system` if you're root, otherwise `qemu:///session`
#VIRSH_DEFAULT_CONNECT_URI=qemu:///system
#ADMIN_PANEL_ALLOW_EMAIL_ADDRESSES=3wc.capsul@doesthisthing.work
# Optional, default no theme
#THEME=yolocolo

1
.gitignore vendored
View File

@ -11,7 +11,6 @@ instance/
.pytest_cache/ .pytest_cache/
.coverage .coverage
htmlcov/ htmlcov/
/unittest-log-output.log
dist/ dist/
build/ build/

View File

@ -59,7 +59,6 @@ def create_app(http_client_factory):
LOG_LEVEL=config.get("LOG_LEVEL", "INFO"), LOG_LEVEL=config.get("LOG_LEVEL", "INFO"),
SPOKE_HOST_ID=config.get("SPOKE_HOST_ID", "baikal"), SPOKE_HOST_ID=config.get("SPOKE_HOST_ID", "baikal"),
SPOKE_HOST_TOKEN=config.get("SPOKE_HOST_TOKEN", "changeme"), SPOKE_HOST_TOKEN=config.get("SPOKE_HOST_TOKEN", "changeme"),
SSH_USERNAME=os.environ.get("SSH_USERNAME", default="cyberian"),
HUB_TOKEN=config.get("HUB_TOKEN", "changeme"), HUB_TOKEN=config.get("HUB_TOKEN", "changeme"),
# https://www.postgresql.org/docs/9.1/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS # https://www.postgresql.org/docs/9.1/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS

View File

@ -62,18 +62,6 @@ def sql_script(f, c):
model.connection.commit() model.connection.commit()
@bp.cli.command('account-balance')
@click.option('-u', help='users email address')
@with_appcontext
def account_balance(u):
vms = get_model().list_vms_for_account(u)
payments = get_model().list_payments_for_account(u)
click.echo(".")
click.echo(".")
click.echo(get_account_balance(vms, payments, datetime.utcnow()))
click.echo(".")
@bp.cli.command('cron-task') @bp.cli.command('cron-task')
@with_appcontext @with_appcontext

View File

@ -108,8 +108,6 @@ def detail(id):
if vm is None: if vm is None:
return abort(404, f"{id} doesn't exist.") return abort(404, f"{id} doesn't exist.")
vm['ssh_username'] = current_app.config['SSH_USERNAME']
if vm['deleted']: if vm['deleted']:
return render_template("capsul-detail.html", vm=vm, delete=True, deleted=True) return render_template("capsul-detail.html", vm=vm, delete=True, deleted=True)

View File

@ -43,7 +43,7 @@ def init_app(app, is_running_server):
hasSchemaVersionTable = False hasSchemaVersionTable = False
actionWasTaken = False actionWasTaken = False
schemaVersion = 0 schemaVersion = 0
desiredSchemaVersion = 19 desiredSchemaVersion = 18
cursor = connection.cursor() cursor = connection.cursor()

View File

@ -23,7 +23,7 @@ def pricing():
@bp.route("/faq") @bp.route("/faq")
def faq(): def faq():
return render_template("faq.html", ssh_username=current_app.config['SSH_USERNAME']) return render_template("faq.html")
@bp.route("/about-ssh") @bp.route("/about-ssh")
def about_ssh(): def about_ssh():

View File

@ -1,8 +0,0 @@
DELETE FROM os_images WHERE id = 'guixsystem130';
DELETE FROM os_images WHERE id = 'archlinux';
UPDATE os_images SET deprecated = FALSE WHERE id = 'guixsystem120';
UPDATE os_images SET deprecated = FALSE WHERE id = 'centos7';
UPDATE os_images SET deprecated = FALSE WHERE id = 'centos8';
UPDATE os_images SET description = 'Ubuntu 20.04 LTS (Fossa)' WHERE id = 'ubuntu20';
UPDATE schemaversion SET version = 18;

View File

@ -1,12 +0,0 @@
INSERT INTO os_images (id, template_image_file_name, description, deprecated)
VALUES ('guixsystem130', 'guixsystem/1.3.0/root.img.qcow2', 'Guix System 1.3.0', FALSE);
INSERT INTO os_images (id, template_image_file_name, description, deprecated)
VALUES ('archlinux', 'archlinux/root.img.qcow2', 'Arch Linux', FALSE);
UPDATE os_images SET deprecated = TRUE WHERE id = 'guixsystem120';
UPDATE os_images SET deprecated = TRUE WHERE id = 'centos7';
UPDATE os_images SET deprecated = TRUE WHERE id = 'centos8';
UPDATE os_images SET description = 'Ubuntu 20.04 (Focal)' WHERE id = 'ubuntu20';
UPDATE schemaversion SET version = 19;

View File

@ -30,6 +30,6 @@ if virsh domuuid "$vmname" | grep -vqE '^[\t\s\n]*$'; then
fi fi
# this gets the ipv4 # this gets the ipv4
ipv4="$(virsh domifaddr "$vmname" | awk '/ipv4/ {print $4}' | cut -d'/' -f1)" ipv4="$(virsh domifaddr "$vmname" | awk '/vnet/ {print $4}' | cut -d'/' -f1)"
echo "$exists $state $ipv4" echo "$exists $state $ipv4"

View File

@ -97,7 +97,7 @@
</div> </div>
<div class="row justify-start"> <div class="row justify-start">
<label class="align" for="ssh_username">SSH Username</label> <label class="align" for="ssh_username">SSH Username</label>
<span id="ssh_username">{{ vm['ssh_username'] }}</span> <span id="ssh_username">cyberian</span>
</div> </div>
<div class="row justify-start"> <div class="row justify-start">
<label class="align" for="ssh_authorized_keys">SSH Authorized Keys</label> <label class="align" for="ssh_authorized_keys">SSH Authorized Keys</label>

View File

@ -21,13 +21,13 @@
</li> </li>
<li> <li>
How do I log in? How do I log in?
<p>ssh to the ip provided to you using the "{{ ssh_username }}" user.</p> <p>ssh to the ip provided to you using the cyberian user.</p>
<pre class='code'>$ ssh {{ ssh_username }}@1.2.3.4</pre> <pre class='code'>$ ssh cyberian@1.2.3.4</pre>
<p>For more information, see <a href="/about-ssh">Understanding the Secure Shell Protocol (SSH)</a>.</p> <p>For more information, see <a href="/about-ssh">Understanding the Secure Shell Protocol (SSH)</a>.</p>
</li> </li>
<li> <li>
How do I change to the root user? How do I change to the root user?
<p>The "{{ ssh_username }}" user has passwordless sudo access by default. This should work:</p> <p>The cyberian user has passwordless sudo access by default. This should work:</p>
<pre class='code'> <pre class='code'>
# Linux # Linux
$ sudo su - $ sudo su -

View File

@ -7,11 +7,18 @@
<h1>SUPPORT</h1> <h1>SUPPORT</h1>
</div> </div>
<div class="row half-margin"> <div class="row half-margin">
<a href="mailto:support@cyberia.club?subject=capsul%20support%20request">support@cyberia.club</a> <a href="mailto:support@cyberia.club?subject=Please%20help!">support@cyberia.club</a>
</div> </div>
{% endblock %} {% endblock %}
{% block subcontent %} {% block subcontent %}
<p>
Note: We maintain a searchable archive of all support emails at
<a href="https://lists.cyberia.club/~cyberia/support">https://lists.cyberia.club/~cyberia/support</a>
</p>
<p>
If you do not want your mail to appear in a public archive, email <a href="mailto:capsul@cyberia.club?subject=Please%20help!">capsul@cyberia.club</a> instead.
</p>
<p> <p>
Please describe your problem or feature request, and we will do our best to get back to you promptly. Thank you very much. Please describe your problem or feature request, and we will do our best to get back to you promptly. Thank you very much.
</p> </p>

View File

@ -12,6 +12,8 @@ class LoginTests(BaseTestCase):
response = client.get(url_for("auth.login")) response = client.get(url_for("auth.login"))
self.assert_200(response) self.assert_200(response)
# FIXME test generated login link
def test_login_magiclink(self): def test_login_magiclink(self):
token, ignoreCaseMatches = get_model().login('test@example.com') token, ignoreCaseMatches = get_model().login('test@example.com')

View File

@ -29,6 +29,7 @@ class ConsoleTests(BaseTestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
get_model().cursor.execute("DELETE FROM host_operation") get_model().cursor.execute("DELETE FROM host_operation")
get_model().cursor.execute("DELETE FROM operations") get_model().cursor.execute("DELETE FROM operations")
get_model().cursor.execute("DELETE FROM vm_ssh_host_key") get_model().cursor.execute("DELETE FROM vm_ssh_host_key")
@ -47,6 +48,8 @@ class ConsoleTests(BaseTestCase):
for host_id in host_ids: for host_id in host_ids:
get_model().host_heartbeat(host_id) get_model().host_heartbeat(host_id)
def test_index(self): def test_index(self):
self._login('test@example.com') self._login('test@example.com')
with self.client as client: with self.client as client:
@ -77,6 +80,7 @@ class ConsoleTests(BaseTestCase):
0 0
) )
def test_create_fails_capacity(self): def test_create_fails_capacity(self):
with self.client as client: with self.client as client:
@ -158,6 +162,7 @@ class ConsoleTests(BaseTestCase):
url_for("console.index") + f'?created={vm_id}' url_for("console.index") + f'?created={vm_id}'
) )
def test_keys_loads(self): def test_keys_loads(self):
self._login('test@example.com') self._login('test@example.com')
with self.client as client: with self.client as client:
@ -210,3 +215,5 @@ class ConsoleTests(BaseTestCase):
'A key with that name already exists', 'A key with that name already exists',
category='message' category='message'
) )

View File

@ -116,4 +116,4 @@ class TestHTTPClient:
# in the same order as the tasks that we passed in -- which were in the same order as online_hosts # in the same order as the tasks that we passed in -- which were in the same order as online_hosts
results = await asyncio.gather(*tasks) results = await asyncio.gather(*tasks)
return results return results

View File

@ -15,8 +15,8 @@ services:
- "5000:5000" - "5000:5000"
environment: environment:
- "POSTGRES_CONNECTION_PARAMETERS=host=db port=5432 user=capsul password=capsul dbname=capsul" - "POSTGRES_CONNECTION_PARAMETERS=host=db port=5432 user=capsul password=capsul dbname=capsul"
- SPOKE_MODEL - SPOKE_MODEL=shell-scripts
- FLASK_DEBUG #- FLASK_DEBUG=1
- BASE_URL=http://localhost:5000 - BASE_URL=http://localhost:5000
- ADMIN_PANEL_ALLOW_EMAIL_ADDRESSES=3wc.capsul@doesthisthing.work - ADMIN_PANEL_ALLOW_EMAIL_ADDRESSES=3wc.capsul@doesthisthing.work
- VIRSH_DEFAULT_CONNECT_URI=qemu:///system - VIRSH_DEFAULT_CONNECT_URI=qemu:///system

View File

@ -3,7 +3,6 @@
Create a `.env` file to set up the application configuration: Create a `.env` file to set up the application configuration:
``` ```
cp .env.sample .env
nano .env nano .env
``` ```