1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-03-31 04:04:32 +00:00

podman: use dependency quadlets directly in build for generator

This commit is contained in:
Nicholas Hassan 2025-02-12 22:10:25 +10:30 committed by Austin Horstman
parent eb5d59dac9
commit 4108ec3aa8
4 changed files with 80 additions and 64 deletions

View file

@ -9,54 +9,46 @@ let
createQuadletSource = name: containerDef:
let
formatServiceNameForType = type: name:
{
image = "podman-${name}-image.service";
build = "podman-${name}-build.service";
network = "podman-${name}-network.service";
volume = "podman-${name}-volume.service";
}."${type}";
# formatServiceNameForType = type: name:
# {
# image = "${name}-image.service";
# build = "${name}-build.service";
# network = "${name}-network.service";
# volume = "${name}-volume.service";
# }."${type}";
dependencyByHomeManagerQuadlet = type: name:
let
definitionsOfType =
filter (q: q.resourceType == type) cfg.internal.quadletDefinitions;
matchingName =
filter (q: q.serviceName == "podman-${name}") definitionsOfType;
in if ((length matchingName) == 1) then
[ (formatServiceNameForType type name) ]
dependencyBySuffix = type: name:
if (hasInfix ".${type}" name) then
let
baseName = elemAt (splitString ".${type}" name) 0;
in
if (hasAttr (builtins.trace (baseName) baseName) cfg.internal.builtQuadlets) then
[ (cfg.internal.builtQuadlets.${baseName}) ]
else
[ ]
else
[ ];
forEachValue = type: value:
let resolve = v: dependencyByHomeManagerQuadlet type v;
in if isList value then
concatLists (map resolve value)
else
resolve value;
withResolverFor = type: value:
{
"image" = forEachValue "image" value;
"build" = forEachValue "build" value;
"network" = forEachValue "network" value;
"volume" = let
a = if isList value then value else [ value ];
volumes = map (v: elemAt (splitString ":" v) 0) a;
in forEachValue "volume" volumes;
}.${type};
let
resolve = v: dependencyBySuffix type v;
in
if builtins.isList value
then builtins.concatLists (map resolve value) # Flatten list of lists
else resolve value;
dependencyServices = (withResolverFor "image" containerDef.image)
++ (withResolverFor "build" containerDef.image)
++ (withResolverFor "network" containerDef.network)
++ (withResolverFor "volume" containerDef.volumes);
dependencyServices = (withResolverFor "image" containerDef.image) ++
(withResolverFor "build" containerDef.image) ++
(withResolverFor "network" containerDef.network) ++
(withResolverFor "volume" containerDef.volumes);
resolvedImage = if (builtins.hasAttr containerDef.image cfg.images) then
cfg.images."${containerDef.image}".image
else if (builtins.hasAttr containerDef.image cfg.builds) then
"localhost/homemanager/${containerDef.image}"
else
containerDef.image;
getActualImage =
if (builtins.hasAttr containerDef.image cfg.images) then
cfg.images."${containerDef.image}".image
else if (builtins.hasAttr containerDef.image cfg.builds) then
"localhost/homemanager/${containerDef.image}"
else
containerDef.image;
quadlet = (podman-lib.deepMerge {
Container = {
@ -101,29 +93,34 @@ let
TimeoutStopSec = 30;
};
Unit = {
After = dependencyServices;
Requires = dependencyServices;
Description = (if (builtins.isString containerDef.description) then
containerDef.description
else
"Service for container ${name}");
};
} containerDef.extraConfig);
in ''
# Automatically generated by home-manager podman container configuration
# DO NOT EDIT THIS FILE DIRECTLY
#
# ${name}.container
${podman-lib.toQuadletIni quadlet}
'';
in
{
dependencies = dependencyServices;
text = ''
# Automatically generated by home-manager podman container configuration
# DO NOT EDIT THIS FILE DIRECTLY
#
# ${name}.container
${podman-lib.toQuadletIni quadlet}
'';
};
toQuadletInternal = name: containerDef: {
toQuadletInternal = name: containerDef: let
quadletSrc = createQuadletSource name containerDef;
in {
assertions = podman-lib.buildConfigAsserts name containerDef.extraConfig;
dependencies = quadletSrc.dependencies;
resourceType = "container";
serviceName =
"podman-${name}"; # quadlet service name: 'podman-<name>.service'
source =
podman-lib.removeBlankLines (createQuadletSource name containerDef);
podman-lib.removeBlankLines quadletSrc.text;
};
# Define the container user type as the user interface

View file

@ -17,12 +17,14 @@ let
buildInputs = [ cfg.package ];
dontUnpack = true;
# dontUnpack = true;
unpackPhase = ''
mkdir -p $out/quadlets
${concatStringsSep "\n" (map (v: "cp ${v.out}/quadlets/${v.quadletData.serviceName}.${v.quadletData.resourceType} $out/quadlets") quadlet.dependencies)}
'';
installPhase = ''
mkdir $out
# Directory for the quadlet file
mkdir -p $out/quadlets
# Directory for systemd unit files
mkdir -p $out/units
@ -84,5 +86,7 @@ in {
home.activation.podmanQuadletCleanup =
lib.mkIf (lib.length builtQuadlets >= 1)
(lib.hm.dag.entryAfter [ "reloadSystemd" ] activationCleanupScript);
services.podman.internal.builtQuadlets = listToAttrs (map (pkg: { name = removePrefix "podman-" pkg.passthru.quadletData.serviceName; value = pkg; }) builtQuadlets);
};
}

View file

@ -11,6 +11,13 @@ let
description = "List of Nix type assertions.";
};
dependencies = lib.mkOption {
type = with lib.types; listOf package;
default = [ ];
internal = true;
description = "List of systemd service dependencies.";
};
resourceType = lib.mkOption {
type = lib.types.str;
default = "";
@ -33,11 +40,19 @@ let
};
in {
options.services.podman = {
internal.quadletDefinitions = lib.mkOption {
type = lib.types.listOf quadletInternalType;
default = { };
internal = true;
description = "List of quadlet source file content and service names.";
internal = {
quadletDefinitions = lib.mkOption {
type = lib.types.listOf quadletInternalType;
default = { };
internal = true;
description = "List of quadlet source file content and service names.";
};
builtQuadlets = lib.mkOption {
type = with lib.types; attrsOf package;
default = { };
internal = true;
description = "All built quadlets.";
};
};
package = lib.mkOption {

View file

@ -17,9 +17,9 @@
};
containers = {
"my-container" = {
image = "my-img";
network = [ "my-net" "externalnet" ];
volumes = [ "my-vol:/data" ];
image = "my-img.image";
network = [ "my-net.network" "externalnet" ];
volumes = [ "my-vol.volume:/data" ];
};
"my-container-bld" = { image = "my-bld"; };
};