From b54d4372282bbfd080b2191c6b355e87d038a57b Mon Sep 17 00:00:00 2001 From: Yury Bushmelev Date: Sun, 22 Dec 2024 17:47:49 +0800 Subject: [PATCH] Implement support for conf-{available,enabled} as well --- README.md | 16 ++++++++-- REFERENCE.md | 40 +++++++++++++++++++++---- manifests/config.pp | 15 +++++++++- manifests/configfile.pp | 31 +++++++++++++++++--- manifests/init.pp | 13 ++++++++- spec/acceptance/init_spec.rb | 13 +++++++-- spec/classes/init_spec.rb | 52 +++++++++++++++++++++++++++++++-- spec/defines/configfile_spec.rb | 28 ++++++++++++++++++ types/config.pp | 2 +- 9 files changed, 191 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index e2da141..c0e7173 100644 --- a/README.md +++ b/README.md @@ -93,11 +93,12 @@ caddy::vhost { 'example2': } ``` -Use `conf.d` + `sites-available` + `sites-enabled` layout with `config_files` and `vhosts` parameters set: +Use apache-like configuration files layout: ```puppet class { 'caddy': - config_dir => '/etc/caddy/conf.d', + config_dir => '/etc/caddy/conf-available', + config_enabled_dir => '/etc/caddy/conf-enabled', vhost_dir => '/etc/caddy/sites-available', vhost_enable_dir => '/etc/caddy/sites-enabled', config_files => { @@ -120,7 +121,8 @@ class { 'caddy': Same as above but configured in Hiera: ```yaml -caddy::config_dir: /etc/caddy/conf.d +caddy::config_dir: /etc/caddy/conf-available +caddy::config_enable_dir: /etc/caddy/conf-enabled caddy::vhost_dir: /etc/caddy/sites-available caddy::vhost_enable_dir: /etc/caddy/sites-enabled caddy::config_files: @@ -143,6 +145,14 @@ caddy::vhosts: } ``` +You may consider setting following parameters also. This allows +enabling/disabling config files and virtual hosts manually. + +```yaml +caddy::purge_config_enable_dir: false +caddy::purge_vhost_enable_dir: false +``` + ## Reference The [reference][1] documentation of this module is generated using [puppetlabs/puppetlabs-strings][2]. diff --git a/REFERENCE.md b/REFERENCE.md index ed31a63..6552a68 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -98,6 +98,8 @@ The following parameters are available in the `caddy` class: * [`caddyfile_content`](#-caddy--caddyfile_content) * [`config_dir`](#-caddy--config_dir) * [`purge_config_dir`](#-caddy--purge_config_dir) +* [`config_enable_dir`](#-caddy--config_enable_dir) +* [`purge_config_enable_dir`](#-caddy--purge_config_enable_dir) * [`config_files`](#-caddy--config_files) * [`vhost_dir`](#-caddy--vhost_dir) * [`purge_vhost_dir`](#-caddy--purge_vhost_dir) @@ -384,7 +386,9 @@ Default value: `undef` Data type: `Stdlib::Absolutepath` -Where to store Caddy configs +Where to store Caddy configs. +Set this to /etc/caddy/conf-available to simulate nginx/apache behavior +(see config_enable_dir also). Default value: `'/etc/caddy/config'` @@ -396,6 +400,23 @@ Whether to purge Caddy config directory. Default value: `true` +##### `config_enable_dir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Where to load Caddy configs from. Set this parameter to /etc/caddy/conf-enabled +to simulate nginx/apache behavior. + +Default value: `undef` + +##### `purge_config_enable_dir` + +Data type: `Boolean` + +Whether to purge Caddy enabled config directory. + +Default value: `$purge_config_dir` + ##### `config_files` Data type: `Hash[String[1], Caddy::Config]` @@ -490,14 +511,15 @@ The following parameters are available in the `caddy::configfile` defined type: * [`source`](#-caddy--configfile--source) * [`content`](#-caddy--configfile--content) * [`config_dir`](#-caddy--configfile--config_dir) +* [`enable_dir`](#-caddy--configfile--enable_dir) ##### `ensure` -Data type: `Enum['present','absent']` +Data type: `Enum['present','enabled','disabled','absent']` -Make the config file either present or absent. +Make the config file either present (same as disabled), enabled, disabled or absent. -Default value: `'present'` +Default value: `'enabled'` ##### `source` @@ -523,6 +545,14 @@ Where to store the config file. Default value: `$caddy::config_dir` +##### `enable_dir` + +Data type: `Optional[Stdlib::Absolutepath]` + +Directory to symlink the config config file into (conf-enabled e.g.) if any. + +Default value: `$caddy::config_enable_dir` + ### `caddy::vhost` This defined type handles a Caddy virtual host @@ -605,7 +635,7 @@ Alias of ```puppet Struct[{ - ensure => Optional[Enum['absent', 'present']], + ensure => Optional[Enum['present','enabled','disabled','absent']], source => Optional[Stdlib::Filesource], content => Optional[String[1]], }] diff --git a/manifests/config.pp b/manifests/config.pp index fa2929b..1ae1649 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -40,6 +40,17 @@ } } + # Manage config_enable_dir if defined + if $caddy::config_enable_dir { + file { $caddy::config_enable_dir: + ensure => directory, + owner => $caddy::caddy_user, + group => $caddy::caddy_group, + mode => '0755', + purge => $caddy::purge_config_enable_dir, + recurse => if $caddy::purge_config_enable_dir { true } else { undef }, + } + } # Manage vhost_enable_dir if defined if $caddy::vhost_enable_dir { file { $caddy::vhost_enable_dir: @@ -58,8 +69,10 @@ $real_source = $caddy::caddyfile_source $real_content = if $caddy::caddyfile_source { undef } else { $caddy::caddyfile_content.lest || { + $config_dir = $caddy::config_enable_dir.lest || { $caddy::config_dir } + $vhost_dir = $caddy::vhost_enable_dir.lest || { $caddy::vhost_dir } epp('caddy/etc/caddy/caddyfile.epp', - include_dirs => unique([$caddy::config_dir] + [$caddy::vhost_enable_dir.lest || { $caddy::vhost_dir }]) + include_dirs => unique([$config_dir, $vhost_dir]) ) } } diff --git a/manifests/configfile.pp b/manifests/configfile.pp index 938a3db..895d4a7 100644 --- a/manifests/configfile.pp +++ b/manifests/configfile.pp @@ -1,7 +1,7 @@ # @summary This defined type handles a Caddy config file # # @param ensure -# Make the config file either present or absent. +# Make the config file either present (same as disabled), enabled, disabled or absent. # # @param source # Source (path) for the caddy config file. @@ -12,6 +12,9 @@ # @param config_dir # Where to store the config file. # +# @param enable_dir +# Directory to symlink the config config file into (conf-enabled e.g.) if any. +# # @example Configure Caddy logging # caddy::configfile { 'subdomain-log': # source => 'puppet:///modules/caddy/etc/caddy/config/logging.conf', @@ -32,23 +35,43 @@ # } # define caddy::configfile ( - Enum['present','absent'] $ensure = 'present', + Enum['present','enabled','disabled','absent'] $ensure = 'enabled', Optional[Stdlib::Filesource] $source = undef, Optional[String] $content = undef, Stdlib::Absolutepath $config_dir = $caddy::config_dir, + Optional[Stdlib::Absolutepath] $enable_dir = $caddy::config_enable_dir, ) { include caddy - if ($ensure == 'present') and !($source or $content) { + if ($ensure != 'absent') and !($source or $content) { fail('Either $source or $content must be specified when $ensure is "present"') } + $file_ensure = $ensure ? { + 'absent' => 'absent', + default => 'file', + } + file { "${config_dir}/${title}.conf": - ensure => stdlib::ensure($ensure, 'file'), + ensure => $file_ensure, content => $content, source => $source, mode => '0444', require => Class['caddy::config'], notify => Class['caddy::service'], } + + if $enable_dir { + $symlink_ensure = $ensure ? { + 'enabled' => 'link', + default => 'absent', + } + + file { "${enable_dir}/${title}.conf": + ensure => $symlink_ensure, + target => "${config_dir}/${title}.conf", + require => Class['caddy::config'], + notify => Class['caddy::service'], + } + } } diff --git a/manifests/init.pp b/manifests/init.pp index c8e0339..2b092f2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -121,11 +121,20 @@ # Caddyfile content. # # @param config_dir -# Where to store Caddy configs +# Where to store Caddy configs. +# Set this to /etc/caddy/conf-available to simulate nginx/apache behavior +# (see config_enable_dir also). # # @param purge_config_dir # Whether to purge Caddy config directory. # +# @param config_enable_dir +# Where to load Caddy configs from. Set this parameter to /etc/caddy/conf-enabled +# to simulate nginx/apache behavior. +# +# @param purge_config_enable_dir +# Whether to purge Caddy enabled config directory. +# # @param config_files # Hash of config files to create. # @@ -162,6 +171,7 @@ Stdlib::Absolutepath $caddy_home = '/var/lib/caddy', Stdlib::Absolutepath $caddy_ssl_dir = '/etc/ssl/caddy', Stdlib::Absolutepath $config_dir = '/etc/caddy/config', + Optional[Stdlib::Absolutepath] $config_enable_dir = undef, Stdlib::Absolutepath $vhost_dir = '/etc/caddy/config', Optional[Stdlib::Absolutepath] $vhost_enable_dir = undef, Enum['personal', 'commercial'] $caddy_license = 'personal', @@ -188,6 +198,7 @@ Optional[Stdlib::Filesource] $caddyfile_source = undef, Optional[String[1]] $caddyfile_content = undef, Boolean $purge_config_dir = true, + Boolean $purge_config_enable_dir = $purge_config_dir, Boolean $purge_vhost_dir = $purge_config_dir, Boolean $purge_vhost_enable_dir = $purge_vhost_dir, Hash[String[1], Caddy::Config] $config_files = {}, diff --git a/spec/acceptance/init_spec.rb b/spec/acceptance/init_spec.rb index b275b05..7072318 100644 --- a/spec/acceptance/init_spec.rb +++ b/spec/acceptance/init_spec.rb @@ -109,13 +109,18 @@ class { 'caddy': let(:manifest) do <<~PUPPET class { 'caddy': - config_dir => '/etc/caddy/conf.d', + config_dir => '/etc/caddy/conf-available', + config_enable_dir => '/etc/caddy/conf-enabled', vhost_dir => '/etc/caddy/sites-available', vhost_enable_dir => '/etc/caddy/sites-enabled', config_files => { - admin => { + admin_2020 => { content => "{\n admin localhost:2020\n}\n", }, + admin_2021 => { + ensure => 'disabled', + content => "{\n admin localhost:2021\n}\n", + }, }, vhosts => { port_3000 => { @@ -136,6 +141,10 @@ class { 'caddy': its(:stdout) { is_expected.to eq "{\"listen\":\"localhost:2020\"}\n" } end + describe port(2021) do + it { is_expected.not_to be_listening } + end + describe command('curl -v http://localhost:3000/') do its(:exit_status) { is_expected.to eq 0 } its(:stdout) { is_expected.to eq 'port 3000 ok' } diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 7ba2eec..4dfeafd 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -382,6 +382,53 @@ end end + context 'with config_enable_dir set' do + let(:params) { { config_enable_dir: '/etc/caddy/conf-enabled' } } + + it do + is_expected.to contain_file('/etc/caddy/conf-enabled'). + with_ensure('directory'). + with_owner('caddy'). + with_group('caddy'). + with_mode('0755'). + with_purge(true). + with_recurse(true) + end + + it do + is_expected.to contain_file('/etc/caddy/Caddyfile'). + with_content(%r{^import /etc/caddy/conf-enabled/\*\.conf$}) + end + + context 'with purge_config_enable_dir => false' do + let(:params) { super().merge(purge_config_enable_dir: false) } + + it do + is_expected.to contain_file('/etc/caddy/conf-enabled'). + with_ensure('directory'). + with_purge(false). + with_recurse(nil) + end + end + end + + context 'with both config_dir and config_enable_dir set' do + let(:params) do + { + config_dir: '/etc/caddy/conf-available', + config_enable_dir: '/etc/caddy/conf-enabled', + } + end + + it { is_expected.to contain_file('/etc/caddy/conf-available') } + it { is_expected.to contain_file('/etc/caddy/conf-enabled') } + + it do + is_expected.to contain_file('/etc/caddy/Caddyfile'). + with_content(%r{^import /etc/caddy/conf-enabled/\*\.conf$}) + end + end + context 'with vhost_dir set' do let(:params) { { vhost_dir: '/etc/caddy/vhost.d' } } @@ -472,6 +519,7 @@ source: 'puppet:///profiles/caddy/example1.conf', }, example2: { + ensure: 'disabled', content: "foo\nbar\n", }, example3: { @@ -481,8 +529,8 @@ } end - it { is_expected.to contain_caddy__configfile('example1').with_ensure('present').with_source('puppet:///profiles/caddy/example1.conf') } - it { is_expected.to contain_caddy__configfile('example2').with_ensure('present').with_content("foo\nbar\n") } + it { is_expected.to contain_caddy__configfile('example1').with_ensure('enabled').with_source('puppet:///profiles/caddy/example1.conf') } + it { is_expected.to contain_caddy__configfile('example2').with_ensure('disabled').with_content("foo\nbar\n") } it { is_expected.to contain_caddy__configfile('example3').with_ensure('absent') } end diff --git a/spec/defines/configfile_spec.rb b/spec/defines/configfile_spec.rb index 0fd1364..5da4133 100644 --- a/spec/defines/configfile_spec.rb +++ b/spec/defines/configfile_spec.rb @@ -30,6 +30,34 @@ it { is_expected.to contain_file('/etc/caddy/conf.d/example.conf') } end + context 'with enable_dir set' do + let(:params) { super().merge(enable_dir: '/etc/caddy/conf-enabled') } + + it { is_expected.to contain_file('/etc/caddy/config/example.conf').with_ensure('file') } + + it do + is_expected.to contain_file('/etc/caddy/conf-enabled/example.conf'). + with_ensure('link'). + with_target('/etc/caddy/config/example.conf') + end + + %w[present disabled].each do |ens| + context "with ensure => #{ens}" do + let(:params) { super().merge(ensure: ens) } + + it { is_expected.to contain_file('/etc/caddy/config/example.conf').with_ensure('file') } + it { is_expected.to contain_file('/etc/caddy/conf-enabled/example.conf').with_ensure('absent') } + end + end + + context 'with ensure => absent' do + let(:params) { super().merge(ensure: 'absent') } + + it { is_expected.to contain_file('/etc/caddy/config/example.conf').with_ensure('absent') } + it { is_expected.to contain_file('/etc/caddy/conf-enabled/example.conf').with_ensure('absent') } + end + end + context 'with ensure => absent' do let(:params) { super().merge(ensure: 'absent') } diff --git a/types/config.pp b/types/config.pp index 33588a5..f3d2388 100644 --- a/types/config.pp +++ b/types/config.pp @@ -1,6 +1,6 @@ # @summary Caddy config file type type Caddy::Config = Struct[{ - ensure => Optional[Enum['absent', 'present']], + ensure => Optional[Enum['present','enabled','disabled','absent']], source => Optional[Stdlib::Filesource], content => Optional[String[1]], }]