Support of agent6 beta for debianoids
Flipping the attribute 'datadog''agent6' to true installs the agent6
instead of the agent5. Switching it back to false should reverse
the operation as long as the agent 5 version is pinned.
MODIFY
attributes/default.rb
attributes/default.rb
@@ -28,6 +28,43 @@ default['datadog']['api_key'] = nil
# Set it as an attribute, or on your node `run_state` under the key `['datadog']['application_key']`
default['datadog']['application_key'] = nil
+########################################################################
+### Beta-Agent6-only attributes, experimental ###
+### These attributes are not part of the stable API of the cookbook ###
+### Subject to breaking changes between bugfix/minor versions ###
+### Only works on debianoids for now ###
+
+# Set to true to install an agent6 instead of agent5.
+# To upgrade from agent5 to agent6, you need to:
+# * set node['datadog']['agent6'] to true, and
+# * either set node['datadog']['agent6_version'] to an existing agent6 version (recommended), or
+# set node['datadog']['agent6_package_action'] to 'upgrade'
+# To downgrade from agent6 to agent5, you need to:
+# * set node['datadog']['agent6'] to false, and
+# * pin node['datadog']['agent_version'] to an existing agent5 version, and
+# * set node['datadog']['agent_allow_downgrade'] to true
+default['datadog']['agent6'] = false
+# Default of `nil` will install latest version, applies to agent6 only.
+# See documentation of `agent_version` attribute for allowed configuration format.
+default['datadog']['agent6_version'] = nil
+default['datadog']['agent6_package_action'] = 'install' # set to `upgrade` to always upgrade to latest
+
+# beta APT repo where datadog-agent v6 packages are available
+default['datadog']['agent6_aptrepo'] = 'http://apt.datadoghq.com'
+default['datadog']['agent6_aptrepo_dist'] = 'beta'
+
+# Values that differ on Windows
+# The location of the config folder (containing conf.d)
+default['datadog']['agent6_config_dir'] = '/etc/datadog-agent'
+
+# Set a key to true to make the agent6 use the v2 api on that endpoint, false otherwise.
+# Leave key value to nil to use agent6 default for that endpoint.
+# Supported keys: "series", "events", "service checks"
+default['datadog']['use_v2_api'] = {}
+
+### End of Beta-Agent6-only experimental attributes ###
+########################################################################
+
# Use this attribute to send data to additional accounts
# (agent and handler if enabled)
# The key can be anything you want, 'prod' is used there as an example
@@ -93,6 +130,8 @@ yum_protocol =
'https'
end
+# NB: if you're not using the default repos and/or distributions, make sure
+# to pin the version you're installing with node['datadog']['agent_version']
default['datadog']['installrepo'] = true
default['datadog']['aptrepo'] = 'http://apt.datadoghq.com'
default['datadog']['aptrepo_dist'] = 'stable'

MODIFY
providers/monitor.rb
providers/monitor.rb
@@ -9,7 +9,8 @@ end
action :add do
Chef::Log.debug "Adding monitoring for #{new_resource.name}"
- template ::File.join(node['datadog']['config_dir'], 'conf.d', "#{new_resource.name}.yaml") do
+ config_dir = node['datadog']['agent6'] ? node['datadog']['agent6_config_dir'] : node['datadog']['config_dir']
+ template ::File.join(config_dir, 'conf.d', "#{new_resource.name}.yaml") do
if node['platform_family'] == 'windows'
owner 'Administrators'
rights :full_control, 'Administrators'
@@ -41,7 +42,8 @@ action :add do
end
action :remove do
- confd_dir = ::File.join(node['datadog']['config_dir'], 'conf.d')
+ config_dir = node['datadog']['agent6'] ? node['datadog']['agent6_config_dir'] : node['datadog']['config_dir']
+ confd_dir = ::File.join(config_dir, 'conf.d')
Chef::Log.debug "Removing #{new_resource.name} from #{confd_dir}"
file ::File.join(confd_dir, "#{new_resource.name}.yaml") do
action :delete

