mirror of
https://github.com/nix-community/home-manager.git
synced 2025-03-31 04:04:32 +00:00
podman: link dependent quadlets during build
podman's systemd generator can automatically resolve unit dependencies, so instead of us guessing these links to create them, we provide the sources during generation
This commit is contained in:
parent
4108ec3aa8
commit
81bf639da7
10 changed files with 96 additions and 91 deletions
|
@ -7,7 +7,7 @@ let
|
|||
|
||||
createQuadletSource = name: buildDef:
|
||||
let
|
||||
buildConfig = podman-lib.deepMerge {
|
||||
quadlet = podman-lib.deepMerge {
|
||||
Build = {
|
||||
AuthFile = buildDef.authFile;
|
||||
Environment = buildDef.environment;
|
||||
|
@ -30,21 +30,26 @@ let
|
|||
};
|
||||
Unit = { Description = buildDef.description; };
|
||||
} buildDef.extraConfig;
|
||||
in ''
|
||||
# Automatically generated by home-manager for podman build configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.build
|
||||
${podman-lib.toQuadletIni buildConfig}
|
||||
'';
|
||||
in {
|
||||
attrs = quadlet;
|
||||
text = ''
|
||||
# Automatically generated by home-manager for podman build configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.build
|
||||
${podman-lib.toQuadletIni quadlet}
|
||||
'';
|
||||
};
|
||||
|
||||
toQuadletInternal = name: buildDef: {
|
||||
assertions = podman-lib.buildConfigAsserts name buildDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # quadlet service name: 'podman-<name>-build.service
|
||||
source = podman-lib.removeBlankLines (createQuadletSource name buildDef);
|
||||
resourceType = "build";
|
||||
};
|
||||
toQuadletInternal = name: buildDef:
|
||||
let src = createQuadletSource name buildDef;
|
||||
in {
|
||||
assertions = podman-lib.buildConfigAsserts name buildDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # generated service name: 'podman-<name>-build.service
|
||||
source = podman-lib.removeBlankLines src.text;
|
||||
resourceType = "build";
|
||||
};
|
||||
in let
|
||||
buildDefinitionType = types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
|
|
|
@ -9,20 +9,10 @@ let
|
|||
|
||||
createQuadletSource = name: containerDef:
|
||||
let
|
||||
# formatServiceNameForType = type: name:
|
||||
# {
|
||||
# image = "${name}-image.service";
|
||||
# build = "${name}-build.service";
|
||||
# network = "${name}-network.service";
|
||||
# volume = "${name}-volume.service";
|
||||
# }."${type}";
|
||||
|
||||
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
|
||||
let baseName = elemAt (splitString ".${type}" name) 0;
|
||||
in if (hasAttr baseName cfg.internal.builtQuadlets) then
|
||||
[ (cfg.internal.builtQuadlets.${baseName}) ]
|
||||
else
|
||||
[ ]
|
||||
|
@ -30,25 +20,34 @@ let
|
|||
[ ];
|
||||
|
||||
withResolverFor = type: value:
|
||||
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);
|
||||
|
||||
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}"
|
||||
let resolve = v: dependencyBySuffix type v;
|
||||
in if builtins.isList value then
|
||||
builtins.concatLists (map resolve value) # Flatten list of lists
|
||||
else
|
||||
containerDef.image;
|
||||
resolve value;
|
||||
|
||||
dependencyServices = (withResolverFor "image" containerDef.image)
|
||||
++ (withResolverFor "build" containerDef.image)
|
||||
++ (withResolverFor "network" containerDef.network)
|
||||
++ (withResolverFor "volume" containerDef.volumes);
|
||||
|
||||
checkQuadletReference = types: value:
|
||||
if builtins.isList value then
|
||||
builtins.concatLists (map (checkQuadletReference types) value)
|
||||
else
|
||||
let type = findFirst (t: hasInfix ".${t}" value) null types;
|
||||
in if (type != null) then
|
||||
let
|
||||
baseName = elemAt (splitString ".${type}" value) 0;
|
||||
quadletsOfType =
|
||||
filterAttrs (n: v: v.quadletData.resourceType == type)
|
||||
cfg.internal.builtQuadlets;
|
||||
in if (hasAttr baseName quadletsOfType) then
|
||||
[ (replaceStrings [ baseName ] [ "podman-${baseName}" ] value) ]
|
||||
else
|
||||
[ value ]
|
||||
else
|
||||
[ value ];
|
||||
|
||||
quadlet = (podman-lib.deepMerge {
|
||||
Container = {
|
||||
|
@ -62,18 +61,18 @@ let
|
|||
EnvironmentFile = containerDef.environmentFile;
|
||||
Exec = containerDef.exec;
|
||||
Group = containerDef.group;
|
||||
Image = resolvedImage;
|
||||
Image = checkQuadletReference [ "build" "image" ] containerDef.image;
|
||||
IP = containerDef.ip4;
|
||||
IP6 = containerDef.ip6;
|
||||
Label =
|
||||
(containerDef.labels // { "nix.home-manager.managed" = true; });
|
||||
Network = containerDef.network;
|
||||
Network = checkQuadletReference [ "network" ] containerDef.network;
|
||||
NetworkAlias = containerDef.networkAlias;
|
||||
PodmanArgs = containerDef.extraPodmanArgs;
|
||||
PublishPort = containerDef.ports;
|
||||
UserNS = containerDef.userNS;
|
||||
User = containerDef.user;
|
||||
Volume = containerDef.volumes;
|
||||
Volume = checkQuadletReference [ "volume" ] containerDef.volumes;
|
||||
};
|
||||
Install = {
|
||||
WantedBy = optionals containerDef.autoStart [
|
||||
|
@ -99,9 +98,9 @@ let
|
|||
"Service for container ${name}");
|
||||
};
|
||||
} containerDef.extraConfig);
|
||||
in
|
||||
{
|
||||
in {
|
||||
dependencies = dependencyServices;
|
||||
attrs = quadlet;
|
||||
text = ''
|
||||
# Automatically generated by home-manager podman container configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
|
@ -111,17 +110,16 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
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 quadletSrc.text;
|
||||
};
|
||||
toQuadletInternal = name: containerDef:
|
||||
let src = createQuadletSource name containerDef;
|
||||
in {
|
||||
assertions = podman-lib.buildConfigAsserts name containerDef.extraConfig;
|
||||
dependencies = src.dependencies;
|
||||
resourceType = "container";
|
||||
serviceName =
|
||||
"podman-${src.attrs.Container.ContainerName}"; # generated service name: 'podman-<name>.service'
|
||||
source = podman-lib.removeBlankLines src.text;
|
||||
};
|
||||
|
||||
# Define the container user type as the user interface
|
||||
containerDefinitionType = types.submodule {
|
||||
|
|
|
@ -11,7 +11,7 @@ let
|
|||
(if imageDef.username != null then imageDef.username else "")
|
||||
+ (if imageDef.password != null then ":${imageDef.password}" else "");
|
||||
|
||||
imageConfig = podman-lib.deepMerge {
|
||||
quadlet = podman-lib.deepMerge {
|
||||
Image = {
|
||||
AuthFile = imageDef.authFile;
|
||||
CertDir = imageDef.certDir;
|
||||
|
@ -40,13 +40,13 @@ let
|
|||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.image
|
||||
${podman-lib.toQuadletIni imageConfig}
|
||||
${podman-lib.toQuadletIni quadlet}
|
||||
'';
|
||||
|
||||
toQuadletInternal = name: imageDef: {
|
||||
assertions = podman-lib.buildConfigAsserts name imageDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # quadlet service name: 'podman-<name>-image.service
|
||||
"podman-${name}"; # generated service name: 'podman-<name>-image.service
|
||||
source = podman-lib.removeBlankLines (createQuadletSource name imageDef);
|
||||
resourceType = "image";
|
||||
};
|
||||
|
|
|
@ -15,13 +15,13 @@ let
|
|||
pkgs.stdenv.mkDerivation {
|
||||
name = "home-${quadlet.resourceType}-${quadlet.serviceName}";
|
||||
|
||||
buildInputs = [ cfg.package ];
|
||||
|
||||
# dontUnpack = true;
|
||||
buildInputs = [ cfg.package ] ++ quadlet.dependencies;
|
||||
|
||||
unpackPhase = ''
|
||||
mkdir -p $out/quadlets
|
||||
${concatStringsSep "\n" (map (v: "cp ${v.out}/quadlets/${v.quadletData.serviceName}.${v.quadletData.resourceType} $out/quadlets") quadlet.dependencies)}
|
||||
${concatStringsSep "\n" (map (v:
|
||||
"ln -s ${v.out}/quadlets/${v.quadletData.serviceName}.${v.quadletData.resourceType} $out/quadlets")
|
||||
quadlet.dependencies)}
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
|
@ -42,7 +42,6 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
# Create a derivation for each quadlet spec
|
||||
builtQuadlets = map buildPodmanQuadlet cfg.internal.quadletDefinitions;
|
||||
|
||||
accumulateUnitFiles = prefix: path: quadlet:
|
||||
|
@ -87,6 +86,9 @@ in {
|
|||
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);
|
||||
services.podman.internal.builtQuadlets = listToAttrs (map (pkg: {
|
||||
name = removePrefix "podman-" pkg.passthru.quadletData.serviceName;
|
||||
value = pkg;
|
||||
}) builtQuadlets);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ let
|
|||
|
||||
createQuadletSource = name: networkDef:
|
||||
let
|
||||
cfg = (podman-lib.deepMerge {
|
||||
quadlet = (podman-lib.deepMerge {
|
||||
Install = {
|
||||
WantedBy = (if networkDef.autoStart then [
|
||||
"default.target"
|
||||
|
@ -50,13 +50,13 @@ let
|
|||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.network
|
||||
${podman-lib.toQuadletIni cfg}
|
||||
${podman-lib.toQuadletIni quadlet}
|
||||
'';
|
||||
|
||||
toQuadletInternal = name: networkDef: {
|
||||
assertions = podman-lib.buildConfigAsserts name networkDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # quadlet service name: 'podman-<name>-network.service'
|
||||
"podman-${name}"; # generated service name: 'podman-<name>-network.service'
|
||||
source = podman-lib.removeBlankLines (createQuadletSource name networkDef);
|
||||
resourceType = "network";
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ let
|
|||
|
||||
createQuadletSource = name: volumeDef:
|
||||
let
|
||||
volumeConfig = podman-lib.deepMerge {
|
||||
quadlet = podman-lib.deepMerge {
|
||||
Install = {
|
||||
WantedBy = optionals volumeDef.autoStart [
|
||||
"default.target"
|
||||
|
@ -49,13 +49,13 @@ let
|
|||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.volume
|
||||
${podman-lib.toQuadletIni volumeConfig}
|
||||
${podman-lib.toQuadletIni quadlet}
|
||||
'';
|
||||
|
||||
toQuadletInternal = name: volumeDef: {
|
||||
assertions = podman-lib.buildConfigAsserts name volumeDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # quadlet service name: 'podman-<name>-volume.service'
|
||||
"podman-${name}"; # generated service name: 'podman-<name>-volume.service'
|
||||
source = podman-lib.removeBlankLines (createQuadletSource name volumeDef);
|
||||
resourceType = "volume";
|
||||
};
|
||||
|
|
|
@ -27,4 +27,4 @@ Wants=podman-user-wait-network-online.service
|
|||
After=podman-user-wait-network-online.service
|
||||
Description=Service for build my-bld
|
||||
RequiresMountsFor=%t/containers
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-build-podman-my-bld/quadlets/podman-my-bld.build
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-container-podman-my-container-bld/quadlets/podman-my-bld.build
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
[X-Container]
|
||||
ContainerName=my-container-bld
|
||||
Environment=
|
||||
Image=localhost/homemanager/my-bld
|
||||
Image=podman-my-bld.build
|
||||
Label=nix.home-manager.managed=true
|
||||
|
||||
[Install]
|
||||
|
@ -26,13 +26,13 @@ Delegate=yes
|
|||
Type=notify
|
||||
NotifyAccess=all
|
||||
SyslogIdentifier=%N
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container-bld --cidfile=%t/%N.cid --replace --rm --cgroups=split --sdnotify=conmon -d --label nix.home-manager.managed=true localhost/homemanager/my-bld
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container-bld --cidfile=%t/%N.cid --replace --rm --cgroups=split --sdnotify=conmon -d --label nix.home-manager.managed=true homemanager/my-bld
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
After=podman-my-bld-build.service
|
||||
Description=Service for container my-container-bld
|
||||
Requires=podman-my-bld-build.service
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-container-podman-my-container-bld/quadlets/podman-my-container-bld.container
|
||||
Requires=podman-my-bld-build.service
|
||||
After=podman-my-bld-build.service
|
||||
RequiresMountsFor=%t/containers
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
[X-Container]
|
||||
ContainerName=my-container
|
||||
Environment=
|
||||
Image=docker.io/alpine:latest
|
||||
Image=podman-my-img.image
|
||||
Label=nix.home-manager.managed=true
|
||||
Network=my-net
|
||||
Network=podman-my-net.network
|
||||
Network=externalnet
|
||||
Volume=my-vol:/data
|
||||
Volume=podman-my-vol.volume:/data
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
@ -34,12 +34,12 @@ ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --na
|
|||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
After=podman-my-img-image.service
|
||||
After=podman-my-net-network.service
|
||||
After=podman-my-vol-volume.service
|
||||
Description=Service for container my-container
|
||||
Requires=podman-my-img-image.service
|
||||
Requires=podman-my-net-network.service
|
||||
Requires=podman-my-vol-volume.service
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-container-podman-my-container/quadlets/podman-my-container.container
|
||||
Requires=podman-my-img-image.service
|
||||
After=podman-my-img-image.service
|
||||
RequiresMountsFor=%t/containers
|
||||
Requires=podman-my-net-network.service
|
||||
After=podman-my-net-network.service
|
||||
Requires=podman-my-vol-volume.service
|
||||
After=podman-my-vol-volume.service
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
network = [ "my-net.network" "externalnet" ];
|
||||
volumes = [ "my-vol.volume:/data" ];
|
||||
};
|
||||
"my-container-bld" = { image = "my-bld"; };
|
||||
"my-container-bld" = { image = "my-bld.build"; };
|
||||
};
|
||||
images."my-img" = { image = "docker.io/alpine:latest"; };
|
||||
networks."my-net" = {
|
||||
|
|
Loading…
Add table
Reference in a new issue