Description
Use Case
If the HTTP(S) server response lacks a checksum, Puppet uses the Last-Modified (mtime) header to determine whether a file has changed. Unfortunately, this method isn't very reliable for detecting changes, as some web servers update the mtime even when the file content remains unchanged. This behavior can lead to problems in specific use cases.
In this example, I use the public key of the Eclipse Temurin repository to demonstrate the problematic behavior:
# The 'mtime' of this file changes constantly, but the content stays the same.
file { '/root/example_file':
source => 'https://packages.adoptium.net/artifactory/api/gpg/key/public',
notify => Exec['change_detector'],
}
# This resource receives a refresh every run.
exec { 'change_detector':
path => $facts['path'],
command => 'echo "I have been notified!"',
refreshonly => true,
}
Imagine the file resource is notifying a service instead of an exec, this would cause the service to restart on every Puppet run.
Furthermore, these unnecessary file changes on every run clutter the logs.
Describe the Solution You Would Like
When a file resource includes both a 'staging_location' and a 'source' attribute with an HTTP(S) URI, Puppet should download the file to the specified 'staging_location' directory and perform a checksum comparison against the destination file to determine whether a replacement and refresh are needed. This allows Puppet to rely on an actual checksum, rather than mtime, to determine whether a change has occurred.
Describe Alternatives You've Considered
It’s possible to circumvent the unnecessary refreshes as follows:
# Workaround
file { '/root/.example_file.tmp':
source => 'https://packages.adoptium.net/artifactory/api/gpg/key/public',
}
# Notifications are only sent when '/root/.example_file.tmp' and '/root/example_file' differ.
file { '/root/example_file':
source => '/root/.example_file.tmp',
notify => Exec['change_detector'],
}
exec { 'change_detector':
path => $facts['path'],
command => 'echo "I have been notified!"',
refreshonly => true,
}
The unnecessary file changes cannot be avoided, the workaround above only redirects these changes to a resource without a 'notify' attribute.
Additional Context
none