Compare commits

..

No commits in common. "350245c097a2cfa851cffbdcca4ddbdb57674cab" and "69579fea1cc41974b263b094f5e54c315aa6bb94" have entirely different histories.

11 changed files with 48 additions and 85 deletions

View file

@ -79,16 +79,10 @@ in
## and check that they are working properly.
extraTestScript = ''
with subtest("Check the status of the services - there should be none"):
garage.fail("systemctl status garage.service")
mastodon.fail("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
with subtest("Run deployment with no services enabled"):
deployer.succeed("nixops4 apply check-deployment-cli-nothing --show-trace --no-interactive 1>&2")
with subtest("Check the status of the services - there should still be none"):
with subtest("Check the status of the services - there should be none"):
garage.fail("systemctl status garage.service")
mastodon.fail("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")

View file

@ -53,7 +53,6 @@ in
};
config = {
acmeNodeIP = config.nodes.acme.networking.primaryIPAddress;
nodes =
{

View file

@ -50,16 +50,13 @@ in
};
security.pki.certificateFiles = [
## NOTE: This certificate is the one used by the Pebble HTTPS server.
## This is NOT the root CA of the Pebble server. We do add it here so
## that Pebble clients can talk to its API, but this will not allow
## those machines to verify generated certificates.
testCerts.ca.cert
];
## FIXME: it is a bit sad that all this logistics is necessary. look into
## better DNS stuff
networking.extraHosts = "${config.acmeNodeIP} acme.test";
})
];
}

View file