ADD
recipes/_agent6_config.rb
+#
+# Cookbook Name:: datadog
+# Recipe:: _agent6_config
+#
+# Copyright 2011-2017, Datadog
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+is_windows = node['platform_family'] == 'windows'
+
+# FIXME: with the agent6, we still need the agent5 conf file in duplicate in /etc/datadog-agent/trace-agent.conf
+# and /etc/datadog-agent/process-agent.conf for the trace and process agents.
+# Remove them when these agents can read from datadog.yaml.
+trace_agent_config_file = ::File.join(node['datadog']['agent6_config_dir'], 'trace-agent.conf')
+process_agent_config_file = ::File.join(node['datadog']['agent6_config_dir'], 'process-agent.conf')
+
+template trace_agent_config_file do
+ def conf_template_vars
+ {
+ :api_keys => [Chef::Datadog.api_key(node)],
+ :dd_urls => [node['datadog']['url']]
+ }
+ end
+ variables(
+ if respond_to?(:lazy)
+ lazy { conf_template_vars }
+ else
+ conf_template_vars
+ end
+ )
+ if is_windows
+ owner 'Administrators'
+ rights :full_control, 'Administrators'
+ inherits false
+ else
+ owner 'dd-agent'
+ group 'dd-agent'
+ mode '640'
+ end
+ source 'datadog.conf.erb'
+ sensitive true if Chef::Resource.instance_methods(false).include?(:sensitive)
+ notifies :restart, 'service[datadog-agent]', :delayed unless node['datadog']['agent_start'] == false
+end
+
+template process_agent_config_file do
+ def conf_template_vars
+ {
+ :api_keys => [Chef::Datadog.api_key(node)],
+ :dd_urls => [node['datadog']['url']]
+ }
+ end
+ variables(
+ if respond_to?(:lazy)
+ lazy { conf_template_vars }
+ else
+ conf_template_vars
+ end
+ )
+ if is_windows
+ owner 'Administrators'
+ rights :full_control, 'Administrators'
+ inherits false
+ else
+ owner 'dd-agent'
+ group 'dd-agent'
+ mode '640'
+ end
+ source 'datadog.conf.erb'
+ sensitive true if Chef::Resource.instance_methods(false).include?(:sensitive)
+ notifies :restart, 'service[datadog-agent]', :delayed unless node['datadog']['agent_start'] == false
+end
+
+# With agent6, the process-agent and trace-agent are enabled as long-running checks
+# TODO: on agent6, we can't really make the trace-agent _not_ run yet
+datadog_monitor 'apm' do
+ instances [{}]
+ use_integration_template true
+ if node['datadog']['enable_trace_agent'].is_a?(TrueClass)
+ action :add
+ else
+ action :remove
+ end
+end
+process_agent_init_config = { enabled: node['datadog']['enable_process_agent'] }
+datadog_monitor 'process_agent' do
+ init_config process_agent_init_config
+ instances [{}]
+ use_integration_template true
+ if node['datadog']['enable_process_agent'].is_a?(TrueClass) || node['datadog']['enable_process_agent'].is_a?(FalseClass)
+ action :add
+ else
+ action :remove
+ end
+end
+
+agent6_config_file = ::File.join(node['datadog']['agent6_config_dir'], 'datadog.yaml')
+template agent6_config_file do # rubocop:disable Metrics/BlockLength
+ def template_vars # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
+ additional_endpoints = {}
+ node['datadog']['extra_endpoints'].each do |_, endpoint|
+ next unless endpoint['enabled']
+ url = if endpoint['url']
+ endpoint['url']
+ else
+ node['datadog']['url']
+ end
+ if additional_endpoints.key?(url)
+ additional_endpoints[url] << endpoint['api_key']
+ else
+ additional_endpoints[url] = [endpoint['api_key']]
+ end
+ end
+ extra_config = {}
+ node['datadog']['extra_config'].each do |k, v|
+ next if v.nil?
+ extra_config[k] = v
+ end
+ {
+ extra_config: extra_config,
+ api_key: Chef::Datadog.api_key(node),
+ additional_endpoints: additional_endpoints
+ }
+ end
+
+ owner 'dd-agent'
+ group 'dd-agent'
+ mode '640'
+ variables(
+ if respond_to?(:lazy)
+ lazy { template_vars }
+ else
+ template_vars
+ end
+ )
+ sensitive true if Chef::Resource.instance_methods(false).include?(:sensitive)
+ notifies :restart, 'service[datadog-agent]', :delayed unless node['datadog']['agent_start'] == false
+end

