mirror of
https://github.com/nix-community/home-manager
synced 2025-01-30 12:55:02 +01:00
podman: added volume, image, and build quadlets
This commit is contained in:
parent
f8ef4541bb
commit
cc9881c1fb
21 changed files with 996 additions and 32 deletions
|
@ -18,6 +18,7 @@
|
|||
local manifestFile="${config.xdg.configHome}/podman/$2"
|
||||
local extraListCommands="''${3:-}"
|
||||
[[ $resourceType = "container" ]] && extraListCommands+=" -a"
|
||||
[[ $resourceType = "volume" ]] && extraListCommands+=" --filter label=nix.home-manager.preserve=false"
|
||||
|
||||
[ ! -f "$manifestFile" ] && VERBOSE_ENABLED && echo "Manifest does not exist: $manifestFile" && return 0
|
||||
|
||||
|
@ -69,19 +70,20 @@
|
|||
commands=()
|
||||
case "$resourceType" in
|
||||
"container")
|
||||
commands+="${config.services.podman.package}/bin/podman $resourceType stop $resource"
|
||||
commands+="${config.services.podman.package}/bin/podman $resourceType rm -f $resource"
|
||||
commands+=("${config.services.podman.package}/bin/podman $resourceType stop $resource")
|
||||
commands+=("${config.services.podman.package}/bin/podman $resourceType rm -f $resource")
|
||||
;;
|
||||
"network")
|
||||
commands+="${config.services.podman.package}/bin/podman $resourceType rm $resource"
|
||||
"image" | "network" | "volume")
|
||||
commands+=("${config.services.podman.package}/bin/podman $resourceType rm $resource")
|
||||
;;
|
||||
esac
|
||||
for command in "''${commands[@]}"; do
|
||||
command=$(echo $command | tr -d ';&|`')
|
||||
DRYRUN_ENABLED && echo "Would run: $command" && continue || true
|
||||
VERBOSE_ENABLED && echo "Running: $command" || true
|
||||
if [[ "$(eval "$command")" != "$resource" ]]; then
|
||||
if [[ "$(eval "$command")" != *"$resource" ]]; then
|
||||
echo -e "\tCommand failed: ''${command}"
|
||||
[ "$resourceType" == "image" ] && resourceType="ancestor"
|
||||
usedByContainers=$(${config.services.podman.package}/bin/podman container ls -a --filter "$resourceType=$resource" --format "{{.Names}}")
|
||||
echo -e "\t$resource in use by containers: $usedByContainers"
|
||||
fi
|
||||
|
@ -92,7 +94,7 @@
|
|||
[[ "$@" == *"--verbose"* ]] && VERBOSE="true"
|
||||
[[ "$@" == *"--dry-run"* ]] && DRY_RUN="true"
|
||||
|
||||
for type in "container" "network"; do
|
||||
for type in "container" "image" "network" "volume"; do
|
||||
cleanup "$type" "''${type}s.manifest"
|
||||
done
|
||||
'';
|
||||
|
|
168
modules/services/podman-linux/builds.nix
Normal file
168
modules/services/podman-linux/builds.nix
Normal file
|
@ -0,0 +1,168 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.podman;
|
||||
|
||||
podman-lib = import ./podman-lib.nix { inherit lib config; };
|
||||
|
||||
createQuadletSource = name: buildDef:
|
||||
let
|
||||
buildConfig = podman-lib.deepMerge {
|
||||
Build = {
|
||||
AuthFile = buildDef.authFile;
|
||||
Environment = buildDef.environment;
|
||||
File = buildDef.file;
|
||||
ImageTag = [ "homemanager/${name}" ] ++ buildDef.tags;
|
||||
Label = buildDef.labels // { "nix.home-manager.managed" = true; };
|
||||
PodmanArgs = buildDef.extraPodmanArgs;
|
||||
SetWorkingDirectory = buildDef.workingDirectory;
|
||||
TLSVerify = buildDef.tlsVerify;
|
||||
};
|
||||
Install = {
|
||||
WantedBy = optionals buildDef.autoStart [
|
||||
"default.target"
|
||||
"multi-user.target"
|
||||
];
|
||||
};
|
||||
Service = {
|
||||
TimeoutStartSec = 300;
|
||||
RemainAfterExit = "yes";
|
||||
};
|
||||
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}
|
||||
'';
|
||||
|
||||
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";
|
||||
};
|
||||
in let
|
||||
buildDefinitionType = types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description =
|
||||
"Whether to start the build on boot. Requires user lingering.";
|
||||
};
|
||||
|
||||
authFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = "Path of the authentication file.";
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "Service for build ${name}";
|
||||
defaultText = "Service for build \${name}";
|
||||
example = "My Build";
|
||||
description = "The description of the build.";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = podman-lib.primitiveAttrs;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
VAR1 = "0:100";
|
||||
VAR2 = true;
|
||||
VAR3 = 5;
|
||||
}
|
||||
'';
|
||||
description = "Environment variables to set in the build.";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = podman-lib.extraConfigType;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
Build = {
|
||||
Arch = "aarch64";
|
||||
};
|
||||
Service = {
|
||||
TimeoutStartSec = 15;
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = "INI sections and values to populate the Build Quadlet.";
|
||||
};
|
||||
|
||||
extraPodmanArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "--retries 5" ];
|
||||
description = "Extra arguments to pass to the podman build command.";
|
||||
};
|
||||
|
||||
file = mkOption {
|
||||
type = types.str;
|
||||
example = literalExpression ''
|
||||
`"xdg.configFile."containerfiles/my-img/Containerfile"`
|
||||
or
|
||||
`"https://github.com/.../my-img/Containerfile"`
|
||||
'';
|
||||
description =
|
||||
"Path to a Containerfile which contains instructions to build the image.";
|
||||
};
|
||||
|
||||
tags = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Name associated with the build.
|
||||
First tag will always be "homemanager/<name>".
|
||||
'';
|
||||
};
|
||||
|
||||
labels = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = { };
|
||||
example = {
|
||||
app = "myapp";
|
||||
some-label = "somelabel";
|
||||
};
|
||||
description = "The labels to apply to the build.";
|
||||
};
|
||||
|
||||
tlsVerify = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description =
|
||||
"Require HTTPS and verification of certificates when contacting registries.";
|
||||
};
|
||||
|
||||
workingDirectory = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = "WorkingDirectory of the systemd unit file.";
|
||||
};
|
||||
};
|
||||
});
|
||||
in {
|
||||
options.services.podman.builds = mkOption {
|
||||
type = types.attrsOf buildDefinitionType;
|
||||
default = { };
|
||||
description = "Defines Podman build quadlet configurations.";
|
||||
};
|
||||
|
||||
config = let buildQuadlets = mapAttrsToList toQuadletInternal cfg.builds;
|
||||
in mkIf cfg.enable {
|
||||
services.podman.internal.quadletDefinitions = buildQuadlets;
|
||||
assertions = flatten (map (build: build.assertions) buildQuadlets);
|
||||
|
||||
xdg.configFile."/podman/images.manifest".text =
|
||||
podman-lib.generateManifestText buildQuadlets;
|
||||
};
|
||||
}
|
|
@ -9,19 +9,66 @@ let
|
|||
|
||||
createQuadletSource = name: containerDef:
|
||||
let
|
||||
mapHmNetworks = network:
|
||||
if builtins.hasAttr network cfg.networks then
|
||||
"podman-${network}-network.service"
|
||||
else
|
||||
null;
|
||||
makeServiceName = name: type:
|
||||
let
|
||||
typeName = (if lib.strings.hasSuffix "s" type then
|
||||
(lib.strings.substring 0 (builtins.stringLength type - 1) type)
|
||||
else
|
||||
type);
|
||||
in "podman-${name}-${typeName}.service";
|
||||
|
||||
extractVolumeName = resource: builtins.head (builtins.split ":" resource);
|
||||
|
||||
standardizeResource = res:
|
||||
let
|
||||
lst = if lib.isList res then
|
||||
res
|
||||
else if res != null then
|
||||
[ res ]
|
||||
else
|
||||
[ ];
|
||||
in map extractVolumeName lst;
|
||||
|
||||
filterManagedResources = resource: definedResources:
|
||||
builtins.filter (x: builtins.elem x definedResources)
|
||||
(standardizeResource resource);
|
||||
|
||||
getDefinedResourceNames = type:
|
||||
let
|
||||
typeName =
|
||||
if lib.strings.hasSuffix "s" type then type else "${type}s";
|
||||
in builtins.attrNames cfg."${typeName}";
|
||||
|
||||
findDefinedImageType = if (builtins.elem containerDef.image
|
||||
(getDefinedResourceNames "builds")) then
|
||||
"builds"
|
||||
else
|
||||
"images";
|
||||
|
||||
getManagedResourceNames = type:
|
||||
let
|
||||
resourceType = if type == "image" then findDefinedImageType else type;
|
||||
in (filterManagedResources (builtins.getAttr type containerDef)
|
||||
(getDefinedResourceNames resourceType));
|
||||
|
||||
getServiceNames = type:
|
||||
let
|
||||
resourceType = if type == "image" then findDefinedImageType else type;
|
||||
in map (name: makeServiceName name resourceType)
|
||||
(getManagedResourceNames type);
|
||||
|
||||
finalConfig = let
|
||||
managedNetworks = if lib.isList containerDef.network then
|
||||
map mapHmNetworks containerDef.network
|
||||
else if containerDef.network != null then
|
||||
map mapHmNetworks [ containerDef.network ]
|
||||
else
|
||||
[ ];
|
||||
managedServices = builtins.concatLists
|
||||
(map (type: getServiceNames type) [ "image" "network" "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}"
|
||||
else
|
||||
containerDef.image;
|
||||
|
||||
in (podman-lib.deepMerge {
|
||||
Container = {
|
||||
AddCapability = containerDef.addCapabilities;
|
||||
|
@ -34,7 +81,7 @@ let
|
|||
EnvironmentFile = containerDef.environmentFile;
|
||||
Exec = containerDef.exec;
|
||||
Group = containerDef.group;
|
||||
Image = containerDef.image;
|
||||
Image = getActualImage;
|
||||
IP = containerDef.ip4;
|
||||
IP6 = containerDef.ip6;
|
||||
Label =
|
||||
|
@ -66,8 +113,8 @@ let
|
|||
TimeoutStopSec = 30;
|
||||
};
|
||||
Unit = {
|
||||
After = [ "network.target" ] ++ managedNetworks;
|
||||
Requires = managedNetworks;
|
||||
After = [ "network.target" ] ++ managedServices;
|
||||
Requires = managedServices;
|
||||
Description = (if (builtins.isString containerDef.description) then
|
||||
containerDef.description
|
||||
else
|
||||
|
|
|
@ -5,8 +5,15 @@ let
|
|||
in {
|
||||
meta.maintainers = with lib.hm.maintainers; [ bamhm182 n-hass ];
|
||||
|
||||
imports =
|
||||
[ ./containers.nix ./install-quadlet.nix ./networks.nix ./services.nix ];
|
||||
imports = [
|
||||
./builds.nix
|
||||
./containers.nix
|
||||
./images.nix
|
||||
./install-quadlet.nix
|
||||
./networks.nix
|
||||
./services.nix
|
||||
./volumes.nix
|
||||
];
|
||||
|
||||
options.services.podman = {
|
||||
enable = lib.mkEnableOption "Podman, a daemonless container engine";
|
||||
|
|
168
modules/services/podman-linux/images.nix
Normal file
168
modules/services/podman-linux/images.nix
Normal file
|
@ -0,0 +1,168 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.podman;
|
||||
|
||||
podman-lib = import ./podman-lib.nix { inherit lib config; };
|
||||
|
||||
awaitPodmanUnshare = pkgs.writeShellScript "await-podman-unshare" ''
|
||||
until ${cfg.package}/bin/podman unshare ${pkgs.coreutils}/bin/true; do
|
||||
${pkgs.coreutils}/bin/sleep 1
|
||||
done
|
||||
'';
|
||||
|
||||
createQuadletSource = name: imageDef:
|
||||
let
|
||||
credsString =
|
||||
(if imageDef.username != null then imageDef.username else "")
|
||||
+ (if imageDef.password != null then ":${imageDef.password}" else "");
|
||||
|
||||
imageConfig = podman-lib.deepMerge {
|
||||
Image = {
|
||||
AuthFile = imageDef.authFile;
|
||||
CertDir = imageDef.certDir;
|
||||
Creds = (if credsString != "" then credsString else null);
|
||||
DecryptionKey = imageDef.decryptionKeyFile;
|
||||
Image = imageDef.image;
|
||||
ImageTag = imageDef.tag;
|
||||
PodmanArgs = imageDef.extraPodmanArgs;
|
||||
TLSVerify = imageDef.tlsVerify;
|
||||
};
|
||||
Install = {
|
||||
WantedBy = optionals imageDef.autoStart [
|
||||
"default.target"
|
||||
"multi-user.target"
|
||||
];
|
||||
};
|
||||
Service = {
|
||||
ExecStartPre = [ "${awaitPodmanUnshare}" ];
|
||||
TimeoutStartSec = 300;
|
||||
RemainAfterExit = "yes";
|
||||
};
|
||||
Unit = { Description = imageDef.description; };
|
||||
} imageDef.extraConfig;
|
||||
in ''
|
||||
# Automatically generated by home-manager for podman image configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.image
|
||||
${podman-lib.toQuadletIni imageConfig}
|
||||
'';
|
||||
|
||||
toQuadletInternal = name: imageDef: {
|
||||
assertions = podman-lib.buildConfigAsserts name imageDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # quadlet service name: 'podman-<name>-image.service
|
||||
source = podman-lib.removeBlankLines (createQuadletSource name imageDef);
|
||||
resourceType = "image";
|
||||
};
|
||||
in let
|
||||
imageDefinitionType = types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description =
|
||||
"Whether to pull the image on boot. Requires user lingering.";
|
||||
};
|
||||
|
||||
authFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description =
|
||||
"Path of the authentication file used to connect to registry.";
|
||||
};
|
||||
|
||||
certDir = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description =
|
||||
"Path of certificates (*.{crt,cert,key}) used to connect to registry.";
|
||||
};
|
||||
|
||||
decryptionKeyFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = "Path to key used for decrpytion of images.";
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "Service for image ${name}";
|
||||
defaultText = "Service for image \${name}";
|
||||
example = "My Image";
|
||||
description = "The description of the image.";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = podman-lib.extraConfigType;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
Image = {
|
||||
ContainersConfModule = "/etc/nvd.conf";
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = "INI sections and values to populate the Image Quadlet.";
|
||||
};
|
||||
|
||||
extraPodmanArgs = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
example = [ "--os=linux" ];
|
||||
description =
|
||||
"Extra arguments to pass to the podman image pull command.";
|
||||
};
|
||||
|
||||
image = mkOption {
|
||||
type = types.str;
|
||||
example = "quay.io/centos/centos:latest";
|
||||
description = "Image to pull.";
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "P@ssw0rd";
|
||||
description =
|
||||
"Password used to connect to registry. (Will be visible in nix store)";
|
||||
};
|
||||
|
||||
tag = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "quay.io/centos/centos:latest";
|
||||
description =
|
||||
"FQIN of referenced Image when source is a file or directory archive.";
|
||||
};
|
||||
|
||||
tlsVerify = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description =
|
||||
"Require HTTPS and verification of certificates when contacting registries.";
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "bob";
|
||||
description = "Username used to connect to registry.";
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
in {
|
||||
options.services.podman.images = mkOption {
|
||||
type = types.attrsOf imageDefinitionType;
|
||||
default = { };
|
||||
description = "Defines Podman image quadlet configurations.";
|
||||
};
|
||||
|
||||
config = let imageQuadlets = mapAttrsToList toQuadletInternal cfg.images;
|
||||
in mkIf cfg.enable {
|
||||
services.podman.internal.quadletDefinitions = imageQuadlets;
|
||||
assertions = flatten (map (image: image.assertions) imageQuadlets);
|
||||
};
|
||||
}
|
|
@ -63,8 +63,10 @@ in {
|
|||
buildConfigAsserts = quadletName: extraConfig:
|
||||
let
|
||||
configRules = {
|
||||
Build = { ImageTag = (with types; listOf str); };
|
||||
Container = { ContainerName = types.enum [ quadletName ]; };
|
||||
Network = { NetworkName = types.enum [ quadletName ]; };
|
||||
Volume = { VolumeName = types.enum [ quadletName ]; };
|
||||
};
|
||||
|
||||
# Function to build assertions for a specific section and its attributes.
|
||||
|
@ -83,8 +85,23 @@ in {
|
|||
else
|
||||
[ ];
|
||||
|
||||
checkImageTag = extraConfig:
|
||||
let
|
||||
imageTags = (extraConfig.Build or { }).ImageTag or [ ];
|
||||
containsRequiredTag =
|
||||
builtins.elem "homemanager/${quadletName}" imageTags;
|
||||
imageTagsStr = concatMapStringsSep ''" "'' toString imageTags;
|
||||
in [{
|
||||
assertion = imageTags == [ ] || containsRequiredTag;
|
||||
message = ''
|
||||
In '${quadletName}' config. Build.ImageTag: '[ "${imageTagsStr}" ]' does not contain 'homemanager/${quadletName}'.'';
|
||||
}];
|
||||
|
||||
# Flatten assertions from all sections in `extraConfig`.
|
||||
in flatten (mapAttrsToList buildSectionAsserts extraConfig);
|
||||
in flatten (concatLists [
|
||||
(mapAttrsToList buildSectionAsserts extraConfig)
|
||||
(checkImageTag extraConfig)
|
||||
]);
|
||||
|
||||
extraConfigType = with types;
|
||||
attrsOf (attrsOf (oneOf [ primitiveAttrs primitiveList primitive ]));
|
||||
|
@ -107,8 +124,11 @@ in {
|
|||
# specific logic for writing the unit name goes here. It should be
|
||||
# identical to what `podman <resource> ls` shows
|
||||
in {
|
||||
"build" = strippedName;
|
||||
"container" = strippedName;
|
||||
"image" = strippedName;
|
||||
"network" = strippedName;
|
||||
"volume" = strippedName;
|
||||
}."${quadlet.resourceType}";
|
||||
in if allQuadletsSameType then ''
|
||||
${concatStringsSep "\n"
|
||||
|
|
|
@ -42,8 +42,8 @@ in {
|
|||
"${config.home.homeDirectory}/.nix-profile/bin"
|
||||
]
|
||||
}";
|
||||
ExecStart = "${pkgs.podman}/bin/podman auto-update";
|
||||
ExecStartPost = "${pkgs.podman}/bin/podman image prune -f";
|
||||
ExecStart = "${cfg.package}/bin/podman auto-update";
|
||||
ExecStartPost = "${cfg.package}/bin/podman image prune -f";
|
||||
TimeoutStartSec = "300s";
|
||||
TimeoutStopSec = "10s";
|
||||
};
|
||||
|
|
192
modules/services/podman-linux/volumes.nix
Normal file
192
modules/services/podman-linux/volumes.nix
Normal file
|
@ -0,0 +1,192 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.podman;
|
||||
|
||||
podman-lib = import ./podman-lib.nix { inherit lib config; };
|
||||
|
||||
awaitPodmanUnshare = pkgs.writeShellScript "await-podman-unshare" ''
|
||||
until ${cfg.package}/bin/podman unshare ${pkgs.coreutils}/bin/true; do
|
||||
${pkgs.coreutils}/bin/sleep 1
|
||||
done
|
||||
'';
|
||||
|
||||
createQuadletSource = name: volumeDef:
|
||||
let
|
||||
volumeConfig = podman-lib.deepMerge {
|
||||
Install = {
|
||||
WantedBy = optionals volumeDef.autoStart [
|
||||
"default.target"
|
||||
"multi-user.target"
|
||||
];
|
||||
};
|
||||
Service = {
|
||||
Environment = {
|
||||
PATH = (builtins.concatStringsSep ":" [
|
||||
"${podman-lib.newuidmapPaths}"
|
||||
"${makeBinPath [ pkgs.su pkgs.coreutils ]}"
|
||||
]);
|
||||
};
|
||||
ExecStartPre = [ "${awaitPodmanUnshare}" ];
|
||||
TimeoutStartSec = 15;
|
||||
RemainAfterExit = "yes";
|
||||
};
|
||||
Unit = { Description = volumeDef.description; };
|
||||
Volume = {
|
||||
Copy = volumeDef.copy;
|
||||
Device = volumeDef.device;
|
||||
Driver = volumeDef.driver;
|
||||
Group = volumeDef.group;
|
||||
Image = volumeDef.image;
|
||||
Label = volumeDef.labels // {
|
||||
"nix.home-manager.managed" = true;
|
||||
"nix.home-manager.preserve" = volumeDef.preserve;
|
||||
};
|
||||
PodmanArgs = volumeDef.extraPodmanArgs;
|
||||
Type = volumeDef.type;
|
||||
User = volumeDef.user;
|
||||
VolumeName = name;
|
||||
};
|
||||
} volumeDef.extraConfig;
|
||||
in ''
|
||||
# Automatically generated by home-manager for podman volume configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# ${name}.volume
|
||||
${podman-lib.toQuadletIni volumeConfig}
|
||||
'';
|
||||
|
||||
toQuadletInternal = name: volumeDef: {
|
||||
assertions = podman-lib.buildConfigAsserts name volumeDef.extraConfig;
|
||||
serviceName =
|
||||
"podman-${name}"; # quadlet service name: 'podman-<name>-volume.service'
|
||||
source = podman-lib.removeBlankLines (createQuadletSource name volumeDef);
|
||||
resourceType = "volume";
|
||||
};
|
||||
|
||||
in let
|
||||
volumeDefinitionType = types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to create the volume on boot.";
|
||||
};
|
||||
|
||||
copy = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description =
|
||||
"Copy content of the image located at the mountpoint of the volume on first run.";
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "Service for volume ${name}";
|
||||
defaultText = "Service for volume \${name}";
|
||||
example = "My Volume";
|
||||
description = "The description of the volume.";
|
||||
};
|
||||
|
||||
device = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "tmpfs";
|
||||
description = "The path of a device which is mounted for the volume.";
|
||||
};
|
||||
|
||||
driver = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "image";
|
||||
description = "The volume driver to use.";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = podman-lib.extraConfigType;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
Volume = {
|
||||
ContainerConfModule = "/etc/nvd.conf";
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = "INI sections and values to populate the Volume Quadlet.";
|
||||
};
|
||||
|
||||
extraPodmanArgs = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
example = [ "--opt copy" ];
|
||||
description =
|
||||
"Extra arguments to pass to the podman volume create command.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = with types; nullOr (either int str);
|
||||
default = null;
|
||||
description = "The group ID owning the volume inside the container.";
|
||||
};
|
||||
|
||||
image = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "quay.io/centos/centos:latest";
|
||||
description =
|
||||
"Specifies the image the volume is based on when Driver is set to the image.";
|
||||
};
|
||||
|
||||
labels = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = { };
|
||||
example = {
|
||||
app = "myapp";
|
||||
some-label = "somelabel";
|
||||
};
|
||||
description = "The labels to apply to the volume.";
|
||||
};
|
||||
|
||||
preserve = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether the volume should be preserved if it is removed from the configuration.
|
||||
Setting this to false will cause the volume to be deleted if the volume is removed from the configuration
|
||||
'';
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "tmpfs";
|
||||
description =
|
||||
"Filesystem type of Device. (used as -t in mount commands)";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = with types; nullOr (either int str);
|
||||
default = null;
|
||||
description = "The user ID owning the volume inside the container.";
|
||||
};
|
||||
};
|
||||
});
|
||||
in {
|
||||
options.services.podman.volumes = mkOption {
|
||||
type = types.attrsOf volumeDefinitionType;
|
||||
default = { };
|
||||
description = "Defines Podman volume quadlet configurations.";
|
||||
};
|
||||
|
||||
config = let volumeQuadlets = mapAttrsToList toQuadletInternal cfg.volumes;
|
||||
in mkIf cfg.enable {
|
||||
services.podman.internal.quadletDefinitions = volumeQuadlets;
|
||||
assertions = flatten (map (volume: volume.assertions) volumeQuadlets);
|
||||
|
||||
xdg.configFile."/podman/volumes.manifest".text =
|
||||
podman-lib.generateManifestText volumeQuadlets;
|
||||
};
|
||||
}
|
30
tests/modules/services/podman-linux/build-expected.service
Normal file
30
tests/modules/services/podman-linux/build-expected.service
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager for podman build configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-bld.build
|
||||
[X-Build]
|
||||
Environment=
|
||||
File=/nix/store/00000000000000000000000000000000-Containerfile
|
||||
ImageTag=homemanager/my-bld
|
||||
Label=nix.home-manager.managed=true
|
||||
TLSVerify=true
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
RemainAfterExit=yes
|
||||
TimeoutStartSec=300
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman build --tls-verify --tag homemanager/my-bld --label nix.home-manager.managed=true --file /nix/store/00000000000000000000000000000000-Containerfile
|
||||
SyslogIdentifier=%N
|
||||
Type=oneshot
|
||||
|
||||
[Unit]
|
||||
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
|
40
tests/modules/services/podman-linux/build.nix
Normal file
40
tests/modules/services/podman-linux/build.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
containerFile = pkgs.writeTextFile {
|
||||
name = "Containerfile";
|
||||
text = ''
|
||||
FROM docker.io/alpine:latest
|
||||
'';
|
||||
};
|
||||
|
||||
in {
|
||||
services.podman = {
|
||||
enable = true;
|
||||
builds = {
|
||||
"my-bld" = { file = "${containerFile}"; };
|
||||
|
||||
"my-bld-2" = {
|
||||
file = "https://www.github.com/././Containerfile";
|
||||
extraConfig = {
|
||||
Build.ImageTag = [ "locahost/somethingelse" "localhost/anothertag" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test.asserts.assertions.expected = [
|
||||
''
|
||||
In 'my-bld-2' config. Build.ImageTag: '[ "locahost/somethingelse" "localhost/anothertag" ]' does not contain 'homemanager/my-bld-2'.''
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
configPath=home-files/.config/systemd/user
|
||||
buildFile=$configPath/podman-my-bld-build.service
|
||||
|
||||
assertFileExists $buildFile
|
||||
|
||||
buildFile=$(normalizeStorePaths $buildFile)
|
||||
|
||||
assertFileContent $buildFile ${./build-expected.service}
|
||||
'';
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
{
|
||||
podman-configuration = ./configuration.nix;
|
||||
podman-container = ./container.nix;
|
||||
podman-build = ./build.nix;
|
||||
podman-image = ./image.nix;
|
||||
podman-integration = ./integration.nix;
|
||||
podman-manifest = ./manifest.nix;
|
||||
podman-network = ./network.nix;
|
||||
podman-volume = ./volume.nix;
|
||||
}
|
||||
|
|
28
tests/modules/services/podman-linux/image-expected.service
Normal file
28
tests/modules/services/podman-linux/image-expected.service
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager for podman image configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-img.image
|
||||
[X-Image]
|
||||
Image=docker.io/alpine:latest
|
||||
TLSVerify=true
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/nix/store/00000000000000000000000000000000-await-podman-unshare
|
||||
RemainAfterExit=yes
|
||||
TimeoutStartSec=300
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman image pull --tls-verify docker.io/alpine:latest
|
||||
SyslogIdentifier=%N
|
||||
Type=oneshot
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
Description=Service for image my-img
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-image-podman-my-img/quadlets/podman-my-img.image
|
||||
RequiresMountsFor=%t/containers
|
18
tests/modules/services/podman-linux/image.nix
Normal file
18
tests/modules/services/podman-linux/image.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
services.podman = {
|
||||
enable = true;
|
||||
images = { "my-img" = { image = "docker.io/alpine:latest"; }; };
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
configPath=home-files/.config/systemd/user
|
||||
imageFile=$configPath/podman-my-img-image.service
|
||||
assertFileExists $imageFile
|
||||
|
||||
imageFile=$(normalizeStorePaths $imageFile)
|
||||
|
||||
assertFileContent $imageFile ${./image-expected.service}
|
||||
'';
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager for podman build configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-bld.build
|
||||
[X-Build]
|
||||
Environment=
|
||||
File=/nix/store/00000000000000000000000000000000-Containerfile
|
||||
ImageTag=homemanager/my-bld
|
||||
Label=nix.home-manager.managed=true
|
||||
TLSVerify=true
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
RemainAfterExit=yes
|
||||
TimeoutStartSec=300
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman build --tls-verify --tag homemanager/my-bld --label nix.home-manager.managed=true --file /nix/store/00000000000000000000000000000000-Containerfile
|
||||
SyslogIdentifier=%N
|
||||
Type=oneshot
|
||||
|
||||
[Unit]
|
||||
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
|
|
@ -0,0 +1,39 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager podman container configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-container-bld.container
|
||||
[X-Container]
|
||||
ContainerName=my-container-bld
|
||||
Environment=
|
||||
Image=localhost/homemanager/my-bld
|
||||
Label=nix.home-manager.managed=true
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:/home/hm-user/.nix-profile/bin
|
||||
Restart=always
|
||||
TimeoutStopSec=30
|
||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
||||
KillMode=mixed
|
||||
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
|
||||
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
|
||||
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
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
After=network.target
|
||||
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
|
||||
RequiresMountsFor=%t/containers
|
|
@ -11,6 +11,7 @@ Image=docker.io/alpine:latest
|
|||
Label=nix.home-manager.managed=true
|
||||
Network=my-net
|
||||
Network=externalnet
|
||||
Volume=my-vol:/data
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
@ -28,14 +29,18 @@ Delegate=yes
|
|||
Type=notify
|
||||
NotifyAccess=all
|
||||
SyslogIdentifier=%N
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container --cidfile=%t/%N.cid --replace --rm --cgroups=split --network my-net --network externalnet --sdnotify=conmon -d --label nix.home-manager.managed=true docker.io/alpine:latest
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container --cidfile=%t/%N.cid --replace --rm --cgroups=split --network my-net --network externalnet --sdnotify=conmon -d -v my-vol:/data --label nix.home-manager.managed=true docker.io/alpine:latest
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
After=network.target
|
||||
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
|
||||
RequiresMountsFor=%t/containers
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager for podman image configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-img.image
|
||||
[X-Image]
|
||||
Image=docker.io/alpine:latest
|
||||
TLSVerify=true
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/nix/store/00000000000000000000000000000000-await-podman-unshare
|
||||
RemainAfterExit=yes
|
||||
TimeoutStartSec=300
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman image pull --tls-verify docker.io/alpine:latest
|
||||
SyslogIdentifier=%N
|
||||
Type=oneshot
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
Description=Service for image my-img
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-image-podman-my-img/quadlets/podman-my-img.image
|
||||
RequiresMountsFor=%t/containers
|
|
@ -0,0 +1,33 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager for podman volume configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-vol.volume
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
Environment=PATH=/run/wrappers/bin:/usr/bin:/bin:/usr/sbin:/sbin:/nix/store/00000000000000000000000000000000-shadow/bin:/nix/store/00000000000000000000000000000000-coreutils/bin
|
||||
ExecStartPre=/nix/store/00000000000000000000000000000000-await-podman-unshare
|
||||
RemainAfterExit=yes
|
||||
TimeoutStartSec=15
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman volume create --ignore --opt copy --opt device=tmpfs --opt type=tmpfs --label nix.home-manager.managed=true --label nix.home-manager.preserve=false my-vol
|
||||
SyslogIdentifier=%N
|
||||
Type=oneshot
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
Description=Service for volume my-vol
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-volume-podman-my-vol/quadlets/podman-my-vol.volume
|
||||
RequiresMountsFor=%t/containers
|
||||
|
||||
[X-Volume]
|
||||
Copy=true
|
||||
Device=tmpfs
|
||||
Label=nix.home-manager.managed=true
|
||||
Label=nix.home-manager.preserve=false
|
||||
Type=tmpfs
|
||||
VolumeName=my-vol
|
|
@ -1,29 +1,64 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
containerFile = pkgs.writeTextFile {
|
||||
name = "Containerfile";
|
||||
text = ''
|
||||
FROM docker.io/alpine:latest
|
||||
'';
|
||||
};
|
||||
in {
|
||||
services.podman = {
|
||||
enable = true;
|
||||
containers."my-container" = {
|
||||
image = "docker.io/alpine:latest";
|
||||
network = [ "my-net" "externalnet" ];
|
||||
builds."my-bld" = { file = "${containerFile}"; };
|
||||
containers = {
|
||||
"my-container" = {
|
||||
image = "my-img";
|
||||
network = [ "my-net" "externalnet" ];
|
||||
volumes = [ "my-vol:/data" ];
|
||||
};
|
||||
"my-container-bld" = { image = "my-bld"; };
|
||||
};
|
||||
images."my-img" = { image = "docker.io/alpine:latest"; };
|
||||
networks."my-net" = {
|
||||
gateway = "192.168.123.1";
|
||||
subnet = "192.168.123.0/24";
|
||||
};
|
||||
volumes."my-vol" = {
|
||||
device = "tmpfs";
|
||||
preserve = false;
|
||||
type = "tmpfs";
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
configPath=home-files/.config/systemd/user
|
||||
buildFile=$configPath/podman-my-bld-build.service
|
||||
containerFile=$configPath/podman-my-container.service
|
||||
containerBldFile=$configPath/podman-my-container-bld.service
|
||||
imageFile=$configPath/podman-my-img-image.service
|
||||
networkFile=$configPath/podman-my-net-network.service
|
||||
volumeFile=$configPath/podman-my-vol-volume.service
|
||||
assertFileExists $buildFile
|
||||
assertFileExists $containerFile
|
||||
assertFileExists $containerBldFile
|
||||
assertFileExists $imageFile
|
||||
assertFileExists $networkFile
|
||||
assertFileExists $volumeFile
|
||||
|
||||
buildFile=$(normalizeStorePaths $buildFile)
|
||||
containerFile=$(normalizeStorePaths $containerFile)
|
||||
containerBldFile=$(normalizeStorePaths $containerBldFile)
|
||||
imageFile=$(normalizeStorePaths $imageFile)
|
||||
networkFile=$(normalizeStorePaths $networkFile)
|
||||
volumeFile=$(normalizeStorePaths $volumeFile)
|
||||
|
||||
assertFileContent $buildFile ${./integration-build-expected.service}
|
||||
assertFileContent $containerFile ${./integration-container-expected.service}
|
||||
assertFileContent $containerBldFile ${
|
||||
./integration-container-bld-expected.service
|
||||
}
|
||||
assertFileContent $imageFile ${./integration-image-expected.service}
|
||||
assertFileContent $networkFile ${./integration-network-expected.service}
|
||||
assertFileContent $volumeFile ${./integration-volume-expected.service}
|
||||
'';
|
||||
}
|
||||
|
|
36
tests/modules/services/podman-linux/volume-expected.service
Normal file
36
tests/modules/services/podman-linux/volume-expected.service
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Automatically generated by /nix/store/00000000000000000000000000000000-podman/lib/systemd/user-generators/podman-user-generator
|
||||
#
|
||||
# Automatically generated by home-manager for podman volume configuration
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
#
|
||||
# my-vol.volume
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
Environment=PATH=/run/wrappers/bin:/usr/bin:/bin:/usr/sbin:/sbin:/nix/store/00000000000000000000000000000000-shadow/bin:/nix/store/00000000000000000000000000000000-coreutils/bin
|
||||
ExecStartPre=/nix/store/00000000000000000000000000000000-await-podman-unshare
|
||||
RemainAfterExit=yes
|
||||
TimeoutStartSec=15
|
||||
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman volume create --ignore --opt copy --opt device=tmpfs --opt type=tmpfs --opt o=uid=1000,gid=1000 --label nix.home-manager.managed=true --label nix.home-manager.preserve=true --module=/etc/nvd.conf my-vol
|
||||
SyslogIdentifier=%N
|
||||
Type=oneshot
|
||||
|
||||
[Unit]
|
||||
Wants=podman-user-wait-network-online.service
|
||||
After=podman-user-wait-network-online.service
|
||||
Description=Service for volume my-vol
|
||||
SourcePath=/nix/store/00000000000000000000000000000000-home-volume-podman-my-vol/quadlets/podman-my-vol.volume
|
||||
RequiresMountsFor=%t/containers
|
||||
|
||||
[X-Volume]
|
||||
Copy=true
|
||||
Device=tmpfs
|
||||
Group=1000
|
||||
Label=nix.home-manager.managed=true
|
||||
Label=nix.home-manager.preserve=true
|
||||
PodmanArgs=--module=/etc/nvd.conf
|
||||
Type=tmpfs
|
||||
User=1000
|
||||
VolumeName=my-vol
|
35
tests/modules/services/podman-linux/volume.nix
Normal file
35
tests/modules/services/podman-linux/volume.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
services.podman = {
|
||||
enable = true;
|
||||
volumes = {
|
||||
"my-vol" = {
|
||||
device = "tmpfs";
|
||||
extraConfig = { Volume = { User = 1000; }; };
|
||||
extraPodmanArgs = [ "--module=/etc/nvd.conf" ];
|
||||
group = 1000;
|
||||
type = "tmpfs";
|
||||
};
|
||||
|
||||
"my-vol-2" = {
|
||||
extraConfig = { Volume = { VolumeName = "some-other-volume-name"; }; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test.asserts.assertions.expected = [
|
||||
''
|
||||
In 'my-vol-2' config. Volume.VolumeName: 'some-other-volume-name' does not match expected type: value "my-vol-2" (singular enum)''
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
configPath=home-files/.config/systemd/user
|
||||
volumeFile=$configPath/podman-my-vol-volume.service
|
||||
assertFileExists $volumeFile
|
||||
|
||||
volumeFile=$(normalizeStorePaths $volumeFile)
|
||||
|
||||
assertFileContent $volumeFile ${./volume-expected.service}
|
||||
'';
|
||||
}
|
Loading…
Add table
Reference in a new issue