WIP: New module for handling podman pod

Handles basic container, needs to be expanded to all options
This commit is contained in:
pazpi 2024-08-25 15:44:51 +02:00
parent 3fbf5735fe
commit c243852601
No known key found for this signature in database
GPG key ID: 0942571C4B9966BE

View file

@ -0,0 +1,170 @@
# Save this as podman-pod.nix
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.podmanPods;
podOptions = { name, config, ... }: {
options = {
name = mkOption {
type = types.str;
description = "Name of the pod";
};
ports = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of port mappings (e.g. ['8080:80'])";
};
containers = mkOption {
type = types.attrsOf (types.submodule {
options = {
image = mkOption {
type = types.str;
description = "Docker image for the container";
};
extraOptions = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Additional options for the container";
};
};
});
default = { };
description = "Containers to run in the pod";
};
};
};
createPodScript = name: podDef:
let
podDefinitionString = builtins.toJSON { inherit (podDef) ports; };
in
pkgs.writeScript "manage-pod-${name}.sh" ''
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p htop curl
set -e
POD_NAME="${name}"
POD_DEFINITION='${podDefinitionString}'
create_pod() {
podman pod create --name "$POD_NAME" \
${concatStringsSep " " (map (port: "--publish ${port}") podDef.ports)}
}
if podman pod exists "$POD_NAME"; then
CURRENT_CONFIG=$(podman pod inspect "$POD_NAME" | jq -c '.[0] | {ports: [.PortMappings[].HostPort | tostring + ":" + (.ContainerPort | tostring)]}')
if [ "$CURRENT_CONFIG" != "$POD_DEFINITION" ]; then
echo "Pod configuration has changed. Recreating pod..."
podman pod rm -f "$POD_NAME"
create_pod
else
echo "Pod configuration unchanged."
fi
else
echo "Pod does not exist. Creating..."
create_pod
fi
'';
in
{
options.services.podmanPods = mkOption {
type = types.attrsOf (types.submodule podOptions);
default = { };
description = "Podman pods to create";
};
config = mkIf (cfg != { }) {
virtualisation.podman.enable = true;
virtualisation.oci-containers.backend = "podman";
environment.systemPackages = [ pkgs.jq ];
systemd.services = mapAttrs'
(name: podDef:
nameValuePair "podman-pod-${name}" {
description = "Manage Podman pod: ${name}";
serviceConfig = {
Type = "oneshot";
ExecStart = "${createPodScript name podDef}";
};
path = [ pkgs.podman ];
wantedBy = [ "multi-user.target" ];
}
)
cfg //
mapAttrs'
(podName: podDef:
nameValuePair "podman-pod-${podName}" {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
}
)
cfg //
mapAttrs'
(podName: podDef:
nameValuePair "podman-${podName}" {
after = [ "podman-pod-${podName}.service" ];
requires = [ "podman-pod-${podName}.service" ];
partOf = [ "podman-pod-${podName}.service" ];
}
)
(flattenAttrs (mapAttrsToList
(podName: podDef:
mapAttrs'
(containerName: containerDef:
nameValuePair "${podName}-${containerName}" containerDef
)
podDef.containers
)
cfg));
virtualisation.oci-containers.containers = flatten (mapAttrsToList
(podName: podDef:
mapAttrsToList
(containerName: containerDef:
nameValuePair "${podName}-${containerName}" ({
inherit (containerDef) image;
extraOptions = [ "--pod=${podName}" ] ++ containerDef.extraOptions;
})
)
podDef.containers
)
cfg);
networking.firewall.allowedTCPPorts = flatten (mapAttrsToList
(name: podDef:
map (portMapping: lib.toInt (lib.head (lib.splitString ":" portMapping))) podDef.ports
)
cfg);
# systemd.services = mapAttrs'
# (podName: podDef:
# nameValuePair "podman-pod-${podName}" {
# after = [ "network.target" ];
# wantedBy = [ "multi-user.target" ];
# }
# )
# cfg //
# mapAttrs'
# (podName: podDef:
# nameValuePair "podman-${podName}" {
# after = [ "podman-pod-${podName}.service" ];
# requires = [ "podman-pod-${podName}.service" ];
# partOf = [ "podman-pod-${podName}.service" ];
# }
# )
# (flattenAttrs (mapAttrsToList
# (podName: podDef:
# mapAttrs'
# (containerName: containerDef:
# nameValuePair "${podName}-${containerName}" containerDef
# )
# podDef.containers
# )
# cfg));
};
}