13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [4.0.0] - 2020-06-15

### Summary
Stop agent run after upgrade. Fix `absolute_source` on RPM platforms. Update `puppetlabs-facts` dependency. Do not allow install task to upgrade Windows agents if services are still running.

### Features
- ([MODULES-10673](https://tickets.puppetlabs.com/browse/MODULES-10673)) Update dependency for puppetlabs-facts ([#495](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/495))

### Bug fixes
- ([MODULES-10653](https://tickets.puppetlabs.com/browse/MODULES-10653)) Failed to upgrade agent using puppet task ([#494](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/494))
- ([MODULES-10655](https://tickets.puppetlabs.com/browse/MODULES-10655)) Fix up/downgrade of agent to specified version ([#488](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/488))
- ([MODULES-10666](https://tickets.puppetlabs.com/browse/MODULES-10666)) Stop agent run after an upgrade ([#496](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/496))

## [3.2.0] - 2020-05-13

### Summary
Expand Down
2 changes: 2 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ There are a few known issues on Windows platforms:

* MSI installation failures do not produce any error. If the install fails, puppet_agent continues to be applied to the agent. If this happens, you'll need to examine the MSI log file to determine the failure's cause. You can find the location of the log file in the debug output from either a puppet apply or an agent run; the log file name follows the pattern `puppet-<timestamp>-installer.log`.

* Upgrading on most \*NIX platforms (Linux, AIX, Solaris 11) will end the run after the puppet-agent upgrade finishes. This is to avoid unexpected behavior if already loaded Ruby code happens to interact with newer code that came with the upgrade, or viceversa. If run as a daemon, Puppet will automatically start a new agent run after the upgrade finishes.

Specifically in the 1.2.0 Release:
* For Windows, you must trigger an agent run after upgrading so that Puppet can create the necessary directory structures.

Expand Down
4 changes: 2 additions & 2 deletions acceptance/tests/test_upgrade_pc1_to_puppet5.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
manifest = <<-PP
node default {
class { puppet_agent:
package_version => '5.5.10',
package_version => '5.5.16',
collection => 'puppet5'
}
}
Expand All @@ -36,7 +36,7 @@ class { puppet_agent:
agents_only.each do |agent|
start_puppet_service_and_wait_for_puppet_run(agent)
wait_for_installation_pid(agent)
assert_agent_version_on(agent, '5.5.10')
assert_agent_version_on(agent, '5.5.16')
end
end
end
4 changes: 2 additions & 2 deletions acceptance/tests/test_upgrade_puppet5_to_puppet6.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
manifest = <<-PP
node default {
class { puppet_agent:
package_version => '6.0.0',
package_version => '6.15.0',
collection => 'puppet6'
}
}
Expand All @@ -36,7 +36,7 @@ class { puppet_agent:
agents_only.each do |agent|
start_puppet_service_and_wait_for_puppet_run(agent)
wait_for_installation_pid(agent)
assert_agent_version_on(agent, '6.0.0')
assert_agent_version_on(agent, '6.15.0')
end
end
end
35 changes: 35 additions & 0 deletions lib/puppet/provider/puppet_agent_end_run/puppet_agent_end_run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Puppet::Type.type(:puppet_agent_end_run).provide :puppet_agent_end_run do
def end_run
false
end

def stop
if needs_upgrade?
run_mode = Puppet.run_mode.name

# Handle CLI runs of `puppet agent` and `apply`
if Puppet[:onetime] || run_mode != :agent
Puppet.notice("Stopping run after puppet-agent upgrade. Run puppet agent -t or apply your manifest again to finish the transaction.")
end

Puppet::Application.stop!

# Sending the HUP signal to the daemon causes it to restart and finish applying the catalog
if Puppet[:daemonize] && run_mode == :agent
at_exit { Process.kill(:HUP, Process.pid) }
end
end
end

private

def needs_upgrade?
current_version = Facter.value('aio_agent_version')
desired_version = @resource.name

# Ensure version has no git SHA or Debian codenames
desired_version = Gem::Version.new(desired_version).release.version

Puppet::Util::Package.versioncmp(desired_version, current_version) != 0
end
end
30 changes: 30 additions & 0 deletions lib/puppet/type/puppet_agent_end_run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'puppet/property/boolean'

Puppet::Type.newtype(:puppet_agent_end_run) do
@doc = <<-DOC
Stops the current Puppet run if a puppet-agent upgrade was
performed. Used on platforms that manage the Puppet Agent upgrade with
a package resource, as resources evaluated after an upgrade might
cause unexpected behavior due to a mix of old and new Ruby code being
loaded in memory.
Platforms that shell out to external scripts for upgrading (Windows,
macOS, and Solaris 10) do not need to use this type.
DOC

newproperty(:end_run, :boolean => true, parent: Puppet::Property::Boolean) do
desc "Stops the current puppet run"

def insync?(is)
provider.stop
true
end

defaultto { true }
end

newparam(:name) do
desc "The desired puppet-agent version"
isnamevar
end
end
4 changes: 3 additions & 1 deletion manifests/install.pp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
$_install_options = $install_options
if $::puppet_agent::absolute_source {
# absolute_source means we use rpm on EL/suse based platforms
$_package_version = 'present'
$_package_version = $package_version
$_provider = 'rpm'
# The source package should have been downloaded by puppet_agent::prepare::package to the local_packages_dir
$_source = "${::puppet_agent::params::local_packages_dir}/${::puppet_agent::prepare::package::package_file_name}"
Expand All @@ -91,6 +91,8 @@
install_options => $_install_options,
provider => $_provider,
source => $_source,
notify => Puppet_agent_end_run[$_package_version],
}
puppet_agent_end_run { $_package_version : }
}
}
2 changes: 2 additions & 0 deletions manifests/install/solaris.pp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
package { $::puppet_agent::package_name:
ensure => $package_version,
install_options => $install_options,
notify => Puppet_agent_end_run[$package_version],
}
puppet_agent_end_run { $package_version : }
}
}
4 changes: 2 additions & 2 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-puppet_agent",
"version": "3.2.0",
"version": "4.0.0",
"author": "puppetlabs",
"summary": "Upgrades All-In-One Puppet Agents",
"license": "Apache-2.0",
Expand Down Expand Up @@ -125,6 +125,6 @@
{"name":"puppetlabs-stdlib","version_requirement":">= 5.1.0 < 7.0.0"},
{"name":"puppetlabs-inifile","version_requirement":">= 2.4.0 < 5.0.0"},
{"name":"puppetlabs-apt","version_requirement":">= 7.0.1 < 8.0.0"},
{"name":"puppetlabs-facts","version_requirement":">= 0.5.0 < 1.0.0"}
{"name":"puppetlabs-facts","version_requirement":">= 0.5.0 < 2.0.0"}
]
}
49 changes: 44 additions & 5 deletions spec/acceptance/class_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@

it 'should work idempotently with no errors' do
pp = <<-EOS
class { 'puppet_agent': package_version => '5.5.14', collection => 'puppet5' }
class { 'puppet_agent': package_version => '5.5.16', collection => 'puppet5' }
EOS

# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
wait_for_finish_on default
configure_agent_on default
apply_manifest(pp, :catch_changes => true)
wait_for_finish_on default
# Run three times to ensure idempotency if upgrading with the package resource (MODULES-10666)
unless default['platform'] =~ /solaris-10|aix|osx|windows/i
apply_manifest(pp, :expect_changes => true)
wait_for_finish_on default
end
apply_manifest(pp, :catch_changes => true)
end

describe package(package_name(default)) do
Expand Down Expand Up @@ -137,7 +140,7 @@ class { 'puppet_agent': service_names => [] }
context 'with mcollective configured' do
before(:all) {
setup_puppet_on default, :mcollective => true, :agent => true
manifest = 'class { "puppet_agent": package_version => "5.5.14", collection => "puppet5", service_names => ["mcollective"] }'
manifest = 'class { "puppet_agent": package_version => "5.5.16", collection => "puppet5", service_names => ["mcollective"] }'
pp = "file { '#{master.puppet['codedir']}/environments/production/manifests/site.pp': ensure => file, content => '#{manifest}' }"
apply_manifest_on(master, pp, :catch_failures => true)
}
Expand Down Expand Up @@ -183,5 +186,41 @@ class { 'puppet_agent': collection => "puppet5", service_names => ["mcollective
end
end
end

unless default['platform'] =~ /solaris-10|aix|osx|windows/i
context 'on platforms managed with the package resource' do
before(:all) { setup_puppet_on default }

after (:all) do
on default, 'rm -f /tmp/a'
teardown_puppet_on default
end

let(:manifest) do <<-EOS
class { 'puppet_agent': package_version => '5.5.16', collection => 'puppet5', before => File['/tmp/a'] }
file { '/tmp/a': ensure => 'present' }
EOS
end

it 'upgrades the agent on the first run' do
# First run should upgrade the agent
apply_manifest(manifest, :expect_changes => true)
configure_agent_on default
expect(package(package_name(default))).to be_installed
expect(file('/tmp/a')).not_to exist
end

it 'evaluates remanining resources on the second run' do
# Second run should apply the file resource
apply_manifest(manifest, :expect_changes => true)
expect(file('/tmp/a')).to exist
end

it 'does nothing on future runs' do
# Third run should not do anything
apply_manifest(manifest, :catch_changes => true)
end
end
end
end
end
33 changes: 33 additions & 0 deletions spec/classes/puppet_agent_osfamily_redhat_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -237,5 +237,38 @@

it { is_expected.to contain_class("puppet_agent::osfamily::redhat") }
end

context 'when using absolute_source' do
let(:params) {
{
:package_version => '6.12.0',
:absolute_source => "http://just-some-download/url:90/puppet-agent-6.12.0.rpm"
}
}

it { is_expected.to contain_class('Puppet_agent::Prepare::Package')
.with('source' => 'http://just-some-download/url:90/puppet-agent-6.12.0.rpm')
}

it { is_expected.to contain_file('/opt/puppetlabs/packages/puppet-agent-6.12.0.rpm')
.with('path' => '/opt/puppetlabs/packages/puppet-agent-6.12.0.rpm')
.with('ensure' => 'present')
.with('owner' => '0')
.with('group' => '0')
.with('mode' => '0644')
.with('source' => 'http://just-some-download/url:90/puppet-agent-6.12.0.rpm')
.that_requires('File[/opt/puppetlabs/packages]')
.with('checksum' => 'sha256lite')
}

it { is_expected.to contain_package('puppet-agent')
.with('ensure' => '6.12.0')
.with('install_options' => '[]')
.with('provider' => 'rpm')
.with('source' => '/opt/puppetlabs/packages/puppet-agent-6.12.0.rpm')
}

end

end
end
4 changes: 2 additions & 2 deletions spec/spec_helper_acceptance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def install_modules_on(host)
master['puppetservice'] = 'puppetserver'
master['puppetserver-confdir'] = '/etc/puppetlabs/puppetserver/conf.d'
master['type'] = 'aio'
install_puppet_agent_on master, {:version => ENV['PUPPET_CLIENT_VERSION'] || "5.5.10", :puppet_collection => 'puppet5'}
install_puppet_agent_on master, {:version => ENV['PUPPET_CLIENT_VERSION'] || "5.5.14", :puppet_collection => 'puppet5'}

install_modules_on master

Expand Down Expand Up @@ -127,7 +127,7 @@ def setup_puppet_on(host, opts = {})

puts "Setup aio puppet on #{host}"
configure_type_defaults_on host
install_puppet_agent_on host, {:version => ENV['PUPPET_CLIENT_VERSION'] || '5.5.10', :puppet_collection => 'puppet5'}
install_puppet_agent_on host, {:version => ENV['PUPPET_CLIENT_VERSION'] || '5.5.14', :puppet_collection => 'puppet5'}

puppet_opts = agent_opts(master.to_s)
if host['platform'] =~ /windows/i
Expand Down
Loading