Compare commits

...

4 commits

Author SHA1 Message Date
afbbcbc22d simplify configuration via environment
All checks were successful
/ check-pre-commit (pull_request) Successful in 24s
/ check-website (pull_request) Successful in 9s
/ check-peertube (pull_request) Successful in 20s
/ check-pre-commit (push) Successful in 6s
/ check-website (push) Successful in 10s
/ check-peertube (push) Successful in 21s
2025-03-19 10:06:38 +01:00
c5fe0157b0
factor reading env vars out to settings.py
All checks were successful
/ check-pre-commit (pull_request) Successful in 24s
/ check-website (pull_request) Successful in 10s
/ check-peertube (pull_request) Successful in 20s
2025-03-19 09:51:23 +01:00
53d3791eaa
move NIX_DIR to env, making its use more explicit 2025-03-19 09:51:23 +01:00
53658e9880
trigger nixops from panel
adds a deploy button to the panel form - covers the local part of #76.

As a workaround to pass info (from our user form) into nixops4 uses
environment variable `DEPLOYMENT` thru nix's
`--extra-experimental-features configurable-impure-env`.
2025-03-19 09:51:23 +01:00
6 changed files with 85 additions and 19 deletions

View file

@ -58,9 +58,13 @@
packages = [
pkgs.nil
inputs'.agenix.packages.default
inputs'.nixops4.packages.default
pkgs.openssh
pkgs.httpie
pkgs.jq
# exposing this env var as a hack to pass info in from form
(inputs'.nixops4.packages.default.overrideAttrs {
impureEnvVars = [ "DEPLOYMENT" ];
})
];
shellHook = config.pre-commit.installationScript;
};

View file

@ -143,7 +143,17 @@ in
## - We add a “test” deployment with all test machines.
nixops4Deployments = genAttrs machines makeDeployment' // {
default = makeDeployment machines;
test = makeTestDeployment (fromJSON (readFile ./test-machines/configuration.json));
test = makeTestDeployment (
fromJSON (
let
env = builtins.getEnv "DEPLOYMENT";
in
if env != "" then
env
else
builtins.trace "env var DEPLOYMENT not set, falling back to ./test-machines/configuration.json!" (readFile ./test-machines/configuration.json)
)
);
};
flake.nixosConfigurations =
genAttrs machines (makeConfiguration false)

View file

@ -21,14 +21,17 @@ in
];
env = {
NPINS_DIRECTORY = toString ../npins;
# explicitly use nix, as e.g. lix does not have configurable-impure-env
NIX_DIR = pkgs.nix;
REPO_DIR = toString ../.;
CREDENTIALS_DIRECTORY = builtins.toString ./.credentials;
DATABASE_URL = "sqlite:///${toString ./src}/db.sqlite3";
};
shellHook = ''
# in production, secrets are passed via CREDENTIALS_DIRECTORY by systemd.
# use this directory for testing with local secrets
mkdir -p .credentials
mkdir -p $CREDENTIALS_DIRECTORY
echo secret > ${builtins.toString ./.credentials}/SECRET_KEY
export CREDENTIALS_DIRECTORY=${builtins.toString ./.credentials}
export DATABASE_URL="sqlite:///${toString ./src}/db.sqlite3"
'';
};

View file

@ -173,14 +173,26 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Customization via user settings
# This must be at the end, as it must be able to override the above
# TODO: we may want to do this with a flat environment instead, and get all values from `os.environ.get()`.
# this would make it more obvious which moving parts there are, if that environment is specified for development/staging/production in a visible place.
user_settings_file = env.get("USER_SETTINGS_FILE", None)
if user_settings_file is not None:
spec = importlib.util.spec_from_file_location("user_settings", user_settings_file)
if spec is None or spec.loader is None:
raise RuntimeError("User settings specification failed!")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules["user_settings"] = module
from user_settings import * # noqa: F403 # pyright: ignore [reportMissingImports]
# TODO(@fricklerhandwerk):
# we may want to do this with a flat environment instead, and get all values from `os.environ.get()`.
# this would make it more obvious which moving parts there are, if that environment is specified for development/staging/production in a visible place.
user_settings_file = env["USER_SETTINGS_FILE"]
spec = importlib.util.spec_from_file_location("user_settings", user_settings_file)
if spec is None or spec.loader is None:
raise RuntimeError("User settings specification failed!")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules["user_settings"] = module
from user_settings import * # noqa: F403 # pyright: ignore [reportMissingImports]
# non-Django application settings
# TODO(@fricklerhandwerk):
# 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.
# a dir of nix supporting experimental feature `configurable-impure-env`.
nix_bin_dir=f"{env['NIX_DIR']}/bin/"
# 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

@ -5,7 +5,7 @@
{{ form.as_p }}
<button class="button" disabled>Deploy</button>
<button class="button" type="submit" >Save</button>
<button class="button" type="submit" name="deploy">Deploy</button>
<button class="button" type="submit" name="save">Save</button>
</form>
{% endblock %}

View file

@ -1,4 +1,6 @@
from enum import Enum
import json
import subprocess
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
@ -6,7 +8,7 @@ from django.contrib.auth.models import User
from django.views.generic import TemplateView, DetailView
from django.views.generic.edit import FormView
from panel import models
from panel import models, settings
from panel.configuration import forms
@ -41,6 +43,41 @@ class ConfigurationForm(LoginRequiredMixin, FormView):
operator=self.request.user,
)
# Check for deploy button
if "deploy" in self.request.POST.keys():
submission = obj.parsed_value.model_dump_json()
# FIXME: let the user specify these from the form (#190)
dummy_user = {
"initialUser": {
"displayName": "Testy McTestface",
"username": "test",
"password": "testtest",
"email": "test@test.com",
},
}
# serialize back and forth now we still need to manually inject the dummy user
deployment = json.dumps(dummy_user | json.loads(submission))
env = {
"PATH": settings.nix_bin_dir,
# pass in form info to our deployment
"DEPLOYMENT": deployment,
}
cmd = [
"nix",
"develop",
# workaround to pass in info to nixops4 thru env vars, tho impure :(
"--extra-experimental-features",
"configurable-impure-env",
"--command",
"nixops4",
"apply",
"test",
]
subprocess.run(
cmd,
cwd=settings.repo_dir,
env=env,
)
return obj
# TODO(@fricklerhandwerk):