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

View file

@ -17,12 +17,14 @@ let
buildInputs = [ cfg.package ]; 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 = '' installPhase = ''
mkdir $out
# Directory for the quadlet file
mkdir -p $out/quadlets
# Directory for systemd unit files # Directory for systemd unit files
mkdir -p $out/units mkdir -p $out/units
@ -84,5 +86,7 @@ in {
home.activation.podmanQuadletCleanup = home.activation.podmanQuadletCleanup =
lib.mkIf (lib.length builtQuadlets >= 1) lib.mkIf (lib.length builtQuadlets >= 1)
(lib.hm.dag.entryAfter [ "reloadSystemd" ] activationCleanupScript); (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."; 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 { resourceType = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = ""; default = "";
@ -33,11 +40,19 @@ let
}; };
in { in {
options.services.podman = { options.services.podman = {
internal.quadletDefinitions = lib.mkOption { internal = {
type = lib.types.listOf quadletInternalType; quadletDefinitions = lib.mkOption {
default = { }; type = lib.types.listOf quadletInternalType;
internal = true; default = { };
description = "List of quadlet source file content and service names."; 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 { package = lib.mkOption {

View file

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