Skip to content

The file resource’s 'staging_location' attribute should prevent unnecessary refreshes/changes when the 'source' is an HTTP(S) URI #9553

Open
@loomylabs

Description

@loomylabs

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions