WIP: simplify deployment code

This commit is contained in:
Valentin Gagarin 2025-03-31 15:44:23 +02:00
parent f3251ea89f
commit 8fd1e2b75c
2 changed files with 52 additions and 40 deletions
deployment
panel/src/panel

View file

@ -2,7 +2,7 @@
Deployment options as to be presented in the front end.
These are converted to JSON schema in order to generate front-end forms etc.
For this to work, options must not have types `functionTo` or `package` (or `submodule` until [submodule introspection](https://github.com/NixOS/nixpkgs/pull/391544) is merged), and must not access `config` for their default values.
For this to work, options must not have types `functionTo` or `package`, and must not access `config` for their default values.
*/
{
lib,
@ -34,22 +34,30 @@ in
mastodon = {
enable = lib.mkEnableOption "Mastodon";
};
initialUser = {
displayName = mkOption {
type = types.str;
description = "Display name of the user";
};
username = mkOption {
type = types.str;
description = "Username for login";
};
email = mkOption {
type = types.str;
description = "User's email address";
};
password = mkOption {
type = types.str;
description = "Password for login";
initialUser = mkOption {
description = ''
Some services require an initial user to access them.
This option sets the credentials for such an initial user.
'';
type = types.submodule {
options = {
displayName = mkOption {
type = types.str;
description = "Display name of the user";
};
username = mkOption {
type = types.str;
description = "Username for login";
};
email = mkOption {
type = types.str;
description = "User's email address";
};
password = mkOption {
type = types.str;
description = "Password for login";
};
};
};
};
};

View file

@ -14,6 +14,8 @@ from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from pydantic import BaseModel
from panel import models, settings
from panel.configuration import schema
@ -39,7 +41,6 @@ class ConfigurationForm(LoginRequiredMixin, APIView):
success_url = reverse_lazy('configuration_form')
def get_object(self):
"""Get or create the configuration object for the current user"""
obj, created = models.Configuration.objects.get_or_create(
operator=self.request.user,
)
@ -67,31 +68,36 @@ 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 form_valid(self, form):
obj = self.get_object()
obj.value = form.to_python().model_dump_json()
obj.save()
# Check for deploy button
if "deploy" in self.request.POST.keys():
deployment_result, deployment_params = self.deployment(obj)
if deployment_result.returncode == 0:
deployment_status = "Deployment Succeeded"
else:
deployment_status = "Deployment Failed"
def post(self, request):
config = self.get_object()
serializer = schema.Model.drf_serializer(
instance=config.parsed_value,
data=request.data
)
if not serializer.is_valid():
return Response({'serializer': serializer})
config.value = json.dumps(serializer.validated_data)
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_status": deployment_status,
"services": {
"peertube": deployment_params['peertube']['enable'],
"pixelfed": deployment_params['pixelfed']['enable'],
"mastodon": deployment_params['mastodon']['enable']
}
"services": deployment_params.json(),
})
def deployment(self, obj):
submission = obj.parsed_value.model_dump_json()
def deployment(self, config: BaseModel):
# FIXME: let the user specify these from the form (#190)
dummy_user = {
"initialUser": {
@ -101,12 +107,10 @@ class DeploymentStatus(ConfigurationForm):
"email": "test@test.com",
},
}
# serialize back and forth now we still need to manually inject the dummy user
deployment_params = json.dumps(dummy_user | json.loads(submission))
env = {
"PATH": settings.bin_path,
# pass in form info to our deployment
"DEPLOYMENT": deployment_params,
"DEPLOYMENT": config.json()
}
cmd = [
"nix",
@ -123,4 +127,4 @@ class DeploymentStatus(ConfigurationForm):
cwd=settings.repo_dir,
env=env,
)
return deployment_result, json.loads(deployment_params)
return deployment_result, config