puppet: Stop relying on "tidy" ordering, which ignores metaparams.

The `tidy` parameter is buggy, and ignores all ordering
metaparameters.  This is fixed in Puppet 7[^1], but it's helpful to
resolve it now.  Specifically, this fixes bugs with tidy running too
early, and deleting the old version of a package before its new
version is installed or symlinked, leaving a race condition if
anything tries to run the binary in this window.

This is mostly not a problem for Supervisor-managed processes, since
the binary is already running, and can continue to run if it is tidied
out from under the running process.  For stand-alone tools like wal-g,
which are run frequently by PostgreSQL, this may cause issues if
PostgreSQL tries to call them during a puppet run.

Remove all complicated uses of tidy, and replace them with an `exec`
which does the equivalent.  We also generate `file` resources for
binaries, making them easier (and clearer) to specify as dependencies.

[^1]: https://puppet.atlassian.net/browse/PUP-10688
This commit is contained in:
Alex Vandiver 2024-04-15 18:11:08 +00:00 committed by Tim Abbott
parent d341e6ced1
commit b0e3191434
14 changed files with 70 additions and 38 deletions

View File

@ -32,9 +32,10 @@ class kandra::aws_tools {
ensure => link,
target => "/srv/zulip-aws_signing_helper-${helper_version}",
require => [
Zulip::External_Dep['aws_signing_helper'],
File["/srv/zulip-aws_signing_helper-${helper_version}"],
Exec['install-aws-cli'],
],
before => Exec['Cleanup aws_signing_helper'],
}
package { 'sqlite3': ensure => installed }
file { '/usr/local/bin/teleport-aws-credentials':

View File

@ -13,6 +13,8 @@ class kandra::profile::grafana inherits kandra::profile::base {
version => $version,
url => "https://dl.grafana.com/oss/release/grafana-${version}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "grafana-v${version}",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
group { 'grafana':
@ -45,7 +47,7 @@ class kandra::profile::grafana inherits kandra::profile::base {
ensure => file,
require => [
Package[supervisor],
Zulip::External_Dep['grafana'],
File[$bin],
File[$data_dir],
File['/var/log/grafana'],
],

View File

@ -24,11 +24,14 @@ class kandra::profile::prometheus_server inherits kandra::profile::base {
version => $version,
url => "https://github.com/prometheus/prometheus/releases/download/v${version}/prometheus-${version}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "prometheus-${version}.linux-${zulip::common::goarch}",
bin => [$bin, "${dir}/promtool"],
cleanup_after => [Service[supervisor]],
}
file { '/usr/local/bin/promtool':
ensure => link,
target => "${dir}/promtool",
require => Zulip::External_Dep['prometheus'],
require => File["${dir}/promtool"],
before => Exec['Cleanup prometheus'],
}
file { $data_dir:
@ -56,7 +59,7 @@ class kandra::profile::prometheus_server inherits kandra::profile::base {
ensure => file,
require => [
Package[supervisor],
Zulip::External_Dep['prometheus'],
File[$bin],
File[$data_dir],
File['/etc/prometheus/prometheus.yaml'],
],

View File

@ -25,8 +25,9 @@ class kandra::prometheus::akamai {
User[zulip],
Package[supervisor],
File['/etc/vector.toml'],
Zulip::External_Dep['vector'],
File[$bin],
],
before => Exec['Cleanup vector'],
owner => 'root',
group => 'root',
mode => '0644',

View File

@ -12,6 +12,8 @@ class kandra::prometheus::node {
version => $version,
url => "https://github.com/prometheus/node_exporter/releases/download/v${version}/node_exporter-${version}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "node_exporter-${version}.linux-${zulip::common::goarch}",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
kandra::firewall_allow { 'node_exporter': port => '9100' }
@ -20,7 +22,7 @@ class kandra::prometheus::node {
require => [
User[zulip],
Package[supervisor],
Zulip::External_Dep['node_exporter'],
File[$bin],
],
owner => 'root',
group => 'root',

View File

@ -32,19 +32,20 @@ class kandra::prometheus::postgresql {
require => [
Zulip::External_Dep['golang'],
Zulip::External_Dep['postgres_exporter-src'],
]
],
notify => Exec['Cleanup postgres_exporter'],
}
# This resource exists purely so it doesn't get tidied; it is
# created by the 'compile postgres_exporter' step.
# This resource is created by the 'compile postgres_exporter' step.
file { $bin:
ensure => file,
require => Exec['compile postgres_exporter'],
}
tidy { '/usr/local/bin/postgres_exporter-*':
path => '/usr/local/bin',
recurse => 1,
matches => 'postgres_exporter-*',
require => Exec['compile postgres_exporter'],
exec { 'Cleanup postgres_exporter':
refreshonly => true,
provider => shell,
onlyif => "ls /usr/local/bin/postgres_exporter-* | grep -xv '${bin}'",
command => "ls /usr/local/bin/postgres_exporter-* | grep -xv '${bin}' | xargs rm -r",
require => [File[$bin], Service[supervisor]],
}
if false {

View File

@ -13,6 +13,8 @@ class kandra::prometheus::process {
version => $version,
url => "https://github.com/ncabatoff/process-exporter/releases/download/v${version}/process-exporter-${version}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "process-exporter-${version}.linux-${zulip::common::goarch}",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
kandra::firewall_allow { 'process_exporter': port => '9256' }
@ -29,7 +31,7 @@ class kandra::prometheus::process {
require => [
User[zulip],
Package[supervisor],
Zulip::External_Dep['process_exporter'],
File[$bin],
File[$conf],
],
owner => 'root',

View File

@ -12,6 +12,8 @@ class kandra::prometheus::redis {
version => $version,
url => "https://github.com/oliver006/redis_exporter/releases/download/v${version}/redis_exporter-v${version}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "redis_exporter-v${version}.linux-${zulip::common::goarch}",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
kandra::firewall_allow { 'redis_exporter': port => '9121' }
@ -20,7 +22,7 @@ class kandra::prometheus::redis {
require => [
User[zulip],
Package[supervisor],
Zulip::External_Dep['redis_exporter'],
File[$bin],
],
owner => 'root',
group => 'root',

View File

@ -12,6 +12,8 @@ class kandra::prometheus::uwsgi {
version => $version,
url => "https://github.com/timonwong/uwsgi_exporter/releases/download/v${version}/uwsgi_exporter-${version}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "uwsgi_exporter-${version}.linux-${zulip::common::goarch}",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
kandra::firewall_allow { 'uwsgi_exporter': port => '9238' }
@ -20,7 +22,7 @@ class kandra::prometheus::uwsgi {
require => [
User[zulip],
Package[supervisor],
Zulip::External_Dep['uwsgi_exporter'],
File[$bin],
],
owner => 'root',
group => 'root',

View File

@ -14,5 +14,7 @@ class kandra::vector {
version => $version,
url => "https://packages.timber.io/vector/${version}/vector-${version}-${arch}-unknown-linux-gnu.tar.gz",
tarball_prefix => "vector-${arch}-unknown-linux-gnu",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
}

View File

@ -15,6 +15,8 @@ class zulip::camo (String $listen_address = '0.0.0.0') {
version => $version,
url => "https://github.com/cactus/go-camo/releases/download/v${version}/go-camo-${version}.go${goversion}.linux-${zulip::common::goarch}.tar.gz",
tarball_prefix => "go-camo-${version}",
bin => [$bin],
cleanup_after => [Service[supervisor]],
}
# We would like to not waste resources by going through Smokescreen,
@ -45,7 +47,7 @@ class zulip::camo (String $listen_address = '0.0.0.0') {
require => [
Package['camo'],
Package[supervisor],
Zulip::External_Dep['go-camo'],
File[$bin],
File['/usr/local/bin/secret-env-wrapper'],
],
owner => 'root',

View File

@ -4,6 +4,8 @@ define zulip::external_dep(
String $tarball_prefix = '',
String $sha256 = '',
String $mode = '0755',
Array[String] $bin = [],
Array[Type[Resource]] $cleanup_after = [],
) {
$arch = $facts['os']['architecture']
if $sha256 == '' {
@ -28,11 +30,13 @@ define zulip::external_dep(
url => $url,
sha256 => $sha256_filled,
install_to => $path,
before => File[$path],
notify => Exec["Cleanup ${title}"],
}
file { $path:
ensure => file,
mode => $mode,
ensure => file,
require => Zulip::Sha256_File_To[$title],
before => Exec["Cleanup ${title}"],
mode => $mode,
}
} else {
zulip::sha256_tarball_to { $title:
@ -40,19 +44,26 @@ define zulip::external_dep(
sha256 => $sha256_filled,
install_from => $tarball_prefix,
install_to => $path,
before => File[$path],
notify => Exec["Cleanup ${title}"],
}
file { $path:
ensure => present,
ensure => present,
require => Zulip::Sha256_Tarball_To[$title],
before => Exec["Cleanup ${title}"],
}
file { $bin:
ensure => file,
require => [File[$path], Zulip::Sha256_Tarball_To[$title]],
before => Exec["Cleanup ${title}"],
mode => $mode,
}
}
tidy { "/srv/zulip-${title}-*":
path => '/srv/',
recurse => 1,
rmdirs => true,
matches => "zulip-${title}-*",
require => File[$path],
exec { "Cleanup ${title}":
refreshonly => true,
provider => shell,
onlyif => "ls -d /srv/zulip-${title}-* | grep -xv '${path}'",
command => "ls -d /srv/zulip-${title}-* | grep -xv '${path}' | xargs rm -r",
require => $cleanup_after,
}
}

View File

@ -23,17 +23,17 @@ class zulip::smokescreen {
Zulip::External_Dep['smokescreen-src'],
],
}
# This resource exists purely so it doesn't get tidied; it is
# created by the 'compile smokescreen' step.
# This resource is created by the 'compile smokescreen' step.
file { $bin:
ensure => file,
require => Exec['compile smokescreen'],
}
tidy { '/usr/local/bin/smokescreen-*':
path => '/usr/local/bin',
recurse => 1,
matches => 'smokescreen-*',
require => Exec['compile smokescreen'],
exec { 'Cleanup smokescreen':
refreshonly => true,
provider => shell,
onlyif => "ls /usr/local/bin/smokescreen-* | grep -xv '${bin}'",
command => "ls /usr/local/bin/smokescreen-* | grep -xv '${bin}' | xargs rm -r",
require => [File[$bin], Service[supervisor]],
}
$listen_address = zulipconf('http_proxy', 'listen_address', '127.0.0.1')

View File

@ -19,7 +19,8 @@ class zulip::wal_g {
file { '/usr/local/bin/wal-g':
ensure => link,
target => $bin,
require => Zulip::External_Dep['wal-g'],
require => File[$bin],
before => Exec['Cleanup wal-g'],
}
# We used to install versions into /usr/local/bin/wal-g-VERSION,
# until we moved to using Zulip::External_Dep which places them in