diff --git a/REFERENCE.md b/REFERENCE.md
index fb5cc41..ee101b9 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -21,6 +21,10 @@
* [`caddy::vhost`](#caddy--vhost): This defined type handles the Caddy virtual hosts.
+### Data types
+
+* [`Caddy::VirtualHost`](#Caddy--VirtualHost): Caddy virtual host type
+
## Classes
### `caddy`
@@ -87,6 +91,12 @@ The following parameters are available in the `caddy` class:
* [`repo_settings`](#-caddy--repo_settings)
* [`package_name`](#-caddy--package_name)
* [`package_ensure`](#-caddy--package_ensure)
+* [`manage_caddyfile`](#-caddy--manage_caddyfile)
+* [`caddyfile_source`](#-caddy--caddyfile_source)
+* [`caddyfile_content`](#-caddy--caddyfile_content)
+* [`config_dir`](#-caddy--config_dir)
+* [`purge_config_dir`](#-caddy--purge_config_dir)
+* [`vhosts`](#-caddy--vhosts)
##### `version`
@@ -339,6 +349,54 @@ Whether to install or remove the caddy package. Only relevant when $install_meth
Default value: `$version`
+##### `manage_caddyfile`
+
+Data type: `Boolean`
+
+Whether to manage Caddyfile.
+
+Default value: `true`
+
+##### `caddyfile_source`
+
+Data type: `Optional[Stdlib::Filesource]`
+
+Caddyfile source.
+
+Default value: `undef`
+
+##### `caddyfile_content`
+
+Data type: `Optional[String[1]]`
+
+Caddyfile content.
+
+Default value: `undef`
+
+##### `config_dir`
+
+Data type: `Stdlib::Absolutepath`
+
+Where to store Caddy configs
+
+Default value: `'/etc/caddy/config'`
+
+##### `purge_config_dir`
+
+Data type: `Boolean`
+
+Whether to purge Caddy config directory.
+
+Default value: `true`
+
+##### `vhosts`
+
+Data type: `Hash[String[1], Caddy::VirtualHost]`
+
+List of virtual hosts to create.
+
+Default value: `{}`
+
## Defined types
### `caddy::vhost`
@@ -367,14 +425,24 @@ caddy::vhost { 'example2:
The following parameters are available in the `caddy::vhost` defined type:
+* [`ensure`](#-caddy--vhost--ensure)
* [`source`](#-caddy--vhost--source)
* [`content`](#-caddy--vhost--content)
+* [`config_dir`](#-caddy--vhost--config_dir)
+
+##### `ensure`
+
+Data type: `Enum['present','absent']`
+
+Make the vhost either present or absent
+
+Default value: `'present'`
##### `source`
Data type: `Optional[Stdlib::Filesource]`
-source (path) for the caddy vhost configuration
+Source (path) for the caddy vhost configuration
Default value: `undef`
@@ -382,7 +450,31 @@ Default value: `undef`
Data type: `Optional[String]`
-string with the caddy vhost configuration
+String with the caddy vhost configuration
Default value: `undef`
+##### `config_dir`
+
+Data type: `Stdlib::Absolutepath`
+
+Where to store the vhost config file
+
+Default value: `$caddy::config_dir`
+
+## Data types
+
+### `Caddy::VirtualHost`
+
+Caddy virtual host type
+
+Alias of
+
+```puppet
+Struct[{
+ ensure => Optional[Enum['absent', 'present']],
+ source => Optional[Stdlib::Filesource],
+ content => Optional[String[1]],
+}]
+```
+
diff --git a/files/etc/caddy/Caddyfile b/files/etc/caddy/Caddyfile
deleted file mode 100644
index 4a1f549..0000000
--- a/files/etc/caddy/Caddyfile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# THIS FILE IS MANAGED BY PUPPET
-#
-
-import config/*.conf
diff --git a/manifests/config.pp b/manifests/config.pp
index d4d3eb9..8fe685f 100644
--- a/manifests/config.pp
+++ b/manifests/config.pp
@@ -22,17 +22,31 @@
owner => 'root',
group => 'root',
;
+ $caddy::config_dir:
+ purge => $caddy::purge_config_dir,
+ recurse => true,
+ ;
+ }
+
+ if $caddy::manage_caddyfile {
+ # Prefer source over content if both are defined
+ # Fallback to the bundled template if both are unset
+ $real_source = $caddy::caddyfile_source
+ $real_content = if $caddy::caddyfile_source { undef } else {
+ $caddy::caddyfile_content.lest || {
+ epp('caddy/etc/caddy/caddyfile.epp',
+ config_dir => $caddy::config_dir,
+ )
+ }
+ }
- ['/etc/caddy/Caddyfile']:
+ file { '/etc/caddy/Caddyfile':
ensure => file,
mode => '0444',
- source => 'puppet:///modules/caddy/etc/caddy/Caddyfile',
- require => File['/etc/caddy'],
- ;
-
- ['/etc/caddy/config']:
- purge => true,
- recurse => true,
- ;
+ owner => $caddy::caddy_user,
+ group => $caddy::caddy_group,
+ source => $real_source,
+ content => $real_content,
+ }
}
}
diff --git a/manifests/init.pp b/manifests/init.pp
index 7147b8a..ec49d5f 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -111,6 +111,24 @@
# @param package_ensure
# Whether to install or remove the caddy package. Only relevant when $install_method is 'repo'.
#
+# @param manage_caddyfile
+# Whether to manage Caddyfile.
+#
+# @param caddyfile_source
+# Caddyfile source.
+#
+# @param caddyfile_content
+# Caddyfile content.
+#
+# @param config_dir
+# Where to store Caddy configs
+#
+# @param purge_config_dir
+# Whether to purge Caddy config directory.
+#
+# @param vhosts
+# List of virtual hosts to create.
+#
class caddy (
String[1] $version = '2.0.0',
Optional[Enum['github','repo']] $install_method = undef,
@@ -123,6 +141,7 @@
Stdlib::Absolutepath $caddy_log_dir = '/var/log/caddy',
Stdlib::Absolutepath $caddy_home = '/var/lib/caddy',
Stdlib::Absolutepath $caddy_ssl_dir = '/etc/ssl/caddy',
+ Stdlib::Absolutepath $config_dir = '/etc/caddy/config',
Enum['personal', 'commercial'] $caddy_license = 'personal',
Enum['on','off'] $caddy_telemetry = 'off',
String[1] $caddy_features = 'http.git,http.filter,http.ipfilter',
@@ -143,6 +162,11 @@
Hash[String[1],Any] $repo_settings = {},
String[1] $package_name = 'caddy',
String[1] $package_ensure = $version,
+ Boolean $manage_caddyfile = true,
+ Optional[Stdlib::Filesource] $caddyfile_source = undef,
+ Optional[String[1]] $caddyfile_content = undef,
+ Boolean $purge_config_dir = true,
+ Hash[String[1], Caddy::VirtualHost] $vhosts = {},
) {
case $caddy_architecture {
'x86_64', 'amd64': { $arch = 'amd64' }
@@ -179,6 +203,12 @@
contain caddy::config
contain caddy::service
+ $vhosts.each |String[1] $name, Caddy::VirtualHost $vhost| {
+ caddy::vhost { $name:
+ * => $vhost,
+ }
+ }
+
Class['caddy::install']
-> Class['caddy::config']
~> Class['caddy::service']
diff --git a/manifests/vhost.pp b/manifests/vhost.pp
index 12b99ef..4e5cef7 100644
--- a/manifests/vhost.pp
+++ b/manifests/vhost.pp
@@ -1,7 +1,16 @@
# @summary This defined type handles the Caddy virtual hosts.
#
-# @param source source (path) for the caddy vhost configuration
-# @param content string with the caddy vhost configuration
+# @param ensure
+# Make the vhost either present or absent
+#
+# @param source
+# Source (path) for the caddy vhost configuration
+#
+# @param content
+# String with the caddy vhost configuration
+#
+# @param config_dir
+# Where to store the vhost config file
#
# @example Configure virtual host, based on source
# caddy::vhost { 'example1':
@@ -14,12 +23,19 @@
# }
#
define caddy::vhost (
- Optional[Stdlib::Filesource] $source = undef,
- Optional[String] $content = undef,
+ Enum['present','absent'] $ensure = 'present',
+ Optional[Stdlib::Filesource] $source = undef,
+ Optional[String] $content = undef,
+ Stdlib::Absolutepath $config_dir = $caddy::config_dir,
) {
include caddy
- file { "/etc/caddy/config/${title}.conf":
- ensure => file,
+
+ if ($ensure == 'present') and !($source or $content) {
+ fail('Either $source or $content must be specified when $ensure is "present"')
+ }
+
+ file { "${config_dir}/${title}.conf":
+ ensure => stdlib::ensure($ensure, 'file'),
content => $content,
source => $source,
mode => '0444',
diff --git a/spec/acceptance/init_spec.rb b/spec/acceptance/init_spec.rb
index 3282d62..46f9677 100644
--- a/spec/acceptance/init_spec.rb
+++ b/spec/acceptance/init_spec.rb
@@ -93,7 +93,7 @@ class { 'caddy':
}
caddy::vhost {'example1':
- source => 'puppet:///modules/caddy/etc/caddy/config/example1.conf',
+ content => "localhost:3000 {\n respond \\'example1\\'\n}\n"
}
caddy::vhost {'example2':
diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb
index e7fbcc1..08b054e 100644
--- a/spec/classes/init_spec.rb
+++ b/spec/classes/init_spec.rb
@@ -116,7 +116,8 @@
'owner' => 'caddy',
'group' => 'caddy',
'mode' => '0444',
- 'source' => 'puppet:///modules/caddy/etc/caddy/Caddyfile'
+ 'source' => nil,
+ 'content' => %r{^import /etc/caddy/config/\*\.conf$}
).
that_requires('File[/etc/caddy]')
end
@@ -319,6 +320,59 @@
it { is_expected.to contain_service('caddy').with_enable(false) }
end
+
+ context 'with manage_caddyfile => false' do
+ let(:params) { { manage_caddyfile: false } }
+
+ it { is_expected.not_to contain_file('/etc/caddy/Caddyfile') }
+ end
+
+ context 'with caddyfile_source set' do
+ let(:params) { { caddyfile_source: 'http://example.com/Caddyfile' } }
+
+ it { is_expected.to contain_file('/etc/caddy/Caddyfile').with_source('http://example.com/Caddyfile').with_content(nil) }
+ end
+
+ context 'with caddyfile_content set' do
+ let(:params) { { caddyfile_content: "localhost\nfile_server\n" } }
+
+ it { is_expected.to contain_file('/etc/caddy/Caddyfile').with_source(nil).with_content("localhost\nfile_server\n") }
+ end
+
+ context 'with both caddyfile_source and caddyfile_content set' do
+ let(:params) do
+ {
+ caddyfile_source: 'http://example.com/Caddyfile',
+ caddyfile_content: "localhost\nfile_server\n",
+ }
+ end
+
+ it 'prefers source over content' do
+ is_expected.to contain_file('/etc/caddy/Caddyfile').with_source('http://example.com/Caddyfile').with_content(nil)
+ end
+ end
+
+ context 'with vhosts set' do
+ let(:params) do
+ {
+ vhosts: {
+ 'h1.example.com': {
+ source: 'http://example.com/test-example-com.conf',
+ },
+ 'h2.example.com': {
+ content: "localhost:1234{\n file_server\n}\n",
+ },
+ 'h3.example.com': {
+ ensure: 'absent',
+ }
+ }
+ }
+ end
+
+ it { is_expected.to contain_file('/etc/caddy/config/h1.example.com.conf').with_source('http://example.com/test-example-com.conf') }
+ it { is_expected.to contain_file('/etc/caddy/config/h2.example.com.conf').with_content("localhost:1234{\n file_server\n}\n") }
+ it { is_expected.to contain_file('/etc/caddy/config/h3.example.com.conf').with_ensure('absent') }
+ end
end
end
end
diff --git a/spec/defines/vhost_spec.rb b/spec/defines/vhost_spec.rb
index a6be06b..0cae95e 100644
--- a/spec/defines/vhost_spec.rb
+++ b/spec/defines/vhost_spec.rb
@@ -8,17 +8,14 @@
let(:facts) do
facts
end
+ let(:pre_condition) { 'class { "caddy": config_dir => "/etc/caddy/config" }' }
+ let(:title) { 'example' }
context 'with source' do
- let(:title) { 'example1' }
- let(:params) do
- {
- source: 'puppet:///modules/caddy/etc/caddy/config/example1.conf'
- }
- end
+ let(:params) { { source: 'puppet:///modules/caddy/etc/caddy/config/example1.conf' } }
it do
- expect(subject).to contain_file('/etc/caddy/config/example1.conf').with(
+ is_expected.to contain_file('/etc/caddy/config/example.conf').with(
'ensure' => 'file',
'source' => 'puppet:///modules/caddy/etc/caddy/config/example1.conf',
'mode' => '0444',
@@ -26,18 +23,31 @@
'notify' => 'Class[Caddy::Service]'
)
end
+
+ context 'with config_dir set' do
+ let(:params) { super().merge(config_dir: '/etc/caddy/conf.d') }
+
+ it { is_expected.to contain_file('/etc/caddy/conf.d/example.conf') }
+ 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') }
+ end
+
+ context 'with custom title' do
+ let(:title) { 'test' }
+
+ it { is_expected.to contain_file('/etc/caddy/config/test.conf') }
+ end
end
context 'with content' do
- let(:title) { 'example2' }
- let(:params) do
- {
- content: 'localhost:2015'
- }
- end
+ let(:params) { { content: 'localhost:2015' } }
it do
- expect(subject).to contain_file('/etc/caddy/config/example2.conf').with(
+ is_expected.to contain_file('/etc/caddy/config/example.conf').with(
'ensure' => 'file',
'content' => 'localhost:2015',
'mode' => '0444',
@@ -46,6 +56,10 @@
)
end
end
+
+ context 'without source & content' do
+ it { is_expected.to compile.and_raise_error(%r{Either \$source or \$content must be specified}) }
+ end
end
end
end
diff --git a/templates/etc/caddy/caddyfile.epp b/templates/etc/caddy/caddyfile.epp
new file mode 100644
index 0000000..b65848f
--- /dev/null
+++ b/templates/etc/caddy/caddyfile.epp
@@ -0,0 +1,8 @@
+<%- |
+ String[1] $config_dir,
+| -%>
+#
+# THIS FILE IS MANAGED BY PUPPET
+#
+
+import <%= $config_dir %>/*.conf
diff --git a/types/virtualhost.pp b/types/virtualhost.pp
new file mode 100644
index 0000000..8b5dd04
--- /dev/null
+++ b/types/virtualhost.pp
@@ -0,0 +1,6 @@
+# @summary Caddy virtual host type
+type Caddy::VirtualHost = Struct[{
+ ensure => Optional[Enum['absent', 'present']],
+ source => Optional[Stdlib::Filesource],
+ content => Optional[String[1]],
+}]