@ -33,25 +33,11 @@
## information coming from the FediPanel.
##
## FIXME: lock step the interface with the definitions in the FediPanel
panelConfigNullable:
panelConfig:
let
inherit (lib) mkIf;
nonNull = x: v: if x == null then v else x;
panelConfig = {
domain = nonNull panelConfigNullable.domain "fediversity.net";
initialUser = nonNull panelConfigNullable.initialUser {
displayName = "Testy McTestface";
username = "test";
password = "testtest";
email = "test@test.com";
};
mastodon = nonNull panelConfigNullable.mastodon { enable = false; };
peertube = nonNull panelConfigNullable.peertube { enable = false; };
pixelfed = nonNull panelConfigNullable.pixelfed { enable = false; };
};
in
## Regular arguments of a NixOps4 deployment module.
@ -136,7 +122,7 @@ in
{ pkgs, ... }:
mkIf (cfg.mastodon.enable || cfg.peertube.enable || cfg.pixelfed.enable) {
fediversity = {
inherit (cfg) domain;
inherit (panelConfig) domain;
garage.enable = true;
pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
mastodon = mastodonS3KeyConfig { inherit pkgs; };

View file

@ -1,5 +1,6 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; # consumed by flake-parts
flake-parts.url = "github:hercules-ci/flake-parts";
git-hooks.url = "github:cachix/git-hooks.nix";
nixops4.follows = "nixops4-nixos/nixops4";
@ -10,11 +11,9 @@
inputs@{ flake-parts, ... }:
let
sources = import ./npins;
inherit (import "${flake-inputs}/lib.nix") import-flake;
inherit (sources) git-hooks agenix;
nixpkgs = import-flake sources.nixpkgs;
in
flake-parts.lib.mkFlake { inputs = inputs // { inherit nixpkgs; }; } {
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
"aarch64-linux"

View file

@ -25,22 +25,6 @@
"url": null,
"hash": "1w2gsy6qwxa5abkv8clb435237iifndcxq0s79wihqw11a5yb938"
},
"flake-inputs": {
"type": "GitRelease",
"repository": {
"type": "GitHub",
"owner": "fricklerhandwerk",
"repo": "flake-inputs"
},
"pre_releases": false,
"version_upper_bound": null,
"release_prefix": null,
"submodules": false,
"version": "1.1",
"revision": "6461d0b56e790bf289af07c5e5261abbf4f536af",
"url": "https://api.github.com/repos/fricklerhandwerk/flake-inputs/tarball/1.1",
"hash": "03mwisvr1mc3nd33nvg4bvcyxjxpm4lwhwym39r0768cm1007ixl"
},
"flake-parts": {
"type": "Git",
"repository": {

View file

@ -9,4 +9,10 @@ in
{
REPO_DIR = toString ../.;
# explicitly use nix, as e.g. lix does not have configurable-impure-env
BIN_PATH = lib.makeBinPath [
# explicitly use nix, as e.g. lix does not have configurable-impure-env
pkgs.nix
# nixops error maybe due to our flake git hook: executing 'git': No such file or directory
pkgs.git
];
}

View file

@ -146,19 +146,7 @@ in
${cfg.domain} =
{
locations = {
"/" = {
proxyPass = "http://localhost:${toString cfg.port}";
extraConfig = ''
## FIXME: The following is necessary because /deployment/status
## can take aaaaages to respond. I think this is horrendous
## design from the panel and should be changed there, but in the
## meantime we bump nginx's timeouts to one hour.
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
send_timeout 3600;
'';
};
"/".proxyPass = "http://localhost:${toString cfg.port}";
"/static/".alias = "/var/lib/${name}/static/";
};
}
@ -178,18 +166,10 @@ in
description = "${name} ASGI server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path =
[
python-environment
manage-service
]
++ (
with pkgs;
lib.mkBinPath [
nix
git
]
);
path = [
python-environment
manage-service
];
preStart = ''
# Auto-migrate on first run or if the package has changed
versionFile="/var/lib/${name}/package-version"

View file

@ -240,6 +240,8 @@ if user_settings_file is not None:
# The correct thing to do here would be using a helper function such as with `get_secret()` that will catch the exception and explain what's wrong and where to put the right values.
# Replacing the `USER_SETTINGS_FILE` mechanism following the comment there would probably be a good thing.
# PATH to expose to launch button
bin_path=env['BIN_PATH']
# path of the root flake to trigger nixops from, see #94.
# to deploy this should be specified, for dev just use a relative path.
repo_dir = env["REPO_DIR"]

View file

@ -1,10 +1,9 @@
from django.test import TestCase
from django.urls import reverse
from django.contrib.auth.models import User
from django.template import Template, Context
from urllib.parse import unquote
from panel.templatetags.custom_tags import auth_url
class Login(TestCase):
def setUp(self):
self.username = 'testuser'
@ -28,7 +27,8 @@ class Login(TestCase):
# check that the expected login URL is in the response
context = response.context[0]
login_url = auth_url(context, 'login')
template = Template("{% load custom_tags %}{% auth_url 'login' %}")
login_url = template.render(context)
self.assertIn(login_url, response.content.decode('utf-8'))
# log in
@ -49,7 +49,8 @@ class Login(TestCase):
# check that the expected logout URL is present
context = response.context[0]
logout_url = auth_url(context, 'logout')
template = Template("{% load custom_tags %}{% auth_url 'logout' %}")
logout_url = template.render(context)
self.assertIn(logout_url, response.content.decode('utf-8'))
# log out again
@ -87,7 +88,8 @@ class Login(TestCase):
# check that the expected logout URL is present
context = response.context[0]
logout_url = auth_url(context, 'logout')
template = Template("{% load custom_tags %}{% auth_url 'logout' %}")
logout_url = template.render(context)
self.assertIn(logout_url, response.content.decode('utf-8'))
# log out
@ -95,7 +97,8 @@ class Login(TestCase):
# check that we're at the expected location, logged out
self.assertEqual(response.status_code, 200)
login_url = auth_url(context, 'login')
template = Template("{% load custom_tags %}{% auth_url 'login' %}")
login_url = template.render(context)
location, status = response.redirect_chain[-1]
self.assertEqual(location, unquote(login_url))
self.assertFalse(response.context['user'].is_authenticated)

View file

@ -65,6 +65,9 @@ class ConfigurationForm(LoginRequiredMixin, APIView):
config.save()
return redirect(self.success_url)
# TODO(@fricklerhandwerk):
# this is broken after changing the form view.
# but if there's no test for it, how do we know it ever worked in the first place?
class DeploymentStatus(ConfigurationForm):
def post(self, request):
@ -81,15 +84,28 @@ class DeploymentStatus(ConfigurationForm):
config.save()
deployment_result, deployment_params = self.deployment(config.parsed_value)
if deployment_result.returncode == 0:
deployment_status = "Deployment Succeeded"
else:
deployment_status = "Deployment Failed"
return render(self.request, "partials/deployment_result.html", {
"deployment_succeeded": (deployment_result.returncode == 0),
"deployment_status": deployment_status,
"services": deployment_params.json(),
})
def deployment(self, config: BaseModel):
# FIXME: let the user specify these from the form (#190)
dummy_user = {
"initialUser": {
"displayName": "Testy McTestface",
"username": "test",
"password": "testtest",
"email": "test@test.com",
},
}
env = {
"PATH": os.environ.get("PATH"),
"PATH": settings.bin_path,
# pass in form info to our deployment
"DEPLOYMENT": config.json()
}
@ -102,13 +118,10 @@ class DeploymentStatus(ConfigurationForm):
"nixops4",
"apply",
"test",
"--show-trace",
"--no-interactive",
]
deployment_result = subprocess.run(
cmd,
cwd = settings.repo_dir,
env = env,
stderr = subprocess.STDOUT,
cwd=settings.repo_dir,
env=env,
)
return deployment_result, config