diff --git a/.fixtures.yml b/.fixtures.yml index 93ec5df..8623ad7 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -3,6 +3,7 @@ --- fixtures: forge_modules: + systemd: "puppet/systemd" stdlib: "puppetlabs/stdlib" concat: "puppetlabs/concat" selinux_core: "puppetlabs/selinux_core" diff --git a/README.md b/README.md index d778ea8..4f53e0c 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,36 @@ Several additional examples are in a separate [github project](https://github.co a Traefik container configuration that enables SSL termination and proxy access to other containers running on the host, with a dynamic configuration directory enabling updates to proxy rules as new containers are added and/or removed. +## Creating Containers,Volumes, Pods, ... with Quadlet Unit Files + +Container unit files can be created and managed, for example: + +```puppet +podman::quadlet{'centos.container': + ensure => present, + unit_entry => { + 'Description' => 'Trivial Container that will be very lazy', + }, + service_entry => { + 'TimeoutStartSec' => '900', + }, + container_entry => { + 'Image' => 'quay.io/centos/centos:latest', + 'Exec' => 'sh -c "sleep inf' + }, + install_entry => { + 'WantedBy' => 'default.target' + }, + active => true, +} + +``` + +Will create a service `centos.service` that is then started and enabled for boot. + +Similarly quadlets for volumes, pods, ... can be created in a similar manner + + ## Limitations The module was written and tested with RedHat/CentOS, but should work with any distribution that uses systemd and includes diff --git a/REFERENCE.md b/REFERENCE.md index c0acda8..4051358 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -18,15 +18,23 @@ ### Defined types -* [`podman::container`](#podmancontainer): manage podman container and register as a systemd service -* [`podman::image`](#podmanimage): pull or remove container images -* [`podman::network`](#podmannetwork): Create a podman network with defined flags -* [`podman::pod`](#podmanpod): Create a podman pod with defined flags -* [`podman::rootless`](#podmanrootless): Enable a given user to run rootless podman containers as a systemd user service. -* [`podman::secret`](#podmansecret): Manage a podman secret. Create and remove secrets, it cannot replace. -* [`podman::subgid`](#podmansubgid): Define an entry in the `/etc/subgid` file. -* [`podman::subuid`](#podmansubuid): Manage entries in `/etc/subuid` -* [`podman::volume`](#podmanvolume): Create a podman volume with defined flags +* [`podman::container`](#podman--container): manage podman container and register as a systemd service +* [`podman::image`](#podman--image): pull or remove container images +* [`podman::network`](#podman--network): Create a podman network with defined flags +* [`podman::pod`](#podman--pod): Create a podman pod with defined flags +* [`podman::quadlet`](#podman--quadlet): Generate and manage podman quadlet definitions (podman > 4.4.0) +* [`podman::rootless`](#podman--rootless): Enable a given user to run rootless podman containers as a systemd user service. +* [`podman::secret`](#podman--secret): Manage a podman secret. Create and remove secrets, it cannot replace. +* [`podman::subgid`](#podman--subgid): Define an entry in the `/etc/subgid` file. +* [`podman::subuid`](#podman--subuid): Manage entries in `/etc/subuid` +* [`podman::volume`](#podman--volume): Create a podman volume with defined flags + +### Data types + +* [`Podman::Quadlet_name`](#Podman--Quadlet_name): custom datatype that validates different filenames for quadlet units +* [`Podman::Unit::Container`](#Podman--Unit--Container): custom datatype for container entries of podman container quadlet +* [`Podman::Unit::Pod`](#Podman--Unit--Pod): custom datatype for Volume entries of podman container quadlet +* [`Podman::Unit::Volume`](#Podman--Unit--Volume): custom datatype for Volume entries of podman container quadlet ## Classes @@ -73,31 +81,31 @@ podman::containers: The following parameters are available in the `podman` class: -* [`podman_pkg`](#podman_pkg) -* [`skopeo_pkg`](#skopeo_pkg) -* [`buildah_pkg`](#buildah_pkg) -* [`podman_docker_pkg`](#podman_docker_pkg) -* [`compose_pkg`](#compose_pkg) -* [`machinectl_pkg`](#machinectl_pkg) -* [`buildah_pkg_ensure`](#buildah_pkg_ensure) -* [`podman_docker_pkg_ensure`](#podman_docker_pkg_ensure) -* [`compose_pkg_ensure`](#compose_pkg_ensure) -* [`machinectl_pkg_ensure`](#machinectl_pkg_ensure) -* [`nodocker`](#nodocker) -* [`storage_options`](#storage_options) -* [`rootless_users`](#rootless_users) -* [`enable_api_socket`](#enable_api_socket) -* [`manage_subuid`](#manage_subuid) -* [`file_header`](#file_header) -* [`match_subuid_subgid`](#match_subuid_subgid) -* [`subid`](#subid) -* [`pods`](#pods) -* [`volumes`](#volumes) -* [`images`](#images) -* [`containers`](#containers) -* [`networks`](#networks) - -##### `podman_pkg` +* [`podman_pkg`](#-podman--podman_pkg) +* [`skopeo_pkg`](#-podman--skopeo_pkg) +* [`buildah_pkg`](#-podman--buildah_pkg) +* [`podman_docker_pkg`](#-podman--podman_docker_pkg) +* [`compose_pkg`](#-podman--compose_pkg) +* [`machinectl_pkg`](#-podman--machinectl_pkg) +* [`buildah_pkg_ensure`](#-podman--buildah_pkg_ensure) +* [`podman_docker_pkg_ensure`](#-podman--podman_docker_pkg_ensure) +* [`compose_pkg_ensure`](#-podman--compose_pkg_ensure) +* [`machinectl_pkg_ensure`](#-podman--machinectl_pkg_ensure) +* [`nodocker`](#-podman--nodocker) +* [`storage_options`](#-podman--storage_options) +* [`rootless_users`](#-podman--rootless_users) +* [`enable_api_socket`](#-podman--enable_api_socket) +* [`manage_subuid`](#-podman--manage_subuid) +* [`file_header`](#-podman--file_header) +* [`match_subuid_subgid`](#-podman--match_subuid_subgid) +* [`subid`](#-podman--subid) +* [`pods`](#-podman--pods) +* [`volumes`](#-podman--volumes) +* [`images`](#-podman--images) +* [`containers`](#-podman--containers) +* [`networks`](#-podman--networks) + +##### `podman_pkg` Data type: `String` @@ -105,7 +113,7 @@ The name of the podman package (default 'podman') Default value: `'podman'` -##### `skopeo_pkg` +##### `skopeo_pkg` Data type: `String` @@ -113,7 +121,7 @@ The name of the skopeo package (default 'skopeo') Default value: `'skopeo'` -##### `buildah_pkg` +##### `buildah_pkg` Data type: `String` @@ -121,7 +129,7 @@ The name of the buildah package (default 'buildah') Default value: `'buildah'` -##### `podman_docker_pkg` +##### `podman_docker_pkg` Data type: `String` @@ -129,7 +137,7 @@ The name of the podman-docker package (default 'podman-docker'). Default value: `'podman-docker'` -##### `compose_pkg` +##### `compose_pkg` Data type: `String` @@ -137,7 +145,7 @@ The name of the podman-compose package (default 'podman-compose'). Default value: `'podman-compose'` -##### `machinectl_pkg` +##### `machinectl_pkg` Data type: `String` @@ -145,7 +153,7 @@ The name of the machinectl package (default 'systemd-container'). Default value: `'systemd-container'` -##### `buildah_pkg_ensure` +##### `buildah_pkg_ensure` Data type: `Enum['absent', 'installed']` @@ -153,7 +161,7 @@ The ensure value for the buildah package (default 'absent') Default value: `'absent'` -##### `podman_docker_pkg_ensure` +##### `podman_docker_pkg_ensure` Data type: `Enum['absent', 'installed']` @@ -161,7 +169,7 @@ The ensure value for the podman docker package (default 'installed') Default value: `'installed'` -##### `compose_pkg_ensure` +##### `compose_pkg_ensure` Data type: `Enum['absent', 'installed']` @@ -169,7 +177,7 @@ The ensure value for the podman-compose package (default 'absent') Default value: `'absent'` -##### `machinectl_pkg_ensure` +##### `machinectl_pkg_ensure` Data type: `Enum['absent', 'installed']` @@ -177,7 +185,7 @@ The ensure value for the machinectl package (default 'installed') Default value: `'installed'` -##### `nodocker` +##### `nodocker` Data type: `Enum['absent', 'file']` @@ -186,7 +194,7 @@ Values should be either 'file' or 'absent'. (default is 'absent') Default value: `'absent'` -##### `storage_options` +##### `storage_options` Data type: `Hash` @@ -194,7 +202,7 @@ A hash containing any storage options you wish to set in /etc/containers/storage Default value: `{}` -##### `rootless_users` +##### `rootless_users` Data type: `Array` @@ -202,15 +210,15 @@ An array of users to manage using [`podman::rootless`](#podmanrootless) Default value: `[]` -##### `enable_api_socket` +##### `enable_api_socket` Data type: `Boolean` The enable value of the API socket (default `false`) -Default value: ``false`` +Default value: `false` -##### `manage_subuid` +##### `manage_subuid` Data type: `Boolean` @@ -219,9 +227,9 @@ The implementation uses [concat](https://forge.puppet.com/puppetlabs/concat) fra out the subuid/subgid entries. If you have a large number of entries you may want to manage them with another method. You cannot use the `subuid` and `subgid` defined types unless this is `true`. -Default value: ``false`` +Default value: `false` -##### `file_header` +##### `file_header` Data type: `String` @@ -230,7 +238,7 @@ Default file_header is `# FILE MANAGED BY PUPPET` Default value: `'# FILE MANAGED BY PUPPET'` -##### `match_subuid_subgid` +##### `match_subuid_subgid` Data type: `Boolean` @@ -238,9 +246,9 @@ Enable the `subid` parameter to manage both subuid and subgid entries with the s This setting requires `manage_subuid` to be `true` or it will have no effect. (default is true) -Default value: ``true`` +Default value: `true` -##### `subid` +##### `subid` Data type: `Hash` @@ -250,7 +258,7 @@ Hash key `subuid` is the subordinate UID, and `count` is the number of subordina Default value: `{}` -##### `pods` +##### `pods` Data type: `Hash` @@ -258,7 +266,7 @@ A hash of pods to manage using [`podman::pod`](#podmanpod) Default value: `{}` -##### `volumes` +##### `volumes` Data type: `Hash` @@ -266,7 +274,7 @@ A hash of volumes to manage using [`podman::volume`](#podmanvolume) Default value: `{}` -##### `images` +##### `images` Data type: `Hash` @@ -274,7 +282,7 @@ A hash of images to manage using [`podman::image`](#podmanimage) Default value: `{}` -##### `containers` +##### `containers` Data type: `Hash` @@ -282,7 +290,7 @@ A hash of containers to manage using [`podman::container`](#podmancontainer) Default value: `{}` -##### `networks` +##### `networks` Data type: `Hash` @@ -292,7 +300,7 @@ Default value: `{}` ## Defined types -### `podman::container` +### `podman::container` manage podman container and register as a systemd service @@ -319,36 +327,36 @@ podman::container { 'jenkins': The following parameters are available in the `podman::container` defined type: -* [`image`](#image) -* [`user`](#user) -* [`flags`](#flags) -* [`service_flags`](#service_flags) -* [`command`](#command) -* [`ensure`](#ensure) -* [`enable`](#enable) -* [`update`](#update) -* [`ruby`](#ruby) +* [`image`](#-podman--container--image) +* [`user`](#-podman--container--user) +* [`flags`](#-podman--container--flags) +* [`service_flags`](#-podman--container--service_flags) +* [`command`](#-podman--container--command) +* [`ensure`](#-podman--container--ensure) +* [`enable`](#-podman--container--enable) +* [`update`](#-podman--container--update) +* [`ruby`](#-podman--container--ruby) -##### `image` +##### `image` -Data type: `String` +Data type: `Optional[String]` Container registry source of the image being deployed. Required when `ensure` is `present` but optional when `ensure` is set to `absent`. -Default value: `''` +Default value: `undef` -##### `user` +##### `user` -Data type: `String` +Data type: `Optional[String]` Optional user for running rootless containers. For rootless containers, the user must also be defined as a puppet resource that includes at least 'uid', 'gid', and 'home' attributes. -Default value: `''` +Default value: `undef` -##### `flags` +##### `flags` Data type: `Hash` @@ -366,43 +374,43 @@ YAML representation you can use `~` or `null` as the value. Default value: `{}` -##### `service_flags` +##### `service_flags` Data type: `Hash` When a container is created, a systemd unit file for the container service is generated using the 'podman generate systemd' command. All flags for the -command are supported using the 'service_flags" hash parameter, again using +command are supported using the 'service_flags' hash parameter, again using only the long form of the flag names. Default value: `{}` -##### `command` +##### `command` -Data type: `String` +Data type: `Optional[String]` Optional command to be used as the container entry point. -Default value: `''` +Default value: `undef` -##### `ensure` +##### `ensure` -Data type: `String` +Data type: `Enum['present', 'absent']` Valid values are 'present' or 'absent' Default value: `'present'` -##### `enable` +##### `enable` Data type: `Boolean` Status of the automatically generated systemd service for the container. Valid values are 'running' or 'stopped'. -Default value: ``true`` +Default value: `true` -##### `update` +##### `update` Data type: `Boolean` @@ -412,19 +420,19 @@ value of the running container image with the digest of the registry image. When `false`, the container will only be redeployed when the declared state of the puppet resource is changed. -Default value: ``true`` +Default value: `true` -##### `ruby` +##### `ruby` -Data type: `Stdlib::Unixpath` +Data type: `Optional[Stdlib::Unixpath]` The absolute path to the ruby binary to use in scripts. The default path is '/opt/puppetlabs/puppet/bin/ruby' for Puppetlabs packaged puppet, and '/usr/bin/ruby' for all others. -Default value: `$facts['ruby']['sitedir']` +Default value: `undef` -### `podman::image` +### `podman::image` pull or remove container images @@ -445,28 +453,28 @@ podman::image { 'my_container': The following parameters are available in the `podman::image` defined type: -* [`image`](#image) -* [`ensure`](#ensure) -* [`flags`](#flags) -* [`user`](#user) -* [`exec_env`](#exec_env) +* [`image`](#-podman--image--image) +* [`ensure`](#-podman--image--ensure) +* [`flags`](#-podman--image--flags) +* [`user`](#-podman--image--user) +* [`exec_env`](#-podman--image--exec_env) -##### `image` +##### `image` Data type: `String` The name of the container image to pull, which should be present in a configured container registry. -##### `ensure` +##### `ensure` -Data type: `String` +Data type: `Enum['present', 'absent']` State of the resource must be either `present` or `absent`. Default value: `'present'` -##### `flags` +##### `flags` Data type: `Hash` @@ -475,17 +483,17 @@ long form of the flag name. Default value: `{}` -##### `user` +##### `user` -Data type: `String` +Data type: `Optional[String]` Optional user for running rootless containers. When using this parameter, the user must also be defined as a Puppet resource and must include the 'uid', 'gid', and 'home' -Default value: `''` +Default value: `undef` -##### `exec_env` +##### `exec_env` Data type: `Array` @@ -495,7 +503,7 @@ pulled. Useful for defining a proxy for downloads. For example: Default value: `[]` -### `podman::network` +### `podman::network` Create a podman network with defined flags @@ -514,19 +522,19 @@ podman::network { 'mnetwork': The following parameters are available in the `podman::network` defined type: -* [`ensure`](#ensure) -* [`disable_dns`](#disable_dns) -* [`driver`](#driver) -* [`opts`](#opts) -* [`gateway`](#gateway) -* [`internal`](#internal) -* [`ip_range`](#ip_range) -* [`labels`](#labels) -* [`subnet`](#subnet) -* [`ipv6`](#ipv6) -* [`user`](#user) +* [`ensure`](#-podman--network--ensure) +* [`disable_dns`](#-podman--network--disable_dns) +* [`driver`](#-podman--network--driver) +* [`opts`](#-podman--network--opts) +* [`gateway`](#-podman--network--gateway) +* [`internal`](#-podman--network--internal) +* [`ip_range`](#-podman--network--ip_range) +* [`labels`](#-podman--network--labels) +* [`subnet`](#-podman--network--subnet) +* [`ipv6`](#-podman--network--ipv6) +* [`user`](#-podman--network--user) -##### `ensure` +##### `ensure` Data type: `Enum['present', 'absent']` @@ -534,16 +542,16 @@ State of the resource must be either 'present' or 'absent'. Default value: `'present'` -##### `disable_dns` +##### `disable_dns` Data type: `Boolean` Disables the DNS plugin for this network which if enabled, can perform container to container name resolution. -Default value: ``false`` +Default value: `false` -##### `driver` +##### `driver` Data type: `Enum['bridge', 'macvlan']` @@ -551,7 +559,7 @@ Driver to manage the network. Default value: `'bridge'` -##### `opts` +##### `opts` Data type: `Array[String]` @@ -559,32 +567,32 @@ A list of driver specific options. Default value: `[]` -##### `gateway` +##### `gateway` Data type: `Optional[String]` Define the gateway for the network. Must also provide the subnet. -Default value: ``undef`` +Default value: `undef` -##### `internal` +##### `internal` Data type: `Boolean` Restrict external access of this network. -Default value: ``false`` +Default value: `false` -##### `ip_range` +##### `ip_range` Data type: `Optional[String]` Allocate container IP from a range. The range must be a complete subnet and in CIDR notation. -Default value: ``undef`` +Default value: `undef` -##### `labels` +##### `labels` Data type: `Hash[String,String]` @@ -592,33 +600,33 @@ A hash of metadata labels to set on the network. Default value: `{}` -##### `subnet` +##### `subnet` Data type: `Optional[String]` The subnet in CIDR notation -Default value: ``undef`` +Default value: `undef` -##### `ipv6` +##### `ipv6` Data type: `Boolean` Enable IPv6 (dual-stack) networking. -Default value: ``false`` +Default value: `false` -##### `user` +##### `user` -Data type: `String` +Data type: `Optional[String]` Optional user for creating rootless container networks. For rootless containers, the user must also be defined as a puppet resource that includes at least 'uid', 'gid', and 'home' attributes. -Default value: `''` +Default value: `undef` -### `podman::pod` +### `podman::pod` Create a podman pod with defined flags @@ -638,19 +646,19 @@ podman::pod { 'mypod': The following parameters are available in the `podman::pod` defined type: -* [`ensure`](#ensure) -* [`flags`](#flags) -* [`user`](#user) +* [`ensure`](#-podman--pod--ensure) +* [`flags`](#-podman--pod--flags) +* [`user`](#-podman--pod--user) -##### `ensure` +##### `ensure` -Data type: `String` +Data type: `Enum['present', 'absent']` State of the resource, which must be either 'present' or 'absent'. Default value: `'present'` -##### `flags` +##### `flags` Data type: `Hash` @@ -660,21 +668,157 @@ pod name unless the 'name' flag is included in the hash of flags. Default value: `{}` -##### `user` +##### `user` -Data type: `String` +Data type: `Optional[String]` Optional user for running rootless containers. When using this parameter, the user must also be defined as a Puppet resource and must include the 'uid', 'gid', and 'home' -Default value: `''` +Default value: `undef` + +### `podman::quadlet` + +Generate and manage podman quadlet definitions (podman > 4.4.0) + +* **See also** + * podman-systemd.unit.5 + * https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html + +#### Examples + +##### Run a CentOS Container + +```puppet +quadlet::quadlet{'centos.container': + ensure => present, + unit_entry => { + 'Description' => 'Trivial Container that will be very lazy', + }, + service_entry => { + 'TimeoutStartSec' => '900', + }, + container_entry => { + 'Image' => 'quay.io/centos/centos:latest', + 'Exec' => 'sh -c "sleep inf"' + }, + install_entry => { + 'WantedBy' => 'default.target' + }, + active => true, +} +``` + +#### Parameters + +The following parameters are available in the `podman::quadlet` defined type: + +* [`quadlet`](#-podman--quadlet--quadlet) +* [`ensure`](#-podman--quadlet--ensure) +* [`user`](#-podman--quadlet--user) +* [`mode`](#-podman--quadlet--mode) +* [`active`](#-podman--quadlet--active) +* [`unit_entry`](#-podman--quadlet--unit_entry) +* [`install_entry`](#-podman--quadlet--install_entry) +* [`service_entry`](#-podman--quadlet--service_entry) +* [`container_entry`](#-podman--quadlet--container_entry) +* [`pod_entry`](#-podman--quadlet--pod_entry) +* [`volume_entry`](#-podman--quadlet--volume_entry) + +##### `quadlet` + +Data type: `Podman::Quadlet_name` + +of the quadlet file this is the namevar. + +Default value: `$title` + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +State of the container definition. + +Default value: `'present'` + +##### `user` + +Data type: `String[1]` + +User running the container + +Default value: `'root'` + +##### `mode` + +Data type: `Stdlib::Filemode` + +Filemode of container file. + +Default value: `'0444'` + +##### `active` + +Data type: `Optional[Boolean]` + +Make sure the container is running. + +Default value: `undef` -### `podman::rootless` +##### `unit_entry` + +Data type: `Optional[Systemd::Unit::Unit]` + +The `[Unit]` section definition. + +Default value: `undef` + +##### `install_entry` + +Data type: `Optional[Systemd::Unit::Install]` + +The `[Install]` section definition. + +Default value: `undef` + +##### `service_entry` + +Data type: `Optional[Systemd::Unit::Service]` + +The `[Service]` section definition. + +Default value: `undef` + +##### `container_entry` + +Data type: `Optional[Podman::Unit::Container]` + +The `[Container]` section defintion. + +Default value: `undef` + +##### `pod_entry` + +Data type: `Optional[Podman::Unit::Pod]` + +The `[Pod]` section defintion. + +Default value: `undef` + +##### `volume_entry` + +Data type: `Optional[Podman::Unit::Volume]` + +The `[Volume]` section defintion. + +Default value: `undef` + +### `podman::rootless` Enable a given user to run rootless podman containers as a systemd user service. -### `podman::secret` +### `podman::secret` Manage a podman secret. Create and remove secrets, it cannot replace. @@ -717,13 +861,13 @@ podman::secret{'ora_password': The following parameters are available in the `podman::secret` defined type: -* [`ensure`](#ensure) -* [`path`](#path) -* [`secret`](#secret) -* [`flags`](#flags) -* [`user`](#user) +* [`ensure`](#-podman--secret--ensure) +* [`path`](#-podman--secret--path) +* [`secret`](#-podman--secret--secret) +* [`flags`](#-podman--secret--flags) +* [`user`](#-podman--secret--user) -##### `ensure` +##### `ensure` Data type: `Enum['present','absent']` @@ -731,16 +875,16 @@ State of the resource must be either 'present' or 'absent'. Default value: `'present'` -##### `path` +##### `path` Data type: `Optional[Stdlib::Unixpath]` Load secret from an existing file path The secret and path parameters are mutually exclusive. -Default value: ``undef`` +Default value: `undef` -##### `secret` +##### `secret` Data type: `Optional[Sensitive[String]]` @@ -749,9 +893,9 @@ changed the secret will **NOT** be modified. Best to set a secret version as a label. The secret and path parameters are mutually exclusive. -Default value: ``undef`` +Default value: `undef` -##### `flags` +##### `flags` Data type: `Hash` @@ -762,7 +906,7 @@ If the flags for a secret are modified the secret will be recreated. Default value: `{}` -##### `user` +##### `user` Data type: `Optional[String[1]]` @@ -770,9 +914,9 @@ Optional user for running rootless containers. When using this parameter, the user must also be defined as a Puppet resource and must include the 'uid', 'gid', and 'home' -Default value: ``undef`` +Default value: `undef` -### `podman::subgid` +### `podman::subgid` Define an entry in the `/etc/subgid` file. @@ -791,23 +935,23 @@ podman::subgid { 'myuser': The following parameters are available in the `podman::subgid` defined type: -* [`subgid`](#subgid) -* [`count`](#count) -* [`order`](#order) +* [`subgid`](#-podman--subgid--subgid) +* [`count`](#-podman--subgid--count) +* [`order`](#-podman--subgid--order) -##### `subgid` +##### `subgid` Data type: `Integer` Numerical subordinate group ID -##### `count` +##### `count` Data type: `Integer` Numerical subordinate group ID count -##### `order` +##### `order` Data type: `Integer` @@ -815,7 +959,7 @@ Sequence number for concat fragments# Default value: `10` -### `podman::subuid` +### `podman::subuid` Manage entries in `/etc/subuid` @@ -834,23 +978,23 @@ podman::subuid { 'namevar': The following parameters are available in the `podman::subuid` defined type: -* [`subuid`](#subuid) -* [`count`](#count) -* [`order`](#order) +* [`subuid`](#-podman--subuid--subuid) +* [`count`](#-podman--subuid--count) +* [`order`](#-podman--subuid--order) -##### `subuid` +##### `subuid` Data type: `Integer` Numerical subordinate user ID -##### `count` +##### `count` Data type: `Integer` Numerical subordinate user ID count -##### `order` +##### `order` Data type: `Integer` @@ -858,7 +1002,7 @@ Sequence number for concat fragments Default value: `10` -### `podman::volume` +### `podman::volume` Create a podman volume with defined flags @@ -878,19 +1022,19 @@ podman::volume { 'myvolume': The following parameters are available in the `podman::volume` defined type: -* [`ensure`](#ensure) -* [`flags`](#flags) -* [`user`](#user) +* [`ensure`](#-podman--volume--ensure) +* [`flags`](#-podman--volume--flags) +* [`user`](#-podman--volume--user) -##### `ensure` +##### `ensure` -Data type: `String` +Data type: `Enum['present', 'absent']` State of the resource must be either 'present' or 'absent'. Default value: `'present'` -##### `flags` +##### `flags` Data type: `Hash` @@ -901,13 +1045,140 @@ Volume names are created based on the resoure title (namevar) Default value: `{}` -##### `user` +##### `user` -Data type: `String` +Data type: `Optional[String]` Optional user for running rootless containers. When using this parameter, the user must also be defined as a Puppet resource and must include the 'uid', 'gid', and 'home' -Default value: `''` +Default value: `undef` + +## Data types + +### `Podman::Quadlet_name` + +custom datatype that validates different filenames for quadlet units + +* **See also** + * https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html + +Alias of `Pattern[/^[a-zA-Z0-9:\-_.\\@%]+\.(container|volume|pod|network)$/]` + +### `Podman::Unit::Container` + +custom datatype for container entries of podman container quadlet + +* **See also** + * https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html + +Alias of + +```puppet +Struct[Optional['AddCapability'] => Array[String[1],1], + Optional['Annotation'] => Array[String[1],1], + Optional['AutoUpdate'] => Enum['registry','local'], + Optional['ContainerName'] => String[1], + Optional['DNS'] => Array[Stdlib::IP::Address,0], + Optional['DNSOption'] => Array[String[1],0], + Optional['DNSSearch'] => Array[Stdlib::Fqdn,0], + Optional['DropCapability'] => Array[String[1],0], + Optional['Environment'] => Array[String[1],0], + Optional['EnvironmentFile'] => Array[String[1],0], + Optional['Exec'] => String[1], + Optional['ExposeHostPort'] => Array[Stdlib::Port,0], + Optional['GIDMap'] => Array[String[1],0], + Optional['GlobalArgs'] => Array[String[1],0], + Optional['Group'] => Integer[0], + Optional['HealthCmd'] => String[1], + Optional['HealthOnFailure'] => Enum['none','kill','restart','stop'], + Optional['HealthStartPeriod'] => String[1], + Optional['HealthStartupCmd'] => String[1], + Optional['HealthStartupInterval'] => Variant[Enum['disable'],Integer[0]], + Optional['HealthStartupTimeout'] => String[1], + Optional['HealthTimeout'] => String[1], + Optional['Image'] => String[1], + Optional['IP'] => Stdlib::IP::Address::V4, + Optional['IP6'] => Stdlib::IP::Address::V6, + Optional['Label'] => Variant[String[1],Array[String[1],1]], + Optional['LogDriver'] => Enum['k8s-file','journald','none','passthrough'], + Optional['Mask'] => String[1], + Optional['Mount'] => Array[String[1],0], + Optional['Network'] => String[1], + Optional['NoNewPrivileges'] => Boolean, + Optional['Notify'] => Boolean, + Optional['PidsLimits'] => Integer[-1], + Optional['Pod'] => Pattern[/^[a-zA-Z0-0_-]+\.pod$/], + Optional['PodmanArgs'] => Array[String[1],0], + Optional['PublishPort'] => Array[Stdlib::Port,1], + Optional['Pull'] => Enum['always','missing','never','newer'], + Optional['ReadOnly'] => Boolean, + Optional['ReadOnlyTmpfs'] => Boolean, + Optional['Rootfs'] => String[1], + Optional['RunInit'] => Boolean, + Optional['SeccompProfile'] => String[1], + Optional['Secret'] => Array[String[1],0], + Optional['SecurityLabelDisable'] => Boolean, + Optional['SecurityLabelFileType'] => String[1], + Optional['SecurityLabelNested'] => Boolean, + Optional['ShmSize'] => String[1], + Optional['StopTimeout'] => Integer[1], + Optional['SubGIDMap'] => String[1], + Optional['SubUIDMap'] => String[1], + Optional['Sysctl'] => Array[String[1],0], + Optional['Timezone'] => String[1], + Optional['Tmpfs'] => Array[String[1],0], + Optional['UIDMap'] => Array[String[1],0], + Optional['Ulimit'] => String[1], + Optional['Unmask'] => String[1], + Optional['User'] => String[1], + Optional['UserNS'] => String[1], + Optional['Volume'] => Array[String[1],0], + Optional['WorkingDir'] => Stdlib::Unixpath] +``` + +### `Podman::Unit::Pod` + +custom datatype for Volume entries of podman container quadlet + +* **See also** + * https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html + +Alias of + +```puppet +Struct[Optional['ContainersConfModule'] => Variant[Stdlib::Unixpath,Array[Stdlib::Unixpath,1]], + Optional['GlobalArgs'] => Variant[String[1],Array[String[1],1]], + Optional['Network'] => String[1], + Optional['PodmanArgs'] => Variant[String[1],Array[String[1]]], + Optional['PodName'] => String[1], + Optional['PublishPort'] => Array[Stdlib::Port,1], + Optional['Volume'] => Variant[String[1],Array[String[1],]]] +``` + +### `Podman::Unit::Volume` + +custom datatype for Volume entries of podman container quadlet + +* **See also** + * https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html + +Alias of + +```puppet +Struct[Optional['ContainersConfModule'] => Variant[Stdlib::Unixpath,Array[Stdlib::Unixpath,1]], + Optional['Copy'] => Boolean, + Optional['Device'] => String[1], + Optional['Driver'] => String[1], + Optional['GlobalArgs'] => Variant[String[1],Array[String[1],1]], + Optional['Group'] => String[1], + Optional['Image'] => String[1], + Optional['Label'] => Variant[String[1],Array[String[1],1]], + Optional['Options'] => String[1], + Optional['PodmanArgs'] => Variant[String[1],Array[String[1]]], + Optional['Type'] => String[1], + Optional['User'] => String[1], + Optional['VolumeName'] => String[1]] +``` diff --git a/manifests/quadlet.pp b/manifests/quadlet.pp new file mode 100644 index 0000000..bbc55d0 --- /dev/null +++ b/manifests/quadlet.pp @@ -0,0 +1,150 @@ +# @summary Generate and manage podman quadlet definitions (podman > 4.4.0) +# +# @see podman-systemd.unit.5 https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html +# +# @param quadlet of the quadlet file this is the namevar. +# @param ensure State of the container definition. +# @param user User running the container +# @param mode Filemode of container file. +# @param active Make sure the container is running. +# @param unit_entry The `[Unit]` section definition. +# @param install_entry The `[Install]` section definition. +# @param service_entry The `[Service]` section definition. +# @param container_entry The `[Container]` section defintion. +# @param pod_entry The `[Pod]` section defintion. +# @param volume_entry The `[Volume]` section defintion. +# +# @example Run a CentOS Container +# quadlet::quadlet{'centos.container': +# ensure => present, +# unit_entry => { +# 'Description' => 'Trivial Container that will be very lazy', +# }, +# service_entry => { +# 'TimeoutStartSec' => '900', +# }, +# container_entry => { +# 'Image' => 'quay.io/centos/centos:latest', +# 'Exec' => 'sh -c "sleep inf"' +# }, +# install_entry => { +# 'WantedBy' => 'default.target' +# }, +# active => true, +# } +# +define podman::quadlet ( + Enum['present', 'absent'] $ensure = 'present', + Podman::Quadlet_name $quadlet = $title, + String[1] $user = 'root', + Stdlib::Filemode $mode = '0444', + Optional[Boolean] $active = undef, + Optional[Systemd::Unit::Install] $install_entry = undef, + Optional[Systemd::Unit::Unit] $unit_entry = undef, + Optional[Systemd::Unit::Service] $service_entry = undef, + Optional[Podman::Unit::Container] $container_entry = undef, + Optional[Podman::Unit::Volume] $volume_entry = undef, + Optional[Podman::Unit::Pod] $pod_entry = undef, +) { + $_split = $quadlet.split('[.]') + $_name = $_split[0] + $_type = $_split[1] + # Validate the input and find the service name. + case $_type { + 'container': { + if $volume_entry or $pod_entry { + fail('A volume_entry or pod_entry makes no sense on a container quadlet') + } + $_service = "${_name}.service" + } + 'volume': { + if $container_entry or $pod_entry { + fail('A container_entry or pod_entry makes no sense on a volume quadlet') + } + $_service = "${_name}-volume.service" + } + 'pod': { + if $container_entry or $volume_entry { + fail('A container_entry or volume_entry makes no sense on a pod quadlet') + } + $_service = "${_name}-pod.service" + } + default: { + fail('Should never be here due to typing on quadlet') + } + } + + include podman + + # Determine path + if $user == 'root' { + $_path = '/etc/containers/systemd' + $_group = root + } else { + $_path = "${User[$user]['home']}/.config/containers/systemd" + $_group = User[$user]['gid'] + ensure_resource('podman::rootless', $user, {}) + } + + file { "${_path}/${quadlet}": + ensure => $ensure, + owner => $user, + group => $_group, + mode => $mode, + content => epp('podman/quadlet_file.epp', { + 'unit_entry' => $unit_entry, + 'service_entry' => $service_entry, + 'install_entry' => $install_entry, + 'container_entry' => $container_entry, + 'volume_entry' => $volume_entry, + 'pod_entry' => $pod_entry, + }), + } + + if $user == 'root' { + ensure_resource('systemd::daemon_reload', $quadlet) + File["${_path}/${quadlet}"] ~> Systemd::Daemon_reload[$quadlet] + } else { + File["${_path}/${quadlet}"] ~> Exec["daemon-reload-${user}"] + File["${_path}/${quadlet}"] -> Exec["start_${user}.slice"] + } + + if $active != undef { + if $user == 'root' { + service { $_service: + ensure => $active, + } + + if $ensure == 'absent' { + Service[$_service] -> File["${_path}/${quadlet}"] + File["${_path}/${quadlet}"] ~> Systemd::Daemon_reload[$quadlet] + } else { + File["${_path}/${quadlet}"] ~> Service[$_service] + Systemd::Daemon_reload[$quadlet] ~> Service[$_service] + } + } else { + $_systemctl_user = ['systemd-run','--pipe', '--wait', '--user','--machine',"${user}@.host", 'systemctl','--user'] + if $active == true { + exec { "start-${quadlet}-${user}": + command => $_systemctl_user + ['start', $_service], + unless => [$_systemctl_user + ['is-active', $_service]], + path => $facts['path'], + } + exec { "reload-${quadlet}-${user}": + command => $_systemctl_user + ['try-reload-or-restart', $_service], + refreshonly => true, + path => $facts['path'], + before => Exec["start-${quadlet}-${user}"], + } + File["${_path}/${quadlet}"] ~> Exec["reload-${quadlet}-${user}"] + Exec["daemon-reload-${user}"] ~> Exec["reload-${quadlet}-${user}"] + } else { + exec { "stop-${quadlet}-${user}": + command => $_systemctl_user + ['stop', $_service], + onlyif => [$_systemctl_user + ['is-active', $_service]], + path => $facts['path'], + } + } + } + } +} diff --git a/manifests/rootless.pp b/manifests/rootless.pp index af01d62..1a0203f 100644 --- a/manifests/rootless.pp +++ b/manifests/rootless.pp @@ -15,7 +15,9 @@ ensure_resource('File', [ "${User[$name]['home']}/.config", "${User[$name]['home']}/.config/systemd", - "${User[$name]['home']}/.config/systemd/user" + "${User[$name]['home']}/.config/systemd/user", + "${User[$name]['home']}/.config/containers", + "${User[$name]['home']}/.config/containers/systemd", ], { ensure => directory, owner => $name, @@ -36,6 +38,13 @@ ], } + # Use https://github.com/voxpupuli/puppet-systemd/pull/443 once available + exec { "daemon-reload-${name}": + command => ['systemd-run', '--pipe' , '--wait', '--user', '--machine', "${name}@.host", '/usr/bin/systemctl', '--user', 'daemon-reload'], + refreshonly => true, + path => $facts['path'], + } + if $podman::enable_api_socket { exec { "podman rootless api socket ${name}": command => 'systemctl --user enable --now podman.socket', diff --git a/metadata.json b/metadata.json index fe21a0f..f2d5ac7 100644 --- a/metadata.json +++ b/metadata.json @@ -12,6 +12,10 @@ "name": "puppetlabs/stdlib", "version_requirement": ">= 4.1.0 <= 10.0.0" }, + { + "name": "puppet/systemd", + "version_requirement": ">= 5.0.0 <= 7.0.0" + }, { "name": "puppetlabs/concat", "version_requirement": ">= 2.1.0 <= 10.0.0" diff --git a/spec/defines/quadlet_spec.rb b/spec/defines/quadlet_spec.rb new file mode 100644 index 0000000..840b909 --- /dev/null +++ b/spec/defines/quadlet_spec.rb @@ -0,0 +1,188 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'podman::quadlet' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + context 'with a simple centos container image' do + let(:title) { 'centos.container' } + let(:params) do + { + ensure: 'present', + unit_entry: { + 'Description' => 'Simple centos container', + }, + service_entry: { + 'TimeoutStartSec' => '900', + }, + container_entry: { + 'Image' => 'quay.io/centos/centos:latest', + 'Exec' => 'sh -c "sleep inf"', + }, + } + end + + it { is_expected.to compile.with_all_deps } + + it { + is_expected.to contain_file('/etc/containers/systemd/centos.container') + .with_ensure('present') + .with_owner('root') + .with_group('root') + .with_mode('0444') + .with_content(%r{^\[Unit\]$}) + .with_content(%r{^Description=Simple centos container$}) + .with_content(%r{^\[Service\]$}) + .with_content(%r{^TimeoutStartSec=900}) + .with_content(%r{^\[Container\]$}) + .with_content(%r{^Image=quay.io/centos/centos:latest$}) + .with_content(%r{^Exec=sh -c "sleep inf"$}) + } + + it { is_expected.to contain_systemd__daemon_reload('centos.container') } + it { is_expected.not_to contain_service('centos.container') } + it { is_expected.not_to contain_service('centos.service') } + + context 'with the container absent' do + let(:params) do + super().merge({ ensure: 'absent' }) + end + + it { is_expected.to contain_file('/etc/containers/systemd/centos.container').with_ensure('absent') } + it { is_expected.to contain_systemd__daemon_reload('centos.container') } + end + + context 'with the service active' do + let(:params) do + super().merge({ active: true }) + end + + it { is_expected.to contain_service('centos.service').with_ensure(true) } + end + + context 'with a user set' do + let(:pre_condition) do + <<~PUPPET + user{'steve': + ensure => present, + uid => 1000, + gid => 1000, + home => '/var/lib/steve', + } + file{'/var/lib/steve': + ensure => directory, + owner => steve, + group => 1000, + mode => '0644', + } + PUPPET + end + let(:params) do + super().merge({ + user: 'steve', + }) + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_podman__rootless('steve') } + context 'with active true' do + let(:params) do + super().merge({ + active: true, + }) + end + + it { is_expected.to contain_exec('start-centos.container-steve') } + it { + is_expected.to contain_exec('start-centos.container-steve').with( + { + command: ['systemd-run', '--pipe', '--wait', '--user', '--machine', 'steve@.host', 'systemctl', '--user', 'start', 'centos.service'], + unless: [['systemd-run', '--pipe', '--wait', '--user', '--machine', 'steve@.host', 'systemctl', '--user', 'is-active', 'centos.service']], + }, + ) + } + end + end + end + context 'with a simple pod quadlet' do + let(:title) { 'mypod.pod' } + let(:params) do + { + ensure: 'present', + unit_entry: { + 'Description' => 'Simple Pod', + }, + service_entry: { + 'TimeoutStartSec' => '900', + }, + pod_entry: { + 'Network' => 'host', + }, + } + end + + it { is_expected.to compile.with_all_deps } + + it { + is_expected.to contain_file('/etc/containers/systemd/mypod.pod') + .with_ensure('present') + .with_owner('root') + .with_group('root') + .with_mode('0444') + .with_content(%r{^\[Unit\]$}) + .with_content(%r{^Description=Simple Pod$}) + .with_content(%r{^\[Pod\]$}) + .with_content(%r{^Network=host$}) + } + context 'with the pod active' do + let(:params) do + super().merge({ active: true }) + end + + it { is_expected.to contain_service('mypod-pod.service') } + end + end + context 'with a simple volume quadlet' do + let(:title) { 'myvolume.volume' } + let(:params) do + { + ensure: 'present', + unit_entry: { + 'Description' => 'Simple Volume', + }, + service_entry: { + 'TimeoutStartSec' => '900', + }, + volume_entry: { + 'Driver' => 'image', + }, + } + end + + it { is_expected.to compile.with_all_deps } + + it { + is_expected.to contain_file('/etc/containers/systemd/myvolume.volume') + .with_ensure('present') + .with_owner('root') + .with_group('root') + .with_mode('0444') + .with_content(%r{^\[Unit\]$}) + .with_content(%r{^Description=Simple Volume$}) + .with_content(%r{^\[Volume\]$}) + .with_content(%r{^Driver=image$}) + } + context 'with the service active' do + let(:params) do + super().merge({ active: true }) + end + + it { is_expected.to contain_service('myvolume-volume.service') } + end + end + end + end +end diff --git a/spec/defines/rootless_spec.rb b/spec/defines/rootless_spec.rb index fe8725c..bf4da62 100644 --- a/spec/defines/rootless_spec.rb +++ b/spec/defines/rootless_spec.rb @@ -79,6 +79,40 @@ ) end + it do + is_expected.to contain_file('/home/testing-title/.config/containers').only_with( + { + 'ensure' => 'directory', + 'owner' => 'testing-title', + 'group' => '1111', + 'mode' => '0700', + 'require' => 'File[/home/testing-title]', + }, + ) + end + + it do + is_expected.to contain_file('/home/testing-title/.config/containers/systemd').only_with( + { + 'ensure' => 'directory', + 'owner' => 'testing-title', + 'group' => '1111', + 'mode' => '0700', + 'require' => 'File[/home/testing-title]', + }, + ) + end + + it do + is_expected.to contain_exec('daemon-reload-testing-title').only_with( + { + 'command' => ['systemd-run', '--pipe', '--wait', '--user', '--machine', 'testing-title@.host', '/usr/bin/systemctl', '--user', 'daemon-reload'], + 'refreshonly' => true, + 'path' => os_facts[:path], + }, + ) + end + it do is_expected.to contain_exec('start_testing-title.slice').only_with( { diff --git a/spec/type_aliases/quadlet_name_spec.rb b/spec/type_aliases/quadlet_name_spec.rb new file mode 100644 index 0000000..c63afec --- /dev/null +++ b/spec/type_aliases/quadlet_name_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Podman::Quadlet_name' do + context 'with a permitted unit name' do + [ + 'centos.container', + 'fast.network', + 'empty.volume', + 'masive.pod', + ].each do |unit| + it { is_expected.to allow_value(unit) } + end + end + + context 'with a illegal unit name' do + [ + 'a space.service', + 'noending', + 'wrong.ending', + 'forward/slash.unit', + ].each do |unit| + it { is_expected.not_to allow_value(unit) } + end + end +end diff --git a/spec/type_aliases/unit_container_spec.rb b/spec/type_aliases/unit_container_spec.rb new file mode 100644 index 0000000..d7ecd76 --- /dev/null +++ b/spec/type_aliases/unit_container_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Podman::Unit::Container' do + it { is_expected.to allow_value({ 'Image' => 'busybox' }) } + it { is_expected.to allow_value({ 'Exec' => '/bin/bash' }) } + it { is_expected.to allow_value({ 'Exec' => './entrypoint.sh' }) } +end diff --git a/spec/type_aliases/unit_pod_spec.rb b/spec/type_aliases/unit_pod_spec.rb new file mode 100644 index 0000000..18e6bd3 --- /dev/null +++ b/spec/type_aliases/unit_pod_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Podman::Unit::Pod' do + it { is_expected.to allow_value({ 'PodName' => 'special' }) } +end diff --git a/spec/type_aliases/unit_volume_spec.rb b/spec/type_aliases/unit_volume_spec.rb new file mode 100644 index 0000000..cbbd0de --- /dev/null +++ b/spec/type_aliases/unit_volume_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Podman::Unit::Volume' do + it { is_expected.to allow_value({ 'Driver' => 'image' }) } +end diff --git a/templates/quadlet_file.epp b/templates/quadlet_file.epp new file mode 100644 index 0000000..785606a --- /dev/null +++ b/templates/quadlet_file.epp @@ -0,0 +1,42 @@ +<%- | + Optional[Hash] $unit_entry, + Optional[Hash] $service_entry, + Optional[Hash] $install_entry, + Optional[Hash] $container_entry, + Optional[Hash] $volume_entry, + Optional[Hash] $pod_entry, +| -%> +<%- + + # List of possible of unit sections, should match the list of _entry variables + # above. + + $_unit_sections = [ + 'Unit', + 'Service', + 'Container', + 'Pod', + 'Volume', + 'Install', +] + +-%> +# Deployed with puppet +# +<%- +$_unit_sections.each | $_section | { + $_values = getvar("${downcase($_section)}_entry") + if $_values { +-%> + +[<%= $_section %>] +<%- + $_values.each | $_key, $_value | { + Array($_value, true).each | $_subvalue | { -%> +<%= $_key %>=<%= $_subvalue %> +<%- + } + } + } +} +-%> diff --git a/types/quadlet_name.pp b/types/quadlet_name.pp new file mode 100644 index 0000000..8f3b996 --- /dev/null +++ b/types/quadlet_name.pp @@ -0,0 +1,3 @@ +# @summary custom datatype that validates different filenames for quadlet units +# @see https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html +type Podman::Quadlet_name = Pattern[/^[a-zA-Z0-9:\-_.\\@%]+\.(container|volume|pod|network)$/] diff --git a/types/unit/container.pp b/types/unit/container.pp new file mode 100644 index 0000000..dd2f380 --- /dev/null +++ b/types/unit/container.pp @@ -0,0 +1,64 @@ +# @summary custom datatype for container entries of podman container quadlet +# @see https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html +type Podman::Unit::Container = Struct[ + Optional['AddCapability'] => Array[String[1],1], + Optional['Annotation'] => Array[String[1],1], + Optional['AutoUpdate'] => Enum['registry','local'], + Optional['ContainerName'] => String[1], + Optional['DNS'] => Array[Stdlib::IP::Address,0], + Optional['DNSOption'] => Array[String[1],0], + Optional['DNSSearch'] => Array[Stdlib::Fqdn,0], + Optional['DropCapability'] => Array[String[1],0], + Optional['Environment'] => Array[String[1],0], + Optional['EnvironmentFile'] => Array[String[1],0], + Optional['Exec'] => String[1], + Optional['ExposeHostPort'] => Array[Stdlib::Port,0], + Optional['GIDMap'] => Array[String[1],0], + Optional['GlobalArgs'] => Array[String[1],0], + Optional['Group'] => Integer[0], + Optional['HealthCmd'] => String[1], + Optional['HealthOnFailure'] => Enum['none','kill','restart','stop'], + Optional['HealthStartPeriod'] => String[1], + Optional['HealthStartupCmd'] => String[1], + Optional['HealthStartupInterval'] => Variant[Enum['disable'],Integer[0]], + Optional['HealthStartupTimeout'] => String[1], + Optional['HealthTimeout'] => String[1], + Optional['Image'] => String[1], + Optional['IP'] => Stdlib::IP::Address::V4, + Optional['IP6'] => Stdlib::IP::Address::V6, + Optional['Label'] => Variant[String[1],Array[String[1],1]], + Optional['LogDriver'] => Enum['k8s-file','journald','none','passthrough'], + Optional['Mask'] => String[1], + Optional['Mount'] => Array[String[1],0], + Optional['Network'] => String[1], + Optional['NoNewPrivileges'] => Boolean, + Optional['Notify'] => Boolean, + Optional['PidsLimits'] => Integer[-1], + Optional['Pod'] => Pattern[/^[a-zA-Z0-0_-]+\.pod$/], + Optional['PodmanArgs'] => Array[String[1],0], + Optional['PublishPort'] => Array[Stdlib::Port,1], + Optional['Pull'] => Enum['always','missing','never','newer'], + Optional['ReadOnly'] => Boolean, + Optional['ReadOnlyTmpfs'] => Boolean, + Optional['Rootfs'] => String[1], + Optional['RunInit'] => Boolean, + Optional['SeccompProfile'] => String[1], + Optional['Secret'] => Array[String[1],0], + Optional['SecurityLabelDisable'] => Boolean, + Optional['SecurityLabelFileType'] => String[1], + Optional['SecurityLabelNested'] => Boolean, + Optional['ShmSize'] => String[1], + Optional['StopTimeout'] => Integer[1], + Optional['SubGIDMap'] => String[1], + Optional['SubUIDMap'] => String[1], + Optional['Sysctl'] => Array[String[1],0], + Optional['Timezone'] => String[1], + Optional['Tmpfs'] => Array[String[1],0], + Optional['UIDMap'] => Array[String[1],0], + Optional['Ulimit'] => String[1], + Optional['Unmask'] => String[1], + Optional['User'] => String[1], + Optional['UserNS'] => String[1], + Optional['Volume'] => Array[String[1],0], + Optional['WorkingDir'] => Stdlib::Unixpath, +] diff --git a/types/unit/pod.pp b/types/unit/pod.pp new file mode 100644 index 0000000..84fdc0d --- /dev/null +++ b/types/unit/pod.pp @@ -0,0 +1,11 @@ +# @summary custom datatype for Volume entries of podman container quadlet +# @see https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html +type Podman::Unit::Pod = Struct[ + Optional['ContainersConfModule'] => Variant[Stdlib::Unixpath,Array[Stdlib::Unixpath,1]], + Optional['GlobalArgs'] => Variant[String[1],Array[String[1],1]], + Optional['Network'] => String[1], + Optional['PodmanArgs'] => Variant[String[1],Array[String[1]]], + Optional['PodName'] => String[1], + Optional['PublishPort'] => Array[Stdlib::Port,1], + Optional['Volume'] => Variant[String[1],Array[String[1],]], +] diff --git a/types/unit/volume.pp b/types/unit/volume.pp new file mode 100644 index 0000000..4b130e6 --- /dev/null +++ b/types/unit/volume.pp @@ -0,0 +1,17 @@ +# @summary custom datatype for Volume entries of podman container quadlet +# @see https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html +type Podman::Unit::Volume = Struct[ + Optional['ContainersConfModule'] => Variant[Stdlib::Unixpath,Array[Stdlib::Unixpath,1]], + Optional['Copy'] => Boolean, + Optional['Device'] => String[1], + Optional['Driver'] => String[1], + Optional['GlobalArgs'] => Variant[String[1],Array[String[1],1]], + Optional['Group'] => String[1], + Optional['Image'] => String[1], + Optional['Label'] => Variant[String[1],Array[String[1],1]], + Optional['Options'] => String[1], + Optional['PodmanArgs'] => Variant[String[1],Array[String[1]]], + Optional['Type'] => String[1], + Optional['User'] => String[1], + Optional['VolumeName'] => String[1], +]