Compare commits

..

32 Commits

Author SHA1 Message Date
3wc 6fb9c651e8 Revert accidental change to test DB settings 2021-08-16 03:08:52 +02:00
3wc a7bc0c6c01 Fixes to compose file 2021-08-16 02:30:46 +02:00
3wc 0574d58a7c Tidying; add .env.sample 2021-08-16 02:28:28 +02:00
forest b3c655bc47 account-balance cli command 2021-08-16 02:21:52 +02:00
j3s a9a4c4448c Add centos deprecation yeet 2021-08-16 02:21:52 +02:00
j3s a040301bbb Add archlinux, bump everything' 2021-08-16 02:21:52 +02:00
j3s f3ea3d330d Remove ops linky 2021-08-16 02:21:52 +02:00
j3s d9dc3f3049 Add linebreak to support page 2021-08-16 02:21:52 +02:00
j3s d1c95cd113 Add ops 2021-08-16 02:21:52 +02:00
j3s 174532b7fe * 2021-08-16 02:21:52 +02:00
j3s 02c6352f11 Update support wording 2021-08-16 02:21:52 +02:00
3wordchant 171c3252e4 Merge pull request 'Add preliminary automated tests' (#1) from tests into master
Reviewed-on: 3wordchant/capsul-flask#1
2021-08-16 02:11:14 +02:00
3wc 13b2c05476 gitignore unittest output file 2021-08-16 02:07:36 +02:00
forest 5f9fc1adcf create TestHTTPClient that uses werkzueg test client, tests are passing 2021-08-16 02:07:36 +02:00
forest 16ff1b5b26 documenting the janky tests logs situation 2021-08-16 02:07:36 +02:00
forest 8c10f71f58 getting unit tests to log properly 2021-08-16 02:07:36 +02:00
forest 66dee4d87a breaking up after abusive relationship with logger 2021-08-16 02:07:36 +02:00
forest 6a587ac7fc trying to do CaptureLogOutputDuringTestsFilter (but no worky yet) 2021-08-16 02:07:36 +02:00
forest 4e510ebb01 blah failed attempts at getting tests to log 2021-08-16 02:07:36 +02:00
forest 140870ec35 add debug test log 2021-08-16 02:07:36 +02:00
forest 2348191990 trying to get tests to pass with hub_model=capsulflask 2021-08-16 02:07:36 +02:00
forest 5e682cc705 remove redundant get_vms() and add testing documentation from pull
request
2021-08-16 02:07:36 +02:00
3wc 2b33573890 Fix capsul create tests, post-test cleanup, tidy merge 2021-08-16 02:07:36 +02:00
forest da4d28f70c ensure that app is defined in app.py to fix login link logging issues.
also shuffled some things around for cleanliness
2021-08-16 02:07:36 +02:00
3wc d833b3df19 Disable VM creation check for the moment 2021-08-16 02:07:36 +02:00
3wc 46a40261bb Add SSH key tests 2021-08-16 02:07:36 +02:00
3wc b108d4c04e Initial console tests
NB capsul create isn't working properly, see #83
2021-08-16 02:07:36 +02:00
3wc 6bd02a660e 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-08-16 02:07:34 +02:00
mirsal 8a944104d3 Merge pull request 'Make the displayed SSH username configurable' (#12) from mirsal/capsul-flask:ssh-username into master
Reviewed-on: 3wordchant/capsul-flask#12
2021-08-10 11:56:14 +02:00
mirsal d4a9f2f40a Make the displayed SSH username configurable
This patch allows the SSH username displayed in templates to be
configured through the SSH_USERNAME environment variable.
2021-08-10 00:30:45 +00:00
3wordchant 7b16606b16 Merge pull request 'shell_scripts: Fix reporting of VM IP addresses' (#9) from mirsal/capsul-flask:ipv6 into master
Reviewed-on: 3wordchant/capsul-flask#9
2021-08-04 12:13:44 +02:00
mirsal d9f3e68278 shell_scripts: Fix reporting of VM IP addresses
The shell script which gets informations from libvirt incorrectly
matches virsh output lines which contain VMs' public IPv4 addresses.
It doesn't work when there are multiple address families which breaks
reporting of IPv4 address when a VM also has an IPv6 address and virsh
happen to output that one first.

This commit changes it to explicitely match the first ipv4 address instead.
2021-08-04 00:56:55 +00:00
18 changed files with 59 additions and 27 deletions

11
.env.sample Normal file
View File

@ -0,0 +1,11 @@
# 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,6 +11,7 @@ instance/
.pytest_cache/
.coverage
htmlcov/
/unittest-log-output.log
dist/
build/

View File

@ -59,6 +59,7 @@ def create_app(http_client_factory):
LOG_LEVEL=config.get("LOG_LEVEL", "INFO"),
SPOKE_HOST_ID=config.get("SPOKE_HOST_ID", "baikal"),
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"),
# https://www.postgresql.org/docs/9.1/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS

View File

@ -62,6 +62,18 @@ def sql_script(f, c):
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')
@with_appcontext

View File

@ -108,6 +108,8 @@ def detail(id):
if vm is None:
return abort(404, f"{id} doesn't exist.")
vm['ssh_username'] = current_app.config['SSH_USERNAME']
if vm['deleted']:
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
actionWasTaken = False
schemaVersion = 0
desiredSchemaVersion = 18
desiredSchemaVersion = 19
cursor = connection.cursor()

View File

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

View File

@ -0,0 +1,8 @@
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

@ -0,0 +1,12 @@
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
# this gets the ipv4
ipv4="$(virsh domifaddr "$vmname" | awk '/vnet/ {print $4}' | cut -d'/' -f1)"
ipv4="$(virsh domifaddr "$vmname" | awk '/ipv4/ {print $4}' | cut -d'/' -f1)"
echo "$exists $state $ipv4"

View File

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

View File

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

View File

@ -7,18 +7,11 @@
<h1>SUPPORT</h1>
</div>
<div class="row half-margin">
<a href="mailto:support@cyberia.club?subject=Please%20help!">support@cyberia.club</a>
<a href="mailto:support@cyberia.club?subject=capsul%20support%20request">support@cyberia.club</a>
</div>
{% endblock %}
{% 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>
Please describe your problem or feature request, and we will do our best to get back to you promptly. Thank you very much.
</p>

View File

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

View File

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

View File

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

View File

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