WIP: trigger nixops from panel #246
9 changed files with 119 additions and 7 deletions
|
@ -58,7 +58,10 @@
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.nil
|
pkgs.nil
|
||||||
inputs'.agenix.packages.default
|
inputs'.agenix.packages.default
|
||||||
inputs'.nixops4.packages.default
|
(inputs'.nixops4.packages.default.overrideAttrs {
|
||||||
|
impureEnvVars = [ "DEPLOYMENT" ];
|
||||||
|
})
|
||||||
|
pkgs.openssh
|
||||||
pkgs.httpie
|
pkgs.httpie
|
||||||
pkgs.jq
|
pkgs.jq
|
||||||
];
|
];
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1,17 +1,26 @@
|
||||||
{
|
{
|
||||||
|
# inputs,
|
||||||
config,
|
config,
|
||||||
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
name = "panel";
|
name = "panel";
|
||||||
panel = (import ../../../panel/default.nix { }).package;
|
panel = (import ../../../panel/default.nix { }).package;
|
||||||
in
|
in
|
||||||
|
# builtins.trace args.pkgs
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../../../panel/nix/configuration.nix
|
../../../panel/nix/configuration.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
nix.settings = {
|
||||||
|
extra-experimental-features = "configurable-impure-env";
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
|
# inputs.self.outPath
|
||||||
|
# ../../..
|
||||||
panel
|
panel
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -33,7 +42,12 @@ in
|
||||||
settings = {
|
settings = {
|
||||||
DATABASE_URL = "sqlite:///var/lib/${name}/db.sqlite3";
|
DATABASE_URL = "sqlite:///var/lib/${name}/db.sqlite3";
|
||||||
CREDENTIALS_DIRECTORY = "/var/lib/${name}/.credentials";
|
CREDENTIALS_DIRECTORY = "/var/lib/${name}/.credentials";
|
||||||
STATIC_ROOT = "/var/lib/${name}/static";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
systemd.services.${name}.environment = {
|
||||||
|
STATIC_ROOT = "/var/lib/${name}/static";
|
||||||
|
# REPO_DIR = inputs.self.outPath;
|
||||||
|
REPO_DIR = ../../..;
|
||||||
|
NIX_DIR = pkgs.nix;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ in
|
||||||
export CREDENTIALS_DIRECTORY=${builtins.toString ./.credentials}
|
export CREDENTIALS_DIRECTORY=${builtins.toString ./.credentials}
|
||||||
export DATABASE_URL="sqlite:///${toString ./src}/db.sqlite3"
|
export DATABASE_URL="sqlite:///${toString ./src}/db.sqlite3"
|
||||||
'';
|
'';
|
||||||
|
NIX_DIR = pkgs.nix;
|
||||||
};
|
};
|
||||||
|
|
||||||
tests = pkgs'.callPackage ./nix/tests.nix { };
|
tests = pkgs'.callPackage ./nix/tests.nix { };
|
||||||
|
|
|
@ -39,11 +39,11 @@ class Configuration(BaseModel):
|
||||||
# XXX: hard-code available apex domains for now,
|
# XXX: hard-code available apex domains for now,
|
||||||
# they will be prefixed by the user name
|
# they will be prefixed by the user name
|
||||||
class Domain(Enum):
|
class Domain(Enum):
|
||||||
EU = "fediversity.eu"
|
# EU = "fediversity.eu"
|
||||||
NET = "fediversity.net"
|
NET = "fediversity.net"
|
||||||
|
|
||||||
domain: Domain = Field(
|
domain: Domain = Field(
|
||||||
default=Domain.EU,
|
default=Domain.NET,
|
||||||
description="DNS domain where to expose services"
|
description="DNS domain where to expose services"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,30 @@ body
|
||||||
margin: 0
|
margin: 0
|
||||||
font-family: sans-serif
|
font-family: sans-serif
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
|
|
||||||
|
.loader
|
||||||
|
width: 48px
|
||||||
|
height: 48px
|
||||||
|
border: 5px solid #000
|
||||||
|
border-bottom-color: #F34508
|
||||||
|
border-radius: 50%
|
||||||
|
display: inline-block
|
||||||
|
box-sizing: border-box
|
||||||
|
animation: rotation 1s linear infinite
|
||||||
|
|
||||||
|
@keyframes rotation
|
||||||
|
0% { transform: rotate(0deg) }
|
||||||
|
100% { transform: rotate(360deg) }
|
||||||
|
|
||||||
|
#spinner-container
|
||||||
|
position: absolute
|
||||||
|
top: 50%
|
||||||
|
left: 50%
|
||||||
|
transform: translate(-50%, -50%)
|
||||||
|
display: block
|
||||||
|
|
||||||
|
.htmx-indicator
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.htmx-request .htmx-indicator
|
||||||
|
display: inline-block
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
{% load compress %}
|
{% load compress %}
|
||||||
{% compress css %}
|
{% compress css %}
|
||||||
|
|
|
@ -5,7 +5,18 @@
|
||||||
|
|
||||||
{{ form.as_p }}
|
{{ form.as_p }}
|
||||||
|
|
||||||
<button class="button" disabled>Deploy</button>
|
<button id="deploy-button" class="button"
|
||||||
<button class="button" type="submit" >Save</button>
|
hx-post="{% url 'configuration_form' %}"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-indicator="#spinner-container">
|
||||||
|
Deploy
|
||||||
|
<span class="htmx-indicator loader"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="button" type="submit" name="save">Save</button>
|
||||||
|
|
||||||
|
<div id="spinner-container" class="htmx-indicator">
|
||||||
|
<span class="loader"></span>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib.auth.models import User
|
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 django.http import JsonResponse
|
||||||
|
|
||||||
from panel import models
|
from panel import models
|
||||||
from panel.configuration import forms
|
from panel.configuration import forms
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Index(TemplateView):
|
class Index(TemplateView):
|
||||||
template_name = 'index.html'
|
template_name = 'index.html'
|
||||||
|
|
||||||
|
@ -41,6 +48,44 @@ class ConfigurationForm(LoginRequiredMixin, FormView):
|
||||||
operator=self.request.user,
|
operator=self.request.user,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "deploy" in self.request.POST.keys():
|
||||||
|
threading.Thread(target=self.run_deployment, args=(obj,)).start()
|
||||||
|
|||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def run_deployment(self, obj):
|
||||||
|
if "deploy" in self.request.POST.keys():
|
||||||
kiara
commented
@kevin is there a reason we perform this check twice now? @kevin is there a reason we perform this check twice now?
|
|||||||
|
print("DEPLOYING:")
|
||||||
|
print(os.getenv("REPO_DIR"))
|
||||||
|
print(os.getenv("NIX_DIR"))
|
||||||
|
submission = obj.parsed_value.model_dump_json()
|
||||||
|
deployment = json.dumps(json.loads(submission) | {
|
||||||
|
"initialUser": {
|
||||||
|
"displayName": "Testy McTestface",
|
||||||
|
"username": "test",
|
||||||
|
"password": "testtest",
|
||||||
|
"email": "test@test.com",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
env = {
|
||||||
|
"DEPLOYMENT": deployment,
|
||||||
|
"PATH": f"{os.getenv("NIX_DIR")}/bin/",
|
||||||
|
}
|
||||||
|
print(f"env: {env}")
|
||||||
|
print(f"Path: {os.getcwd()}/..")
|
||||||
|
cmd = [
|
||||||
|
"nix",
|
||||||
|
"develop",
|
||||||
|
"--extra-experimental-features",
|
||||||
|
"configurable-impure-env",
|
||||||
|
"--command",
|
||||||
|
"nixops4",
|
||||||
|
"--show-trace",
|
||||||
|
"--verbose",
|
||||||
|
"apply",
|
||||||
|
"test",
|
||||||
|
]
|
||||||
|
subprocess.run(cmd, cwd=os.getenv("REPO_DIR") or f"{os.getcwd()}/..", env=env)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
# TODO(@fricklerhandwerk):
|
# TODO(@fricklerhandwerk):
|
||||||
|
|
Loading…
Add table
Reference in a new issue
@kevin do we have a way to return info back to the client this way? or would the client know what it needs to know for now?