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

## [4.1.0] - 2020-08-19

### Summary
Add support for Linux Mint 20, and add puppet agent run plan to run the agent against remote
targets.

### Features

- Support for Linux Mint 20, LDME 4 ([#500](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/500))
- ([MODULES-10739](https://tickets.puppetlabs.com/browse/MODULES-10739)) add task support for
puppet7-nightly ([#501](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/501))
- ([MODULES-10768](https://tickets.puppetlabs.com/browse/MODULES-10768)) Add task and plan for
running the Puppet agent ([#503](https://github.com/puppetlabs/puppetlabs-puppet_agent/pull/503))

### Bug fixes

- ([MODULES-10713](https://tickets.puppetlabs.com/browse/MODULES-10713)) Fix agent upgrade on Solaris 11 ([#499](https://github.com/puppetlabs/puppetlabs-puppet_agent/pulls/499))

## [4.0.0] - 2020-06-15

### Summary
Expand Down
5 changes: 4 additions & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# default to night-s-watch
* @puppetlabs/night-s-watch

# tasks
/tasks @puppetlabs/bolt
/task_spec @puppetlabs/bolt
/task_spec @puppetlabs/bolt
27 changes: 27 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
- [`install_options`](#install_options)
- [`msi_move_locked_files`](#msi_move_locked_files)
- [`wait_for_pxp_agent_exit`](#wait_for_pxp_agent_exit)
- [Plans](#plans)
- [`puppet_agent::run`](#puppet_agentrun)
- [Tasks](#tasks)
- [`puppet_agent::version`](#puppet_agentversion)
- [`puppet_agent::install`](#puppet_agentinstall)
Expand Down Expand Up @@ -299,6 +301,31 @@ This is only applicable for Windows operating systems and pertains to /files/ins
wait_for_pxp_agent_exit => 480000
```

### Plans

#### `puppet_agent::run`

Starts a Puppet agent run on the specified targets.

**Parameters**

- `targets`: A list of targets to start the Puppet agent run on.

**Return value**

Returns a `ResultSet` object. Targets that do not have an agent installed will have a failing
`Result` object. For targets that have an agent installed and successfully ran the agent,
the `Result` object will include the output of the agent run, the detailed exit code, and the
contents of the run report.

```
{
"_output": <output>,
"exitcode": <exitcode>,
"report": <report>
}
```

### Tasks

#### `puppet_agent::version`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ 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
5 changes: 3 additions & 2 deletions manifests/install.pp
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,14 @@
$_source = undef
}
}
$_aio_package_version = $package_version.match(/^\d+\.\d+\.\d+(\.\d+)?/)[0]
package { $::puppet_agent::package_name:
ensure => $_package_version,
install_options => $_install_options,
provider => $_provider,
source => $_source,
notify => Puppet_agent_end_run[$_package_version],
notify => Puppet_agent_end_run[$_aio_package_version],
}
puppet_agent_end_run { $_package_version : }
puppet_agent_end_run { $_aio_package_version : }
}
}
5 changes: 3 additions & 2 deletions manifests/install/solaris.pp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@
}
}
} else {
$_aio_package_version = $package_version.match(/^\d+\.\d+\.\d+(\.\d+)?/)[0]
package { $::puppet_agent::package_name:
ensure => $package_version,
install_options => $install_options,
notify => Puppet_agent_end_run[$package_version],
notify => Puppet_agent_end_run[$_aio_package_version],
}
puppet_agent_end_run { $package_version : }
puppet_agent_end_run { $_aio_package_version : }
}
}
2 changes: 1 addition & 1 deletion metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-puppet_agent",
"version": "4.0.0",
"version": "4.1.0",
"author": "puppetlabs",
"summary": "Upgrades All-In-One Puppet Agents",
"license": "Apache-2.0",
Expand Down
70 changes: 70 additions & 0 deletions plans/run.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Starts a Puppet agent run on the specified targets.
# Note: This plan may cause issues when run in Puppet Enterprise.
# @param targets The targets to start a Puppet agent run on.
plan puppet_agent::run (
TargetSpec $targets
) {
# Check which targets have the agent installed by checking
# the version of the agent. No point in trying to run the
# agent if it's not installed.
$version_results = run_task(
'puppet_agent::version',
$targets,
'Check for Puppet agent',
'_catch_errors' => true
)

# Create results with more descriptive error messages for any targets
# where the version task failed.
$version_error_results = $version_results.error_set.map |$result| {
$err = {
'_error' => {
'msg' => "The task puppet_agent::version failed: ${result.error.message}. Unable to determine if the Puppet agent is installed.",
'kind' => 'puppet_agent/agent-version-error',
'details' => {}
}
}

Result.new($result.target, $err)
}

# Filter targets by those that have an agent installed and
# those that don't. The puppet_agent::version task will return
# version:null for any targets that don't have an agent.
$agentless_results = $version_results.ok_set.filter_set |$result| {
$result['version'] == undef
}

$agent_results = $version_results.ok_set.filter_set |$result| {
$result['version'] != undef
}

# Create fail results for agentless targets.
$agentless_error_results = $agentless_results.map |$result| {
$err = {
'_error' => {
'msg' => 'Puppet agent is not installed on the target. Run the puppet_agent::install task on these targets to install the Puppet agent.',
'kind' => 'puppet_agent/agent-not-installed',
'details' => {}
}
}

Result.new($result.target, $err)
}

# Run the agent on all targets that have the agent installed.
$run_results = run_task(
'puppet_agent::run',
$agent_results.targets,
'Run Puppet agent',
'_catch_errors' => true
)

# Merge all of the results into a single ResultSet so each
# target has a result.
return ResultSet.new(
$version_error_results +
$agentless_error_results +
$run_results.results
)
}
3 changes: 2 additions & 1 deletion spec/classes/puppet_agent_osfamily_solaris_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def install_script(ver, arch)
:clientcert => 'foo.example.vm',
:env_temp_variable => '/tmp',
:puppet_agent_pid => 42,
:aio_agent_version => package_version,
:aio_agent_version => '1.10.100.90',
}
# Strips out strings in the version string on Solaris 11,
# because pkg doesn't accept strings in version numbers. This
Expand Down Expand Up @@ -148,6 +148,7 @@ def install_script(ver, arch)
it { should compile.with_all_deps }
it { is_expected.to contain_file('/opt/puppetlabs') }
it { is_expected.to contain_file('/opt/puppetlabs/packages') }
it { is_expected.to contain_puppet_agent_end_run(facts[:aio_agent_version]) }
it do
is_expected.to contain_file("/opt/puppetlabs/packages/puppet-agent@#{sol11_package_version},5.11-1.i386.p5p").with({
'ensure' => 'present',
Expand Down
14 changes: 14 additions & 0 deletions spec/classes/puppet_agent_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ def global_facts(facts, os)
global_facts(facts, os)
end

# Windows, Solaris 10 and OS X use scripts for upgrading agents
# We test Solaris 11 in its own class
if os !~ %r{windows|solaris|darwin}
context 'when using a dev build' do
let(:params) { { :package_version => '5.2.0.100.g23e53f2' } }
it { is_expected.to contain_puppet_agent_end_run('5.2.0.100') }
end

context 'when using a release build' do
let(:params) { { :package_version => '5.2.0' } }
it { is_expected.to contain_puppet_agent_end_run('5.2.0') }
end
end

context 'when the aio_agent_version fact is undefined' do
let(:facts) do
global_facts(facts, os).merge(aio_agent_version: nil)
Expand Down
31 changes: 29 additions & 2 deletions task_spec/spec/acceptance/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def target_platform
run_command('/opt/puppetlabs/bin/puppet resource service puppet', 'target')
end
output = service[0]['result']['stdout']
expect(output).to include("ensure => 'stopped'")
expect(output).to match(%r{ensure\s+=> 'stopped'})

# Try to upgrade with no specific version given in parameter
# Expect nothing to happen and receive a message regarding this
Expand Down Expand Up @@ -116,7 +116,7 @@ def target_platform
# Manually stop the puppet agent service
service = run_command('c:/"program files"/"puppet labs"/puppet/bin/puppet resource service puppet ensure=stopped', 'target')
output = service[0]['result']['stdout']
expect(output).to include("ensure => 'stopped'")
expect(output).to match(%r{ensure\s+=> 'stopped'})
end

# Succesfully upgrade from puppet5 to puppet6
Expand All @@ -143,5 +143,32 @@ def target_platform
expect(res).to include('status' => 'success')
expect(res['result']['_output']).to match(%r{Puppet Agent #{installed_version} detected. Nothing to do.})
end

if target_platform !~ /sles-11/
# Puppet Agent can't be upgraded on Windows nodes while 'puppet agent' service or 'pxp-agent' service are running
if target_platform =~ /win/
# Manually stop the puppet agent service
service = run_command('c:/"program files"/"puppet labs"/puppet/bin/puppet resource service puppet ensure=stopped', 'target')
output = service[0]['result']['stdout']
expect(output).to match(%r{ensure\s+=> 'stopped'})
end

#Upgrade from puppet6 to puppet7 nightly
results = run_task('puppet_agent::install', 'target', { 'collection' => 'puppet7-nightly', 'version' => 'latest' })
results.each do |res|
expect(res).to include('status' => 'success')
end

# Verify that it upgraded
installed_version = nil
results = run_task('puppet_agent::version', 'target', {})
results.each do |res|
expect(res).to include('status' => 'success')
installed_version = res['result']['version']
expect(installed_version).not_to match(%r{^6\.\d+\.\d+})
expect(installed_version).to match(%r{^7\.\d+\.\d+})
expect(res['result']['source']).to be
end
end
end
end
2 changes: 1 addition & 1 deletion tasks/install.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
"collection": {
"description": "The Puppet collection to install from (defaults to puppet, which maps to the latest collection released)",
"type": "Optional[Enum[puppet5, puppet6, puppet, puppet5-nightly, puppet6-nightly, puppet-nightly]]"
"type": "Optional[Enum[puppet5, puppet6, puppet, puppet5-nightly, puppet6-nightly, puppet7-nightly, puppet-nightly]]"
},
"yum_source": {
"description": "The source location to find yum repos (defaults to yum.puppet.com)",
Expand Down
2 changes: 1 addition & 1 deletion tasks/install_powershell.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"collection": {
"description": "The Puppet collection to install from (defaults to puppet, which maps to the latest collection released)",
"type": "Optional[Enum[puppet5, puppet6, puppet, puppet5-nightly, puppet6-nightly, puppet-nightly]]"
"type": "Optional[Enum[puppet5, puppet6, puppet, puppet5-nightly, puppet6-nightly, puppet7-nightly, puppet-nightly]]"
},
"yum_source": {
"description": "The source location to find yum repos (defaults to yum.puppet.com)",
Expand Down
2 changes: 1 addition & 1 deletion tasks/install_shell.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"collection": {
"description": "The Puppet collection to install from (defaults to puppet, which maps to the latest collection released)",
"type": "Optional[Enum[puppet5, puppet6, puppet, puppet5-nightly, puppet6-nightly, puppet-nightly]]"
"type": "Optional[Enum[puppet5, puppet6, puppet, puppet5-nightly, puppet6-nightly, puppet7-nightly, puppet-nightly]]"
},
"yum_source": {
"description": "The source location to find yum repos (defaults to yum.puppet.com)",
Expand Down
8 changes: 7 additions & 1 deletion tasks/install_shell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ fi
if [ -n "$PT_mac_source" ]; then
mac_source=$PT_mac_source
else
mac_source='http://downloads.puppet.com'
if [ "$nightly" = true ]; then
mac_source='http://nightlies.puppet.com/downloads'
else
mac_source='http://downloads.puppet.com'
fi
fi

# Track to handle puppet5 to puppet6
Expand Down Expand Up @@ -550,6 +554,8 @@ case $platform in
info "Mint platform! Lets get you a DEB..."
case $major_version in
"3") deb_codename="stretch";;
"4") deb_codename="buster";;
"20") deb_codename="focal";;
"19") deb_codename="bionic";;
"18") deb_codename="xenial";;
"17") deb_codename="trusty";;
Expand Down
5 changes: 5 additions & 0 deletions tasks/run.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"description": "Run the Puppet agent. This task may cause problems if run in Puppet Enterprise.",
"parameters": {},
"private": true
}
Loading