Skip to content

Commit

Permalink
Merge pull request #122 from matonb/definable_crontime
Browse files Browse the repository at this point in the history
Add cron time parameters
  • Loading branch information
alexjfisher authored Dec 11, 2018
2 parents 305ea0c + c5d966a commit 63fd8aa
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 12 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,21 @@ letsencrypt::certonly { 'foo':
}
```

To automatically renew a certificate, you can pass the `manage_cron` parameter.
You can optionally add a shell command to be run on success using the `cron_success_command` parameter.
You can optionally add a shell command to be run on before using the `cron_before_command` parameter.
You can optionally specify one or multiple days of the month when to run the cron using the `cron_monthday` parameter (default is every day).
You can disable output (and resulting emails) generated by the cron command using the `suppress_cron_output` parameter.
* `manage_cron` can be used to automatically renew the certificate
* `cron_success_command` can be used to run a shell command on a successful renewal
* `cron_before_command` can be used to run a shell command before a renewal
* `cron_monthday` can be used to specify one or multiple days of the month to run the cron job (defaults to every day)
* `cron_hour` can be used to specify hour(s) to run the cron job (defaults to a seeded random hour)
* `cron_minute` can be used to specify minute(s) to run the cron job (defaults to a seeded random minute)
* `suppress_cron_output` can be used to disable output (and resulting emails) generated by the cron command

```puppet
letsencrypt::certonly { 'foo':
domains => ['foo.example.com', 'bar.example.com'],
manage_cron => true,
cron_before_command => 'service nginx stop',
domains => ['foo.example.com', 'bar.example.com'],
manage_cron => true,
cron_hour => [0,12],
cron_minute => '30',
cron_before_command => 'service nginx stop',
cron_success_command => '/bin/systemctl reload nginx.service',
suppress_cron_output => true,
}
Expand Down
10 changes: 8 additions & 2 deletions manifests/certonly.pp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
# [*cron_success_command*]
# String representation of a command that should be run if the renewal command
# succeeds.
# [*cron_hour*]
# Optional string, integer or array, hour(s) that the renewal command should execute.
# e.g. '[0,12]' execute at midnight and midday. Default - seeded random hour.
# [*cron_minute*]
# Optional string, integer or array, minute(s) that the renewal command should execute.
# e.g. 0 or '00' or [0,30]. Default - seeded random minute.
#
define letsencrypt::certonly (
Array[String[1]] $domains = [$title],
Expand All @@ -45,6 +51,8 @@
Optional[String[1]] $cron_before_command = undef,
Optional[String[1]] $cron_success_command = undef,
Array[Variant[Integer[0, 59], String[1]]] $cron_monthday = ['*'],
Variant[Integer[0,23], String, Array] $cron_hour = fqdn_rand(24, $title),
Variant[Integer[0,59], String, Array] $cron_minute = fqdn_rand(60, fqdn_rand_string(10, $title)),
Stdlib::Unixpath $config_dir = $letsencrypt::config_dir,
) {

Expand Down Expand Up @@ -109,8 +117,6 @@
} else {
$cron_cmd = $renewcommand
}
$cron_hour = fqdn_rand(24, $title) # 0 - 23, seed is title plus fqdn
$cron_minute = fqdn_rand(60, fqdn_rand_string(10,$title)) # 0 - 59, seed is title plus fqdn
file { "${::letsencrypt::cron_scripts_path}/renew-${title}.sh":
ensure => 'file',
mode => '0755',
Expand Down
106 changes: 104 additions & 2 deletions spec/defines/letsencrypt_certonly_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
it { is_expected.to contain_exec('letsencrypt certonly foo.example.com').with_command 'letsencrypt --text --agree-tos --non-interactive certonly -a apache --cert-name foo.example.com -d foo.example.com' }
end

context 'with custom plugin and manage cron' do
context 'with custom plugin and manage_cron' do
let(:title) { 'foo.example.com' }
let(:params) do
{
Expand All @@ -87,6 +87,108 @@
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a apache --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with manage_cron and defined cron_hour (integer)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_hour: 13,
manage_cron: true
}
end

it { is_expected.to contain_cron('letsencrypt renew cron foo.example.com').with_hour 13 }
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a standalone --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with manage_cron and out of range defined cron_hour (integer)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_hour: 24,
manage_cron: true
}
end

it { is_expected.to raise_error Puppet::Error }
end

context 'with manage_cron and defined cron_hour (string)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_hour: '00',
manage_cron: true
}
end

it { is_expected.to contain_cron('letsencrypt renew cron foo.example.com').with_hour '00' }
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a standalone --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with manage_cron and defined cron_hour (array)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_hour: [1, 13],
manage_cron: true
}
end

it { is_expected.to contain_cron('letsencrypt renew cron foo.example.com').with_hour [1, 13] }
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a standalone --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with manage_cron and defined cron_minute (integer)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_minute: 15,
manage_cron: true
}
end

it { is_expected.to contain_cron('letsencrypt renew cron foo.example.com').with_minute 15 }
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a standalone --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with manage_cron and out of range defined cron_hour (integer)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_hour: 66,
manage_cron: true
}
end

it { is_expected.to raise_error Puppet::Error }
end

context 'with manage_cron and defined cron_minute (string)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_minute: '15',
manage_cron: true
}
end

it { is_expected.to contain_cron('letsencrypt renew cron foo.example.com').with_minute '15' }
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a standalone --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with manage_cron and defined cron_minute (array)' do
let(:title) { 'foo.example.com' }
let(:params) do
{
cron_minute: [0, 30],
manage_cron: true
}
end

it { is_expected.to contain_cron('letsencrypt renew cron foo.example.com').with_minute [0, 30] }
it { is_expected.to contain_file('/var/lib/puppet/letsencrypt/renew-foo.example.com.sh').with_content "#!/bin/sh\nexport VENV_PATH=/opt/letsencrypt/.venv\nletsencrypt --text --agree-tos --non-interactive certonly -a standalone --keep-until-expiring --cert-name foo.example.com -d foo.example.com\n" }
end

context 'with custom puppet_vardir path and manage_cron' do
let(:facts) { { osfamily: osfamily, operatingsystem: osfamily, operatingsystemrelease: osversion, operatingsystemmajrelease: osversion.split('.').first, path: '/usr/bin', puppet_vardir: '/tmp/custom_vardir' } }
let(:title) { 'foo.example.com' }
Expand Down Expand Up @@ -142,7 +244,7 @@
it { is_expected.to contain_exec('letsencrypt certonly foo.example.com').with_environment(['VENV_PATH=/opt/letsencrypt/.venv', 'FOO=bar', 'FIZZ=buzz']) }
end

context 'with custom environment variables and manage cron' do
context 'with custom environment variables and manage_cron' do
let(:title) { 'foo.example.com' }
let(:params) { { environment: ['FOO=bar', 'FIZZ=buzz'], manage_cron: true } }

Expand Down

0 comments on commit 63fd8aa

Please sign in to comment.