219 lines
6.3 KiB
Nix
219 lines
6.3 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.my.virtualisation.podmanPods;
|
|
|
|
# Get the options from the original oci-containers module
|
|
# containerOptions = (
|
|
# filterAttrs (
|
|
# n: v: n != "definition"
|
|
# ) config.virtualisation.oci-containers.containers.type.getSubOptions
|
|
# );
|
|
|
|
# containerDefinition = mkOption {
|
|
# type = types.attrs;
|
|
# description = "The container definition, derived from virtualisation.oci-containers.containers.";
|
|
# example = {
|
|
# image = "nginx:latest";
|
|
# ports = [ "8080:80" ];
|
|
# };
|
|
# default = { };
|
|
# };
|
|
|
|
# containerDefinition = mkOption {
|
|
# type = types.attrs;
|
|
# description = "The container definition, derived from virtualisation.oci-containers.containers.";
|
|
# example = {
|
|
# image = "nginx:latest";
|
|
# ports = [ "8080:80" ];
|
|
# };
|
|
# default = {};
|
|
|
|
# };
|
|
# # config.virtualisation.oci-containers.containers.type.getSubOptions;
|
|
|
|
containerDefinition = config.virtualisation.oci-containers.containers.type.getSubOptions;
|
|
|
|
# Add our enable option
|
|
extendedContainerOptions = containerDefinition // {
|
|
enable = mkEnableOption "Enable this container";
|
|
};
|
|
|
|
podOptions = {
|
|
options = with types; {
|
|
|
|
name = mkOption {
|
|
type = str;
|
|
description = "Name of the pod";
|
|
};
|
|
|
|
ports = mkOption {
|
|
type = listOf str;
|
|
default = [ ];
|
|
description = "List of port mappings (e.g. ['8080:80'])";
|
|
};
|
|
|
|
containers = mkOption {
|
|
type = attrsOf (submodule {
|
|
options = extendedContainerOptions;
|
|
});
|
|
default = { };
|
|
description = "Attribute set of OCI container configurations for this set";
|
|
};
|
|
};
|
|
};
|
|
|
|
createPodScript =
|
|
name: podDef:
|
|
let
|
|
podDefinitionString = builtins.toJSON { inherit (podDef) ports; };
|
|
in
|
|
pkgs.writeScript "manage-pod-${name}.sh" ''
|
|
#! /bin/sh
|
|
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 '{ports: .[0].InfraConfig.PortBindings | to_entries | map("\(.value[0].HostPort):\(.key | split("/")[0])") | sort'})
|
|
echo "POD_DEFINITION: $POD_DEFINITION"
|
|
echo "CURRENT_CONFIG: $CURRENT_CONFIG"
|
|
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
|
|
'';
|
|
|
|
# enabledContainers = lib.flatten (
|
|
# mapAttrs (
|
|
# podName: podConfig: filterAttrs (name: value: value.enable or true) podConfig.containers
|
|
# ) cfg
|
|
# );
|
|
|
|
# flattenPodContainers =
|
|
# pods:
|
|
# mapAttrs' (
|
|
# podName: pod:
|
|
# mapAttrs' (
|
|
# containerName: container:
|
|
# nameValuePair "${podName}-${containerName}" (
|
|
# container
|
|
# # // {
|
|
# # inherit (pod) name;
|
|
# # extraOptions = (container.extraOptions or [ ]) ++ [ "--pod=${pod.name}" ];
|
|
# # }
|
|
# )
|
|
# ) (filterAttrs (n: v: v.enable or true) pod.containers)
|
|
# ) pods;
|
|
|
|
in
|
|
{
|
|
options.my.virtualisation.podmanPods = mkOption {
|
|
type = types.attrsOf (types.submodule podOptions);
|
|
default = { };
|
|
description = "Podman pods to create";
|
|
};
|
|
|
|
config = mkIf (cfg != { }) {
|
|
|
|
my.virtualisation.podman.enable = true;
|
|
|
|
environment.systemPackages = [ pkgs.jq ];
|
|
|
|
# virtualisation.oci-containers.containers = enabledContainers;
|
|
|
|
# virtualisation.oci-containers.containers = flattenPodContainers cfg;
|
|
|
|
# virtualisation.oci-containers.containers = lib.mkMerge (
|
|
# map (entry: entry.container) (filter (entry: entry.enable) cfg.containers)
|
|
# );
|
|
|
|
# virtualisation.oci-containers.containers = listToAttrs (flatten (mapAttrsToList
|
|
# (podName: podDef:
|
|
# mapAttrs
|
|
# (containerName: containerDef:
|
|
# filterAttrs (attrName: attrValue: attrName != "enable") containerDef
|
|
# # nameValuePair "${podName}-${containerName}" ({
|
|
# # inherit (containerDef) image;
|
|
# # extraOptions = [ "--pod=${podName}" ] ++ containerDef.extraOptions;
|
|
# # })
|
|
# )
|
|
# podDef.containers
|
|
# )
|
|
# cfg));
|
|
|
|
# virtualisation.oci-containers.containers = lib.flatten
|
|
# (mapAttrs
|
|
# (podName: podConfig:
|
|
# mapAttrs
|
|
# (containerName: containerConfig:
|
|
# filterAttrs (attrName: attrValue: attrName != "enable") containerConfig
|
|
# )
|
|
# (filterAttrs (name: value: value.enable) podConfig.containers)
|
|
# )
|
|
# (filterAttrs (podName: podConfig: podConfig.enable) cfg)
|
|
# );
|
|
# mapAttrs
|
|
# (name: value:
|
|
# filterAttrs (n: v: n != "enable") value
|
|
# )
|
|
# (filterAttrs (name: value: value.enable) cfg.containers);
|
|
|
|
networking.firewall.allowedTCPPorts = flatten (
|
|
mapAttrsToList (
|
|
name: podDef: map (portMapping: lib.toInt (lib.head (lib.splitString ":" portMapping))) podDef.ports
|
|
) cfg
|
|
);
|
|
|
|
systemd.services =
|
|
let
|
|
podServices = mapAttrs' (
|
|
name: podDef:
|
|
nameValuePair "podman-pod-${name}" {
|
|
description = "Manage Podman pod: ${name}";
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStart = "${createPodScript name podDef}";
|
|
};
|
|
path = [
|
|
pkgs.jq
|
|
pkgs.podman
|
|
];
|
|
after = [ "network.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
}
|
|
) cfg;
|
|
|
|
containerServices = mapAttrs' (
|
|
name: container:
|
|
nameValuePair "podman-${name}" {
|
|
after = [ "podman-pod-${lib.head (lib.splitString "-" name)}.service" ];
|
|
requires = [ "podman-pod-${lib.head (lib.splitString "-" name)}.service" ];
|
|
partOf = [ "podman-pod-${lib.head (lib.splitString "-" name)}.service" ];
|
|
}
|
|
) config.containers;
|
|
in
|
|
podServices // containerServices;
|
|
|
|
};
|
|
}
|