MODIFY
recipes/_install-linux.rb
recipes/_install-linux.rb
# Install the Apt/Yum repository if enabled
include_recipe 'datadog::repository' if node['datadog']['installrepo']
-dd_agent_version =
+dd_agent5_version =
if node['datadog']['agent_version'].respond_to?(:each_pair)
case node['platform_family']
when 'rhel', 'fedora', 'amazon'
@@ -32,8 +32,28 @@ dd_agent_version =
node['datadog']['agent_version']
end
-# If version specified and lower than 5.x
+dd_agent6_version =
+ if node['datadog']['agent6_version'].respond_to?(:each_pair)
+ case node['platform_family']
+ when 'rhel', 'fedora'
+ node['datadog']['agent6_version']['rhel']
+ else
+ node['datadog']['agent6_version'][node['platform_family']]
+ end
+ else
+ node['datadog']['agent6_version']
+ end
+
+if node['datadog']['agent6']
+ dd_agent_version = dd_agent6_version
+ package_action = node['datadog']['agent6_package_action']
+else
+ dd_agent_version = dd_agent5_version
+ package_action = node['datadog']['agent_package_action']
+end
+
if !dd_agent_version.nil? && dd_agent_version.split('.')[0].split(':').last.to_i < 5
+ # If version specified and lower than 5.x
Chef::Log.warn 'Support for Agent pre 5.x will be removed in datadog cookbook version 3.0'
# Select correct package name based on attribute
dd_pkg_name = node['datadog']['install_base'] ? 'datadog-agent-base' : 'datadog-agent'
@@ -48,6 +68,7 @@ else
only_if 'rpm -q datadog-agent-base' if %w[rhel fedora].include?(node['platform_family'])
not_if 'apt-cache policy datadog-agent-base | grep "Installed: (none)"' if node['platform_family'] == 'debian'
end
+
package_retries = node['datadog']['agent_package_retries']
package_retry_delay = node['datadog']['agent_package_retry_delay']
# Install the regular package
@@ -57,7 +78,7 @@ else
version dd_agent_version
retries package_retries unless package_retries.nil?
retry_delay package_retry_delay unless package_retry_delay.nil?
- action node['datadog']['agent_package_action'] # default is :install
+ action package_action # default is :install
options '--force-yes' if node['datadog']['agent_allow_downgrade']
end
when 'rhel', 'fedora', 'amazon'
@@ -65,7 +86,7 @@ else
version dd_agent_version
retries package_retries unless package_retries.nil?
retry_delay package_retry_delay unless package_retry_delay.nil?
- action node['datadog']['agent_package_action'] # default is :install
+ action package_action # default is :install
allow_downgrade node['datadog']['agent_allow_downgrade']
end
end

