diff options
-rw-r--r-- | facts.d/btrfs.py | 6 | ||||
-rw-r--r-- | manifests/init.pp | 45 | ||||
-rw-r--r-- | manifests/machine.pp | 89 | ||||
-rw-r--r-- | metadata.json | 29 | ||||
-rw-r--r-- | pdk.yaml | 2 | ||||
-rw-r--r-- | templates/systemd/nspawn.epp | 313 | ||||
-rw-r--r-- | types/systemd/bind.pp | 12 | ||||
-rw-r--r-- | types/systemd/nspawn.pp | 115 | ||||
-rw-r--r-- | types/systemd/resourcelimit | 7 |
9 files changed, 618 insertions, 0 deletions
diff --git a/facts.d/btrfs.py b/facts.d/btrfs.py new file mode 100644 index 0000000..dcb6001 --- /dev/null +++ b/facts.d/btrfs.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import btrfs + +with btrfs.FileSystem('/var/lib/machines') as fs: + for subvolume in fs.subvolumes(): diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 0000000..3eedbae --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,45 @@ +# @summary Configures systemd nspawn containers +# @param config +# Shared configuration for all machines, as per systemd.nspawn(5). +# +# See nspawn::machine's documentation for how it's merged. +# +# @param machines +# Set of machines to be configured. Creates `nspawn::machine` resources. +# See that resource type for acceptable options. +# +# @param template_dir +# Location of template subvolumes. +# +# @param purge +# Should old .nspawn files be purged. +class nspawn ( + Nspawn::Systemdconfig $config, + Stdlib::Abspath $template_dir = '/var/lib/templates', + Hash[String, Hash[String, Any]] $machines = {}, + Boolean $purge = true, +) { + # These aren't parameters since they aren't configurable. + # However, move them to the parameters if it turns out that + # different distributions place these files in different places. + # Location of nspawn files. + $nspawn_dir = '/etc/systemd/nspawn' + # Location of machine subvolumes. + $machine_dir = '/var/lib/machines' + + file { $nspawn_dir: + ensure => directory, + purge => $purge, + recurse => true, + } + + file { $template_dir: + ensure => directory, + } + + file { $machine_dir: + ensure => directory, + } + + create::resources('nspawn::machine', $machines) +} diff --git a/manifests/machine.pp b/manifests/machine.pp new file mode 100644 index 0000000..8b09715 --- /dev/null +++ b/manifests/machine.pp @@ -0,0 +1,89 @@ +# @summary Configuration and provisioning for a single container. +# @param name +# Will be used for both the directory name, and the hostname in the container. +# @param template +# Which template this machine should be configured from. +# +# Templates needs to be manually configured behorehand. +# +# The value 'none' is special, since it allows the machine to be +# managed without a template. The template parameter is however +# required, since a machine without a template needs to be manually +# configured through some other mean. +# +# @param domain +# Domain part of FQDN of container. +# +# @param config +# Configuration for the machine, as per systemd.nspawn(5). +# Will be merged with `nspawn::config` per the `$merge` variable. +# +# @param merge +# How this nodes configuration should be merged with the defalut hash. +# +# - deep +# Stdlib's `deep_merge` will be used, with us on the right. +# - shallow +# `$nspawn::config + $config` +# - replace +# The upstream will be ignored. +# +# @param ensure +define nspawn::machine ( + Variant[String, Enum['none']] $template, + String $domain = $trusted['domain'], + Nspawn::Systemdconfig $config, + Enum['deep', 'shallow', 'override'] $merge = 'deep', + Enum['present', 'absent'] $ensure = 'present', +) { + $root = "${nspawn::machine_dir}/${name}" + + $final_config = $merge ? { + 'deep' => deep_merge($nspawn::config, $config), + 'shallow' => $nspawn::config + $config, + 'override' => $config, + } + + file { "${nspawn::nspawn_dir}/${name}.nspawn": + ensure => $ensure, + content => epp("${module_name}/systemd/nspawn.epp", { + 'data' => $final_config + }), + } + + if $ensure == 'present' { + # if $machine_dir has a quota set, then this inherits it + unless $template == 'none' { + exec { "Initialize ${name} from template": + cmd => [ + 'btrfs', 'snapshot', + "${nspawn::template_dir}/${template}", + $root, + ], + creates => $root, + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + } + } + + file { "${root}/etc/passwd": + content => "${name}\n", + } + + file_line { "${root}/etc/hosts ::1": + line => "::1\t${name}.${domain}\t${name}", + match => "${name}.${domain}", + path => "${root}/etc/hosts", + } + } else { + service { "systemd-nspawn@${name}": + ensure => stopped, + enable => false, + } + + exec { "Remove btrfs subvolume ${root}": + cmd => ['btrfs', 'subvolume', 'delete', $root], + onlyif => [['test', '-d', $root]], + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + } + } +} diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..4201259 --- /dev/null +++ b/metadata.json @@ -0,0 +1,29 @@ +{ + "name": "HugoNikanor-nspawn", + "version": "0.1.0", + "author": "Hugo Hörnquist", + "license": "Apache-2.0", + "summary": "Manages Systemd-Nspawn containers", + "source": "https://git.hornquist.se/puppet/nspawn", + "dependencies": [ + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 6.0.0 < 9.0.0" + } + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 5.5.10 < 8.0.0" + } + ], + "operatingsystem_support": [ + { + "operatingsystem": "Archlinux" + } + ], + "pdk-version": "2.5.0", + "template-url": "pdk-default#2.5.0", + "template-ref": "tags/2.5.0-0-g369d483" +} + diff --git a/pdk.yaml b/pdk.yaml new file mode 100644 index 0000000..4bef4bd --- /dev/null +++ b/pdk.yaml @@ -0,0 +1,2 @@ +--- +ignore: [] diff --git a/templates/systemd/nspawn.epp b/templates/systemd/nspawn.epp new file mode 100644 index 0000000..ee79ba0 --- /dev/null +++ b/templates/systemd/nspawn.epp @@ -0,0 +1,313 @@ +<%- | Nspawn::Systemd::Nspawn $data | -%> + +[Exec] +<%- $exec = $data['Exec'] -%> +<%- if $exec['Boot'] == false { -%> +Boot=no +<%- } elsif $exec['Boot'] == true { -%> +Boot=yes +<%- } -%> +<%- if $exec['Ephemeral'] == false { -%> +Ephemeral=no +<%- } elsif $exec['Ephemeral'] == true { -%> +Ephemeral=yes +<%- } -%> +<%- if $exec['ProcessTwo'] == false { -%> +ProcessTwo=no +<%- } elsif $exec['ProcessTwo'] == true { -%> +ProcessTwo=yes +<%- } -%> +<%- unless $exec['Parameters'] =~ Undef { -%> +<%- if $exec['Parameters'] =~ String { -%> +Parameters=<%= $exec['Parameters'] %> +<%- } else { -%> +Parameters=<%= $exec['Parameters'].map |$param| { + if ' ' in $param { + if '"' in $param { + "'${param}'" + } else { + "\"${param}\"" + } + } else { + $param + } +}.join(' ') %> +<%- } } -%> +<%- unless $exec['Environment'] =~ Undef { -%> +<%- $exec['Environment'].each |$key, $value| { -%> +Environment=<%= $key %>=<%= $value %> +<%- } } -%> +<%- unless $exec['User'] =~ Undef { -%> +User=<%= $exec['User'] %> +<%- } -%> +<%- unless $exec['WorkingDirectory'] =~ Undef { -%> +WorkingDirectory=<%= $exec['WorkingDirectory'] %> +<%- } -%> +<%- unless $exec['PivotRoot'] =~ Undef { -%> +PivotRoot=<%= $exec['PivotRoot'] %> +<%- } -%> +<%- unless $exec['Capability'] =~ Undef { -%> +Capability=<% if $exec['Capability'] == 'all' {%>all<%} else { %><%= $exec['Capability'].join(' ') -%> +<%- } } -%> +<%- unless $exec['DropCapability'] =~ Undef { -%> +DropCapability=<% if $exec['DropCapability'] == 'all' {%>all<%} else { %><%= $exec['DropCapability'].join(' ') -%> +<%- } } -%> +<%- unless $exec['AmbientCapability'] =~ Undef { -%> +AmbientCapability=<%= $exec['AmbientCapability'].join(' ') -%> +<%- } -%> +<%- unless $exec['NoNewPrivileges'] =~ Undef { -%> +NoNewPrivileges=<%= if $exec['NoNewPrivileges'] { 'yes' } else { 'no' }%> +<%- } -%> +<%- unless $exec['KillSignal'] =~ Undef { -%> +KillSignal=<%= $exec['KillSignal'] %> +<%- } -%> +<%- unless $exec['Personality'] =~ Undef { -%> +Personality=<%= $exec['Personality'] %> +<%- } -%> +<%- unless $exec['MachineID'] =~ Undef { -%> +MachineID=<%= $exec['MachineID'] %> +<%- } -%> +<%- unless $exec['PrivateUsers'] =~ Undef { -%> +PrivateUsers=<%= +if $exec['PrivateUsers'] =~ Boolean { + if $exec['PrivateUsers'] { 'yes' } else { 'no' } +} elsif $exec['PrivateUsers'] =~ Tuple { + "<%= $exec['PrivateUsers'].join(':') %>" +} else { + $exec['PrivateUsers'] +} %><%- } -%> +<%- unless $exec['NotifyReady'] =~ Undef { -%> +NotifyReady=<%= if $exec['NotifyReady'] { 'yes' } else { 'no' }%> +<%- } -%> +<%- unless $exec['SystemCallFilter'] =~ Undef { -%> +SystemCallFilter=<%= $exec['SystemCallFilter'].join(' ') %> +<%- } -%> +<%- unless $exec['LimitCPU'] =~ Undef { -%> +<%- if $exec['LimitCPU'] =~ Tuple { -%> +LimitCPU=<%= $exec['LimitCPU'].join(':') %> +<%- } else { -%> +LimitCPU=<%= $exec['LimitCPU'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitFSIZE'] =~ Undef { -%> +<%- if $exec['LimitFSIZE'] =~ Tuple { -%> +LimitFSIZE=<%= $exec['LimitFSIZE'].join(':') %> +<%- } else { -%> +LimitFSIZE=<%= $exec['LimitFSIZE'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitDATA'] =~ Undef { -%> +<%- if $exec['LimitDATA'] =~ Tuple { -%> +LimitDATA=<%= $exec['LimitDATA'].join(':') %> +<%- } else { -%> +LimitDATA=<%= $exec['LimitDATA'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitSTACK'] =~ Undef { -%> +<%- if $exec['LimitSTACK'] =~ Tuple { -%> +LimitSTACK=<%= $exec['LimitSTACK'].join(':') %> +<%- } else { -%> +LimitSTACK=<%= $exec['LimitSTACK'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['limitSTACK'] =~ Undef { -%> +<%- if $exec['limitSTACK'] =~ Tuple { -%> +limitSTACK=<%= $exec['limitSTACK'].join(':') %> +<%- } else { -%> +limitSTACK=<%= $exec['limitSTACK'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitCORE'] =~ Undef { -%> +<%- if $exec['LimitCORE'] =~ Tuple { -%> +LimitCORE=<%= $exec['LimitCORE'].join(':')%> +<%- } else { -%> +LimitCORE=<%= $exec['LimitCORE'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LIMITRSS'] =~ Undef { -%> +<%- if $exec['LIMITRSS'] =~ Tuple { -%> +LIMITRSS=<%= $exec['LIMITRSS'].join(':') %> +<%- } else { -%> +LIMITRSS=<%= $exec['LIMITRSS'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitNOFILE'] =~ Undef { -%> +<%- if $exec['LimitNOFILE'] =~ Tuple { -%> +LimitNOFILE=<%= $exec['LimitNOFILE'].join(':') %> +<%- } else { -%> +LimitNOFILE=<%= $exec['LimitNOFILE'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitAS'] =~ Undef { -%> +<%- if $exec['LimitAS'] =~ Tuple { -%> +LimitAS=<%= $exec['LimitAS'].join(':') %> +<%- } else { -%> +LimitAS=<%= $exec['LimitAS'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitNPROC'] =~ Undef { -%> +<%- if $exec['LimitNPROC'] =~ Tuple { -%> +LimitNPROC=<%= $exec['LimitNPROC'].join(':') %> +<%- } else { -%> +LimitNPROC=<%= $exec['LimitNPROC'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitLOCKS'] =~ Undef { -%> +<%- if $exec['LimitLOCKS'] =~ Tuple { -%> +LimitLOCKS=<%= $exec['LimitLOCKS'].join(':') %> +<%- } else { -%> +LimitLOCKS=<%= $exec['LimitLOCKS'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitSIGPENDING'] =~ Undef { -%> +<%- if $exec['LimitSIGPENDING'] =~ Tuple { -%> +LimitSIGPENDING=<%= $exec['LimitSIGPENDING'].join(':') %> +<%- } else { -%> +LimitSIGPENDING=<%= $exec['LimitSIGPENDING'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitMSGQUEUE'] =~ Undef { -%> +<%- if $exec['LimitMSGQUEUE'] =~ Tuple { -%> +LimitMSGQUEUE=<%= $exec['LimitMSGQUEUE'].join(':') %> +<%- } else { -%> +LimitMSGQUEUE=<%= $exec['LimitMSGQUEUE'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitNICE'] =~ Undef { -%> +<%- if $exec['LimitNICE'] =~ Tuple { -%> +LimitNICE=<%= $exec['LimitNICE'].join(':') %> +<%- } else { -%> +LimitNICE=<%= $exec['LimitNICE'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitRTPRIO'] =~ Undef { -%> +<%- if $exec['LimitRTPRIO'] =~ Tuple { -%> +LimitRTPRIO=<%= $exec['LimitRTPRIO'].join(':') %> +<%- } else { -%> +LimitRTPRIO=<%= $exec['LimitRTPRIO'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['LimitRTTIME'] =~ Undef { -%> +<%- if $exec['LimitRTTIME'] =~ Tuple { -%> +LimitRTTIME=<%= $exec['LimitRTTIME'].join(':') %> +<%- } else { -%> +LimitRTTIME=<%= $exec['LimitRTTIME'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['OOMScoreAdjust'] =~ Undef { -%> +OOMScoreAdjust=<%= $exec['OOMScoreAdjust'] %> +<%- } -%> +<%- unless $exec['CPUAffinity'] =~ Undef { -%> +CPUAffinity=<%= $exec['CPUAffinity'].map |$aff| { + if $aff =~ Tuple { + "${aff[0]}-${aff[1]}" + } else { + "${aff}" + }.join(',') +} %> +<%- } -%> +<%- unless $exec['Hostname'] =~ Undef { -%> +Hostname=<%= $exec['Hostname'] %> +<%- } -%> +<%- unless $exec['ResolvConf'] =~ Undef { -%> +ResolvConf=<%= $exec['ResolvConf'] %> +<%- } -%> +<%- unless $exec['Timezone'] =~ Undef { -%> +Timezone=<%= $exec['Timezone'] %> +<%- } -%> +<%- unless $exec['LinkJournal'] =~ Undef { -%> +LinkJournal=<%= $exec['LinkJournal'] %> +<%- } -%> + +[Files] +<%- unless $exec['ReadOnly'] =~ Undef { -%> +ReadOnly=<%= if $exec['ReadOnly'] { 'yes' } else { 'no' } %> +<%- } -%> +<%- unless $exec['Volatile'] =~ Undef { -%> +<%- if $exec['Volatile'] =~ Boolean { -%> +Volatile=<%= if $exec['Volatile'] { 'yes' } else { 'no' } %> +<%- } else { -%> +Volatile=<%= $exec['Volatile'] %> +<%- } -%> +<%- } -%> +<%- unless $exec['Bind'] =~ Undef { $exec['Bind'].each |$bind| { -%> +<%- if $bind =~ Tuple[String, String] { -%> +Bind=<%= $bind[0] %>:<%= $bind[1] %> +<%- } elsif $bind =~ Tuple[String, String, Array[String]] { -%> +Bind=<%= $bind[0] %>:<%= $bind[1] %>:<%= $bind[2].join(':') %> +<%- } elsif $bind =~ Struct { -%> +Bind=<%= $bind['source'] %>:<%= $bind['dest'] %><%- +if $bind['options'] { %>:<%= $bind['options'].join(':') %><%- } -%> +<%- } else { -%> +Bind=<%= $exec['Bind'] %> +<%- } -%> +<%- }} -%> +<%- unless $exec['BindReadOnly'] =~ Undef { $exec['Bind'].each |$bind| { -%> +<%- if $bind =~ Tuple[String, String] { -%> +BindReadOnly=<%= $bind[0] %>:<%= $bind[1] %> +<%- } elsif $bind =~ Tuple[String, String, Array[String]] { -%> +BindReadOnly=<%= $bind[0] %>:<%= $bind[1] %>:<%= $bind[2].join(':') %> +<%- } elsif $bind =~ Struct { -%> +BindReadOnly=<%= $bind['source'] %>:<%= $bind['dest'] %><%- +if $bind['options'] { %>:<%= $bind['options'].join(':') %><%- } -%> +<%- } else { -%> +BindReadOnly=<%= $exec['Bind'] %> +<%- } -%> +<%- }} -%> +<%- unless $exec['BindUser'] =~ Undef {$exec['BindUser'].each |$user| { -%> +BindUser=<%= $user %> +<%- } } -%> +<%- unless $exec['TemporaryFileSystem'] =~ Undef {$exec['TemporaryFileSystem'].each |$fs| { -%> +TemporaryFileSystem=<%= +if $fs =~ Tuple { + $fs.join(':') +} else { + $fs +} +%> +<%- } } -%> +<%- unless $exec['Inaccessible'] =~ Undef {$exec['Inaccessible'].each |$path| { -%> +Inaccessible=<%= $path %> +<%- } } -%> +<%- unless $exec['Overlay'] =~ Undef {$exec['Overlay'].each |$paths| { -%> +Overlay=<%= $paths.join(':') %> +<%- } } -%> +<%- unless $exec['OverlayReadOnly'] =~ Undef {$exec['OverlayReadOnly'].each |$paths| { -%> +OverlayReadOnly=<%= $paths.join(':') %> +<%- } } -%> +<%- unless $exec['PrivateUsersOwnership'] =~ Undef { -%> +PrivateUsersOwnership=<%= $exec['PrivateUsersOwnership'] %> +<%- } -%> + +[Network] +<%- unless $exec['Private'] =~ Undef { -%> +Private=<%= if $exec['Private'] { 'yes' } else { 'no' } %> +<%- } -%> +<%- unless $exec['VirtualEthernet'] =~ Undef { -%> +VirtualEthernet=<%= if $exec['VirtualEthernet'] { 'yes' } else { 'no' } %> +<%- } -%> +<%- unless $exec['VirtualEthernetExtra'] =~ Undef { + $exec['VirtualEthernetExtra'].each |$interface| { -%> +VirtualEthernetExtra=<%= if $interface =~ Tuple { $interface.join(':') } else { $interface } %> +<%- } -%> +<%- } -%> +<%- unless $exec['Interface'] =~ Undef { -%> +Interface=<%= $exec['Interface'].join(' ') %> +<%- } -%> +<%- unless $exec['MACVLAN'] =~ Undef { -%> +MACVLAN=<%= $exec['MACVLAN'].join(' ') %> +<%- } -%> +<%- unless $exec['IPVLAN'] =~ Undef { -%> +IPVLAN=<%= $exec['IPVLAN'].join(' ') %> +<%- } -%> +<%- unless $exec['Bridge'] =~ Undef { -%> +Bridge=<%= $exec['Bridge'] %> +<%- } -%> +<%- unless $exec['Zone'] =~ Undef { -%> +Zone=<%= $exec['Zone'] %> +<%- } -%> +<%- unless $exec['Port'] =~ Undef { + $exec['Port'].each |$p| { -%> +Port=<%= $p.join(':') %> +<%- } -%> +<%- } -%> diff --git a/types/systemd/bind.pp b/types/systemd/bind.pp new file mode 100644 index 0000000..9554e9a --- /dev/null +++ b/types/systemd/bind.pp @@ -0,0 +1,12 @@ +type Nspawn::Systemd::Bind = Variant[ + String, + Tuple[String, String], + # TODO Typecheck options + Tuple[String, String, Array[String]], + Struct[{ + 'source' => String, + 'dest' => String, + # TODO Typecheck options + 'options' => Optional[Array[String]], + }], +] diff --git a/types/systemd/nspawn.pp b/types/systemd/nspawn.pp new file mode 100644 index 0000000..1b488c8 --- /dev/null +++ b/types/systemd/nspawn.pp @@ -0,0 +1,115 @@ +type Nspawn::Systemd::Nspawn = Struct[{ + 'Exec' => Struct[{ + 'Boot' => Optional[Boolean], + 'Ephemeral' => Optional[Boolean], + 'ProcessTwo' => Optional[Boolean], + 'Parameters' => Optional[Variant[ + String, + Array[String], + ]], + 'Environment' => Optional[Hash[String, String]], + 'User' => Optional[String], + 'WorkingDirectory' => Optional[Stdlib::Unixpath], + 'PivotRoot' => Optional[Stdlib::Unixpath], + 'Capability' => Optional[Variant[Enum['all'], Array[String]]], + 'DropCapability' => Optional[Variant[Enum['all'], Array[String]]], + 'AmbientCapability' => Optional[Array[String]], + 'NoNewPrivileges' => Optional[Boolean], + # See signal(7) for valid signals + 'KillSignal' => Optional[String], + 'Personality' => Optional[Enum['x86', 'x86-64']], + 'MachineID' => Optional[Pattern[/\A[A-fa-f0-9]{32}\Z/]], + 'PrivateUsers' => Optional[Variant[ + Integer, + Tuple[Integer, Integer], + Boolean, + Enum['yes', 'no', 'identity', 'pick'] + ]], + 'NotifyReady' => Optional[Boolean], + # If first element is '~', then this is a blacklist + 'SystemCallFilter' => Optional[Array[String]], + 'LimitCPU' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitFSIZE' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitDATA' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitSTACK' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitCORE' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitRSS' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitNOFILE' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitAS' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitNPROC' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitMEMLOCK' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitLOCKS' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitSIGPENDING' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitMSGQUEUE' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitNICE' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitRTPRIO' => Optional[Nspawn::Systemd::ResourceLimit], + 'LimitRTTIME' => Optional[Nspawn::Systemd::ResourceLimit], + 'OOMScoreAdjust' => Optional[Integer[-1000, 1000]], + 'CPUAffinity' => Optional[Array[Variant[Integer, Tuple[Integer, Integer]]]], + 'Hostname' => Optional[String], + 'ResolvConf' => Optional[Enum[ + 'off', + 'copy-host', + 'copy-static', + 'copy-uplink', + 'copy-stub', + 'replace-host', + 'replace-static', + 'replace-uplink', + 'replace-stub', + 'bind-host', + 'bind-static', + 'bind-uplink', + 'bind-stub', + 'delete', + 'auto', + ]], + 'Timezone' => Optional[Enum[ + 'off', + 'copy', + 'bind', + 'symlink', + 'delete', + 'auto', + ]], + 'LinkJournal' => Optional[Enum[ + 'no', + 'host', + 'try-host', + 'guest', + 'try-guest', + 'auto', + ]], + }], + 'Files' => Struct[{ + 'ReadOnly' => Optional[Boolean], + 'Volatile' => Optional[Variant[Boolean, Enum['state']]], + 'Bind' => Optional[Array[Nspawn::Systemd::Bind]], + 'BindReadOnly' => Optional[Array[Nspawn::Systemd::Bind]], + # TODO Can binduser appear multiple times? + 'BindUser' => Optional[Array[String]], + # TODO Can tmpfs appear multiple times? + # TODO options type + 'TemporaryFileSystem' => Optional[Array[Variant[String, Tuple[String, String]]]], + 'Inaccessible' => Optional[Array[Stdlib::Unixpath]], + 'Overlay' => Optional[Array[Array[String, 2]]], + 'OverlayReadOnly' => Optional[Array[Array[String, 2]]], + 'PrivateUsersOwnership' => Optional[Enum['off', 'chown', 'map', 'auto']], + }], + 'Network' => Struct[{ + 'Private' => Optional[Boolean], + 'VirtualEthernet' => Optional[Boolean], + 'VirtualEthernetExtra' => Optional[Array[Variant[String, Tuple[String, String]]]], + 'Interface' => Optional[Array[String]], + 'MACVLAN' => Optional[Array[String]], + 'IPVLAN' => Optional[Array[String]], + 'Bridge' => Optional[String], + 'Zone' => Optional[String], + 'Port' => Optional[Array[Variant[ + Tuple[Enum['tcp', 'udp'], Stdlib::Port, Stdlib::Port], + Tuple[Enum['tcp', 'udp'], Stdlib::Port], + Tuple[Stdlib::Port, Stdlib::Port], + Tuple[Stdlib::Port], + ]]], + }], +}] diff --git a/types/systemd/resourcelimit b/types/systemd/resourcelimit new file mode 100644 index 0000000..3558fb5 --- /dev/null +++ b/types/systemd/resourcelimit @@ -0,0 +1,7 @@ +type Nspawn::Systemd::ResourceLimit = Variant[ + Variant[Integer, enum['infinity']], + Tuple[ + Variant[Integer, enum['infinity']], + Variant[Integer, enum['infinity']], + ] +] |