diff --git a/modules/services/podman-linux/containers.nix b/modules/services/podman-linux/containers.nix index d5836119a..32e643a5b 100644 --- a/modules/services/podman-linux/containers.nix +++ b/modules/services/podman-linux/containers.nix @@ -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 diff --git a/modules/services/podman-linux/install-quadlet.nix b/modules/services/podman-linux/install-quadlet.nix index d0157020c..2f909ae45 100644 --- a/modules/services/podman-linux/install-quadlet.nix +++ b/modules/services/podman-linux/install-quadlet.nix @@ -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); }; } diff --git a/modules/services/podman-linux/options.nix b/modules/services/podman-linux/options.nix index 242028aea..850660c00 100644 --- a/modules/services/podman-linux/options.nix +++ b/modules/services/podman-linux/options.nix @@ -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 { diff --git a/tests/modules/services/podman-linux/integration.nix b/tests/modules/services/podman-linux/integration.nix index 26aef7019..565c22cca 100644 --- a/tests/modules/services/podman-linux/integration.nix +++ b/tests/modules/services/podman-linux/integration.nix @@ -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"; }; };