MODIFY
recipes/dd-agent.rb
recipes/dd-agent.rb
@@ -38,10 +38,18 @@ end
agent_enable = node['datadog']['agent_enable'] ? :enable : :disable
# Set the correct Agent startup action
agent_start = node['datadog']['agent_start'] ? :start : :stop
-# Set the correct config file
-agent_config_file = ::File.join(node['datadog']['config_dir'], 'datadog.conf')
-# Make sure the config directory exists
+#
+# Configures a basic agent
+# To add integration-specific configurations, add 'datadog::config_name' to
+# the node's run_list and set the relevant attributes
+#
+if node['datadog']['agent6']
+ include_recipe 'datadog::_agent6_config'
+else
+ # Agent 5 and lower
+
+ # Make sure the config directory exists for Agent 5
directory node['datadog']['config_dir'] do
if is_windows
owner 'Administrators'
@@ -54,12 +62,7 @@ directory node['datadog']['config_dir'] do
end
end
-#
-# Configures a basic agent
-# To add integration-specific configurations, add 'datadog::config_name' to
-# the node's run_list and set the relevant attributes
-#
-
+ agent_config_file = ::File.join(node['datadog']['config_dir'], 'datadog.conf')
template agent_config_file do # rubocop:disable Metrics/BlockLength
def template_vars # rubocop:disable Metrics/AbcSize
api_keys = [Chef::Datadog.api_key(node)]
@@ -96,6 +99,7 @@ template agent_config_file do # rubocop:disable Metrics/BlockLength
)
sensitive true if Chef::Resource.instance_methods(false).include?(:sensitive)
end
+end
# Common configuration
service 'datadog-agent' do

MODIFY
recipes/repository.rb
recipes/repository.rb
@@ -42,6 +42,23 @@ when 'debian'
action :add
end
+ apt_repository 'datadog-beta' do
+ keyserver 'hkp://keyserver.ubuntu.com:80'
+ key 'C7A7DA52'
+ uri node['datadog']['agent6_aptrepo']
+ distribution node['datadog']['agent6_aptrepo_dist']
+ components ['main']
+ if node['datadog']['agent6'] &&
+ (node['datadog']['agent6_aptrepo'] != node['datadog']['aptrepo'] ||
+ node['datadog']['agent6_aptrepo_dist'] != node['datadog']['aptrepo_dist'])
+ # add the beta repo iff:
+ # * agent6 is selected (avoid automatic upgrades to agent6 if it's not), and
+ # * the node is configured to use a different repo than the agent5 (avoid duplicate repos)
+ action :add
+ else
+ action :remove
+ end
+ end
when 'rhel', 'fedora', 'amazon'
# Import new RPM key
if node['datadog']['yumrepo_gpgkey_new']

MODIFY
templates/default/datadog.conf.erb
templates/default/datadog.conf.erb
@@ -167,6 +167,14 @@ if node['datadog']['legacy_integrations']
end
-%>
+<% if node['datadog']['enable_process_agent'].is_a?(TrueClass) || node['datadog']['enable_process_agent'].is_a?(FalseClass) -%>
+process_agent_enabled: <%= node['datadog']['enable_process_agent'] %>
+<% end -%>
+
+<% if node['datadog']['enable_trace_agent'].is_a?(TrueClass) || node['datadog']['enable_trace_agent'].is_a?(FalseClass) -%>
+apm_enabled: <%= node['datadog']['enable_trace_agent'] %>
+<% end -%>
+
<% if ! node['datadog']['extra_config'].empty? -%>
# ========================================================================== #
# Other config options
@@ -178,14 +186,7 @@ end
<% end -%>
<% end -%>
-<% if node['datadog']['enabled_process_agent'].is_a?(TrueClass) || node['datadog']['enabled_process_agent'].is_a?(FalseClass) -%>
-process_agent_enabled: <%= node['datadog']['enabled_process_agent'] %>
-<% end -%>
-
## Trace settings
-<% if node['datadog']['enable_trace_agent'].is_a?(TrueClass) || node['datadog']['enable_trace_agent'].is_a?(FalseClass) -%>
-apm_enabled: <%= node['datadog']['enable_trace_agent'] %>
-<% end -%>
[trace.config]
<% unless node['datadog']['trace_env'].nil? -%>

