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 = [ packages = [
pkgs.nil pkgs.nil
inputs'.agenix.packages.default inputs'.agenix.packages.default
inputs'.nixops4.packages.default pkgs.openssh
pkgs.httpie pkgs.httpie
pkgs.jq 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; shellHook = config.pre-commit.installationScript;
}; };

View file

@ -143,7 +143,17 @@ in
## - We add a “test” deployment with all test machines. ## - We add a “test” deployment with all test machines.
nixops4Deployments = genAttrs machines makeDeployment' // { nixops4Deployments = genAttrs machines makeDeployment' // {
default = makeDeployment machines; 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 = flake.nixosConfigurations =
genAttrs machines (makeConfiguration false) genAttrs machines (makeConfiguration false)

View file

@ -21,14 +21,17 @@ in
]; ];
env = { env = {
NPINS_DIRECTORY = toString ../npins; 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 = '' shellHook = ''
# in production, secrets are passed via CREDENTIALS_DIRECTORY by systemd. # in production, secrets are passed via CREDENTIALS_DIRECTORY by systemd.
# use this directory for testing with local secrets # use this directory for testing with local secrets
mkdir -p .credentials mkdir -p $CREDENTIALS_DIRECTORY
echo secret > ${builtins.toString ./.credentials}/SECRET_KEY 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 # Customization via user settings
# This must be at the end, as it must be able to override the above # 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()`. # TODO(@fricklerhandwerk):
# this would make it more obvious which moving parts there are, if that environment is specified for development/staging/production in a visible place. # we may want to do this with a flat environment instead, and get all values from `os.environ.get()`.
user_settings_file = env.get("USER_SETTINGS_FILE", None) # this would make it more obvious which moving parts there are, if that environment is specified for development/staging/production in a visible place.
if user_settings_file is not None: user_settings_file = env["USER_SETTINGS_FILE"]
spec = importlib.util.spec_from_file_location("user_settings", user_settings_file) spec = importlib.util.spec_from_file_location("user_settings", user_settings_file)
if spec is None or spec.loader is None: if spec is None or spec.loader is None:
raise RuntimeError("User settings specification failed!") raise RuntimeError("User settings specification failed!")
module = importlib.util.module_from_spec(spec) module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) spec.loader.exec_module(module)
sys.modules["user_settings"] = module sys.modules["user_settings"] = module
from user_settings import * # noqa: F403 # pyright: ignore [reportMissingImports] 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 }} {{ form.as_p }}
<button class="button" disabled>Deploy</button> <button class="button" type="submit" name="deploy">Deploy</button>
<button class="button" type="submit" >Save</button> <button class="button" type="submit" name="save">Save</button>
</form> </form>
{% endblock %} {% endblock %}

View file

@ -1,4 +1,6 @@
from enum import Enum from enum import Enum
import json
import subprocess
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin 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 import TemplateView, DetailView
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from panel import models from panel import models, settings
from panel.configuration import forms from panel.configuration import forms
@ -41,6 +43,41 @@ class ConfigurationForm(LoginRequiredMixin, FormView):
operator=self.request.user, 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 return obj
# TODO(@fricklerhandwerk): # TODO(@fricklerhandwerk):