Skip to content

Commit

Permalink
[windows] Add option to support EXE Agent installer (#410)
Browse files Browse the repository at this point in the history
* The EXE installer handles per-user to per-machine upgrades
gracefully, including edges cases that the present cookbook can't
reasonably handle on its own.
  For this reason, we add the option to use the exe installer when needed
(i.e. for upgrades from Agent <= 5.10.1 to Agent >= 5.12.0).
* The URL to the latest installer changes in 5.12.0 from `ddagent-cli`
to `ddagent-cli-latest` so that unattended upgrades don't make chef
runs fail.
  Reflect this here. The new URLs work only since 5.12.0, so this change
should only be released once the 5.12.0 installers (msi and exe) are
generally available at these URLs.
* Made some changes on the package removal to handle `windows` >= 1.39
more gracefully. Updated the spec tests assuming they run on Chef >= 12.6.
  This should be removed (and the whole recipe should be cleaned up)
when we stop supporting Chef < 12.6 on Windows.
* Added related documentation.
olivielpeau authored Mar 23, 2017
1 parent 05ba57d commit 3f6435b
Showing 5 changed files with 97 additions and 20 deletions.
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -66,10 +66,20 @@ dd-agent
--------
Installs the Datadog agent on the target system, sets the API key, and start the service to report on the local system metrics

**Note for Windows**: With Chef >= 12.6 _and_ the `windows` cookbook >= 1.39.0, Agent upgrades are known to fail.
For Chef>=12.6 users on Windows, we recommend pinning the `windows` cookbook to a lower version (`~> 1.38.0` for instance).
If that's not an option, a known workaround is to use the `remove-dd-agent` recipe (since the `2.5.0` version of the present cookbook) to uninstall the Agent
prior to any Agent upgrade.
**Notes for Windows**:

* With Chef >= 12.6 _and_ the `windows` cookbook >= 1.39.0, Agent upgrades are known to fail.
For Chef>=12.6 users on Windows, we recommend pinning the `windows` cookbook to a lower version (`~> 1.38.0` for instance).

If that's not an option, a known workaround is to use the `remove-dd-agent` recipe (since the `2.5.0` version of the present cookbook) to uninstall the Agent
prior to any Agent upgrade.

* Because of changes in the Windows Agent packaging and install in version 5.12.0, when upgrading the Agent from versions <= 5.10.1 to versions >= 5.12.0,
please set the `windows_agent_use_exe` attribute to `true`.

Once the upgrade is complete, you can leave the attribute to its default value (`false`).

For more information on these Windows packaging changes, see the related [docs on the dd-agent wiki](https://github.com/DataDog/dd-agent/wiki/Windows-Agent-Installation).

dd-handler
----------
7 changes: 7 additions & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
@@ -111,6 +111,13 @@
# Expected checksum to validate correct agent installer is downloaded (Windows only)
default['datadog']['windows_agent_checksum'] = nil

# Set to `true` to use the EXE installer on Windows, recommended to gracefully handle upgrades from per-user
# to per-machine installs on most environments. We recommend setting this option to `true` for Agent upgrades from
# versions <= 5.10.1 to versions >= 5.12.0.
# The EXE installer exists since Agent release 5.12.0
# If you're already using version >= 5.12.0 of the Agent, leave this to false.
default['datadog']['windows_agent_use_exe'] = false

# Values that differ on Windows
# The location of the config folder (containing conf.d)
# The name of the dd agent service
51 changes: 44 additions & 7 deletions recipes/_install-windows.rb
Original file line number Diff line number Diff line change
@@ -24,29 +24,66 @@
node['datadog']['agent_version']
end

# If no version is specified, select the latest package
dd_agent_msi = dd_agent_version ? "ddagent-cli-#{dd_agent_version}.msi" : 'ddagent-cli.msi'
temp_file = ::File.join(Chef::Config[:file_cache_path], 'ddagent-cli.msi')
# If no version is specified, select the latest package.
# The latest package basename is `ddagent-cli-latest` since Agent version 5.12.0
dd_agent_installer_basename = dd_agent_version ? "ddagent-cli-#{dd_agent_version}" : 'ddagent-cli-latest'
temp_file_basename = ::File.join(Chef::Config[:file_cache_path], 'ddagent-cli')

if node['datadog']['windows_agent_use_exe']
dd_agent_installer = "#{dd_agent_installer_basename}.exe"
temp_file = "#{temp_file_basename}.exe"
installer_type = :custom
install_options = '/q'
else
dd_agent_installer = "#{dd_agent_installer_basename}.msi"
temp_file = "#{temp_file_basename}.msi"
installer_type = :msi
# Agent >= 5.12.0 installs per-machine by default, but specifying ALLUSERS=1 shouldn't affect the install
install_options = '/norestart ALLUSERS=1'
end

# Use a separate resource without a `source` so that it looks in the Registry to find the MSI to use
# for the package removal
# On Chef >= 12.6, we have to use the `package` resource instead of `windows_package` to allow not specifying a source
# (this is related to the way the windows cookbook changes the provider of `windows_package` depending on the
# version of Chef, and to improvements on the `package` resource made in Chef 12.6)
# FIXME: when we remove Chef < 12.6 support on Windows, which should allow using core resources only
use_windows_package_resource = Gem::Version.new(Chef::VERSION) < Gem::Version.new('12.6.0')
if use_windows_package_resource
windows_package 'Datadog Agent removal' do
package_name 'Datadog Agent'
action :nothing
end
else
package 'Datadog Agent removal' do
package_name 'Datadog Agent'
action :nothing
end
end

package_retries = node['datadog']['agent_package_retries']
package_retry_delay = node['datadog']['agent_package_retry_delay']

# Download the installer to a temp location
remote_file temp_file do
source node['datadog']['windows_agent_url'] + dd_agent_msi
source node['datadog']['windows_agent_url'] + dd_agent_installer
checksum node['datadog']['windows_agent_checksum'] if node['datadog']['windows_agent_checksum']
retries package_retries unless package_retries.nil?
retry_delay package_retry_delay unless package_retry_delay.nil?
# As of v1.37, the windows cookbook doesn't upgrade the package if a newer version is downloaded
# As a workaround uninstall the package first if a new MSI is downloaded
notifies :remove, 'windows_package[Datadog Agent]', :immediately
if use_windows_package_resource
notifies :remove, 'windows_package[Datadog Agent removal]', :immediately
else
notifies :remove, 'package[Datadog Agent removal]', :immediately
end
end

# Install the package
windows_package 'Datadog Agent' do # ~FC009
source temp_file
installer_type :msi
options '/norestart ALLUSERS=1'
installer_type installer_type
options install_options
action :install
success_codes [0, 3010]
end
26 changes: 22 additions & 4 deletions spec/dd-agent_spec.rb
Original file line number Diff line number Diff line change
@@ -144,7 +144,7 @@ def set_env_var(name, value)
end

context 'on Windows' do
cached(:chef_run) do
cached(:chef_run) do
set_env_var('ProgramData', 'C:\ProgramData')
ChefSpec::SoloRunner.new(
:platform => 'windows',
@@ -155,7 +155,25 @@ def set_env_var(name, value)
end.converge described_recipe
end

it_behaves_like 'windows Datadog Agent'
it_behaves_like 'windows Datadog Agent', :msi
end

context 'on Windows with EXE installer' do
cached(:chef_run) do
set_env_var('ProgramData', 'C:\ProgramData')
ChefSpec::SoloRunner.new(
:platform => 'windows',
:version => '2012R2',
:file_cache_path => 'C:/chef/cache'
) do |node|
node.set['datadog'] = {
'api_key' => 'somethingnotnil',
'windows_agent_use_exe' => true
}
end.converge described_recipe
end

it_behaves_like 'windows Datadog Agent', :exe
end
end

@@ -231,7 +249,7 @@ def set_env_var(name, value)

temp_file = ::File.join('C:/chef/cache', 'ddagent-cli.msi')

it_behaves_like 'windows Datadog Agent'
it_behaves_like 'windows Datadog Agent', :msi
# remote_file source gets converted to an array, so we need to do
# some tricky things to be able to regex against it
# Relevant: http://stackoverflow.com/a/12325983
@@ -286,7 +304,7 @@ def set_env_var(name, value)

temp_file = ::File.join('C:/chef/cache', 'ddagent-cli.msi')

it_behaves_like 'windows Datadog Agent'
it_behaves_like 'windows Datadog Agent', :msi
# remote_file source gets converted to an array, so we need to do
# some tricky things to be able to regex against it
# Relevant: http://stackoverflow.com/a/12325983
15 changes: 10 additions & 5 deletions spec/shared_examples.rb
Original file line number Diff line number Diff line change
@@ -72,20 +72,25 @@
end
end

shared_examples_for 'windows Datadog Agent' do
shared_examples_for 'windows Datadog Agent' do |installer_extension|
it_behaves_like 'common windows resources'

agent_installer = 'C:/chef/cache/ddagent-cli.msi'
agent_installer = "C:/chef/cache/ddagent-cli.#{installer_extension}"

it 'downloads the remote file only if it\'s changed' do
expect(chef_run).to create_remote_file(agent_installer)
end

it 'notifies the removal of the Datadog Agent' do
expect(chef_run.remote_file(agent_installer)).to notify('windows_package[Datadog Agent]').to(:remove)
it 'doesn\'t remove existing version of the Datadog Agent by default' do
expect(chef_run.package('Datadog Agent removal')).to do_nothing
end

it 'notifies the removal of the Datadog Agent when a remote file is downloaded' do
expect(chef_run.remote_file(agent_installer)).to notify('package[Datadog Agent removal]').to(:remove)
end

it 'installs Datadog Agent' do
expect(chef_run).to install_windows_package('Datadog Agent')
installer_type = installer_extension == :msi ? :msi : :custom
expect(chef_run).to install_windows_package('Datadog Agent').with(installer_type: installer_type)
end
end

0 comments on commit 3f6435b

Please sign in to comment.