ADD
templates/default/datadog.yaml.erb
+<%
+# OPTIONS REMOVED IN AGENT 6:
+# - check_freq
+# - use_mount
+# - developer_mode
+# - dogstreams
+# - autorestart
+# - custom_emitters
+# - graphite
+# - dogstatsd_target
+# - dogstatsd_interval
+# - dogstatsd_normalize
+# - legacy_integrations
+
+# TODO: options not supported yet:
+# - agent_checks_interval
+# - Autodiscovery (aka Service Discovery) related options
+# - statsd_forward_host
+# - statsd_forward_port
+# - statsd_metric_namespace
+# - enable_trace_agent: always enabled
+# - all trace-related options are written to an INI file
+
+def string_list_to_array(string_list)
+ # return an array from a comma-separated list in a string
+ string_list.split(',').map{ |elem| elem.strip }
+end
+
+## Normalize complex config values for agent6 format ##
+if node['datadog']['tags'].respond_to?(:each_pair)
+ tags = node['datadog']['tags'].reject{ |_k,v| v.empty? }.map{ |k,v| "#{k.strip}:#{v.strip}" }
+else
+ tags = string_list_to_array(node['datadog']['tags'])
+end
+
+# TODO: support the more complete proxy settings that the agent6 supports
+http_proxy = nil
+if node['datadog']['web_proxy']['host']
+ host = node['datadog']['web_proxy']['host']
+ port = node['datadog']['web_proxy']['port']
+ user = node['datadog']['web_proxy']['user']
+ password = node['datadog']['web_proxy']['password']
+ scheme = ""
+
+ unless host.start_with?('http://') or host.start_with?('https://')
+ scheme = 'http://'
+ end
+
+ http_proxy = host
+ if port
+ http_proxy += ":#{port}"
+ end
+ if user
+ if password
+ http_proxy = "#{user}:#{port}@#{http_proxy}"
+ else
+ http_proxy = "#{user}@#{http_proxy}"
+ end
+ end
+
+ http_proxy = scheme + http_proxy
+end
+
+## Populate agent_config ##
+agent_config = @extra_config.merge({
+ api_key: @api_key,
+ dd_url: node['datadog']['url'],
+ hostname: node['datadog']['hostname'],
+ additional_endpoints: @additional_endpoints,
+ listen_port: node['datadog']['agent_port'],
+ bind_host: node['datadog']['bind_host'],
+ skip_ssl_validation: node['datadog']['web_proxy']['skip_ssl_validation'],
+ tags: tags,
+ create_dd_check_tags: node['datadog']['create_dd_check_tags'],
+ collect_ec2_tags: node['datadog']['collect_ec2_tags'],
+ non_local_traffic: node['datadog']['non_local_traffic'],
+ histogram_aggregates: string_list_to_array(node['datadog']['histogram_aggregates']),
+ histogram_percentiles: string_list_to_array(node['datadog']['histogram_percentiles']), # TODO: check that the value works with agent6
+ use_dogstatsd: node['datadog']['dogstatsd'],
+ log_level: node['datadog']['log_level'], # TODO: make sure it's a seelog-compatible log level
+ log_file: ::File.join(node['datadog']['log_file_directory'], "agent.log")
+})
+
+if node['datadog']['use_v2_api']
+ agent_config['use_v2_api'] = node['datadog']['use_v2_api']
+end
+
+if node['datadog']['syslog']['active']
+ agent_config['log_to_syslog'] = true
+ # TODO: double check the udp settings work with agent6
+ if node['datadog']['syslog']['udp']
+ agent_config['syslog_uri'] = "#{node['datadog']['syslog']['host']}:#{node['datadog']['syslog']['port']}"
+ end
+end
+
+# Set proxy options
+if !http_proxy.nil?
+ agent_config['proxy'] = {
+ http: http_proxy,
+ https: http_proxy
+ }
+end
+
+# Remove nil values
+agent_config.reject!{ |k,v| v.nil? }
+
+-%>
+# Generated by Chef, local modifications will be overwritten
+
+<%= JSON.parse(agent_config.to_json).to_yaml %>

Support of agent6 beta for debianoids (#472)

Flipping the attribute 'datadog''agent6' to true installs the agent6
instead of the agent5. Switching it back to false should reverse
the operation as long as the agent 5 version is pinned.