Add recipe for go-metro integration
Fixes
ADD
attributes/go-metro.rb
+# The implementation for the go-metro recipe allows any package resource
+# property to be defined as an attribute underneath the
+# node['datadog']['go-metro']['libcap_package'] namespace
+#
+# For example, if you want to set the package version, you can do something
+# like:
+# default['datadog']['go-metro']['libcap_package']['version'] = 'foo'
+
+# The only required option is package_name:
+# valid values for RHEL-based system are: libcap, compat-libcap1
+# valid values for Debian-based systems are: libcap, libcap2-bin
+default['datadog']['go-metro']['libcap_package']['package_name'] = 'libcap'
+
+# init config
+default['datadog']['go-metro']['init_config'] = {
+ 'snaplen' => 512,
+ 'idle_ttl' => 300,
+ 'exp_ttl' => 60,
+ 'statsd_ip' => '127.0.0.1',
+ 'statsd_port' => 8125,
+ 'log_to_file' => true,
+ 'log_level' => 'info'
+}

ADD
recipes/go-metro.rb
+include_recipe 'datadog::dd-agent'
+
+# Go-Metro (TCP RTT) Integration: Passively monitor TCP Round Trip Time
+# between the monitored host and others nodes on the network
+
+# Recommended default init_config:
+# (these are set in the go-metro attributes file in this cookbook)
+# node['datadog']['go-metro']['init_config'] = {
+# 'snaplen' => 512,
+# 'idle_ttl' => 300,
+# 'exp_ttl' => 60,
+# 'statsd_ip' => '127.0.0.1',
+# 'statsd_port' => 8125,
+# 'log_to_file' => true,
+# 'log_level' => 'info'
+# }
+
+# Assuming you want to monitor connections to
+# 10.0.0.1, 10.0.0.2, 10.0.0.3, and app.datadoghq.com from eth0,
+# create an instance configuration like this:
+# node['datadog']['go-metro']['instances'] = [
+# {
+# 'interface' => 'eth0',
+# 'tags' => [
+# 'env:prod'
+# ],
+# 'ips' => [
+# '10.0.0.1',
+# '10.0.0.2',
+# '10.0.0.3'
+# ],
+# 'hosts' => [
+# 'app.datadoghq.com'
+# ]
+# }
+# ]
+
+####
+# At the time of writing, the Go-Metro (TCP Round Trip Time) integration
+# is only available as part of the 64-bit DEB and RPM agent distribution
+#
+# Bail if we're not 64-bit or not linux
+if node['kernel']['machine'] != 'x86_64' || node['os'] != 'linux'
+ Chef::Log.fatal('The Go-Metro (TCP RTT) integration is only available')
+ Chef::Log.fatal('as part of the 64-bit DEB and RPM agent distribution')
+ if node['os'] == 'linux'
+ Chef::Log.fatal(
+ "And Chef thinks this machine is #{node['kernel']['machine']}", \
+ "not 'x86_64'"
+ )
+ else
+ Chef::Log.fatal(
+ "And Chef thinks this machine is #{node['os']}, not 'linux'"
+ )
+ end
+ raise
+end
+
+# install desired package for libcap
+# This implementation allows you to set any valid package resourece property
+# as an attribute underneath node['datadog']['go-metro']['libcap-package']
+package 'libcap' do
+ # handle scenario when entire attribute is nil
+ unless node['datadog']['go-metro']['libcap_package'].nil?
+ # send each attribute as a property to the resource
+ node['datadog']['go-metro']['libcap_package'].each do |prop, value|
+ send(prop.to_sym, value) unless value.nil?
+ end
+ end
+end
+
+# add cap_net_raw+ep to the go-metro binary
+execute 'setcap go-metro' do
+ command 'setcap cap_net_raw+ep /opt/datadog-agent/bin/go-metro'
+ not_if 'setcap -v cap_net_raw+ep /opt/datadog-agent/bin/go-metro'
+end
+
+datadog_monitor 'go-metro' do
+ init_config node['datadog']['go-metro']['init_config']
+ instances node['datadog']['go-metro']['instances']
+end

ADD
spec/integrations/go-metro_spec.rb
+describe 'datadog::go-metro' do
+ context 'with default init_config and libcap package on RHEL7' do
+ expected_yaml = <<-EOF
+ init_config:
+ snaplen: 512
+ idle_ttl: 300
+ exp_ttl: 60
+ statsd_ip: 127.0.0.1
+ statsd_port: 8125
+ log_to_file: true
+ log_level: info
+
+ instances:
+ - interface: eth0
+ tags:
+ - env:prod
+ ips:
+ - 10.0.0.1
+ - 10.0.0.2
+ - 10.0.0.3
+ hosts:
+ - app.datadoghq.com
+ - interface: eth1
+ tags:
+ - env:qa
+ ips:
+ - 192.168.0.22
+ hosts:
+ - docs.datadoghq.com
+ EOF
+
+ cached(:chef_run) do
+ ChefSpec::SoloRunner.new(
+ step_into: ['datadog_monitor'], platform: 'redhat', version: '7.3'
+ ) do |node|
+ node.automatic['languages'] = { python: { version: '2.7.2' } }
+
+ node.set['datadog'] = {
+ api_key: 'someapikey',
+ 'go-metro' => {
+ instances: [
+ {
+ interface: 'eth0',
+ tags: ['env:prod'],
+ ips: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
+ hosts: ['app.datadoghq.com']
+ },
+ {
+ interface: 'eth1',
+ tags: ['env:qa'],
+ ips: ['192.168.0.22'],
+ hosts: ['docs.datadoghq.com']
+ }
+ ]
+ }
+ }
+ end.converge(described_recipe)
+ end
+
+ before(:each) do
+ stub_command('setcap -v cap_net_raw+ep /opt/datadog-agent/bin/go-metro')
+ end
+
+ subject { chef_run }
+
+ it_behaves_like 'datadog-agent'
+
+ it { is_expected.to include_recipe('datadog::dd-agent') }
+
+ it { is_expected.to install_package('libcap') }
+
+ it {
+ is_expected.to run_execute('setcap go-metro').with(
+ command: 'setcap cap_net_raw+ep /opt/datadog-agent/bin/go-metro'
+ )
+ }
+
+ it { is_expected.to add_datadog_monitor('go-metro') }
+
+ it 'renders expected YAML config file' do
+ expect(chef_run).to(
+ render_file('/etc/dd-agent/conf.d/go-metro.yaml')
+ .with_content { |content|
+ expect(YAML.safe_load(content).to_json).to be_json_eql(
+ YAML.safe_load(expected_yaml).to_json
+ )
+ }
+ )
+ end
+ end
+
+ context 'with modified init_config, libcap package on Ubuntu 16.04' do
+ expected_yaml = <<-EOF
+ init_config:
+ snaplen: 1024
+ idle_ttl: 300
+ exp_ttl: 120
+ statsd_ip: 127.0.0.5
+ statsd_port: 8125
+ log_to_file: true
+ log_level: debug
+
+ instances:
+ - interface: eth0
+ tags:
+ - env:prod
+ ips:
+ - 10.0.0.1
+ - 10.0.0.2
+ - 10.0.0.3
+ hosts:
+ - app.datadoghq.com
+ EOF
+
+ cached(:chef_run) do
+ ChefSpec::SoloRunner.new(
+ step_into: ['datadog_monitor'], platform: 'ubuntu', version: '16.04'
+ ) do |node|
+ node.automatic['languages'] = { python: { version: '2.7.2' } }
+
+ node.set['datadog'] = {
+ api_key: 'someapikey',
+ 'go-metro' => {
+ libcap_package: {
+ package_name: 'libcap2-bin',
+ version: '123'
+ },
+ init_config: {
+ snaplen: 1024,
+ idle_ttl: 300,
+ exp_ttl: 120,
+ statsd_ip: '127.0.0.5',
+ log_level: 'debug'
+ },
+ instances: [
+ {
+ interface: 'eth0',
+ tags: ['env:prod'],
+ ips: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
+ hosts: ['app.datadoghq.com']
+ }
+ ]
+ }
+ }
+ end.converge(described_recipe)
+ end
+
+ before(:each) do
+ stub_command('setcap -v cap_net_raw+ep /opt/datadog-agent/bin/go-metro')
+ end
+
+ subject { chef_run }
+
+ it_behaves_like 'datadog-agent'
+
+ it { is_expected.to include_recipe('datadog::dd-agent') }
+
+ it {
+ is_expected.to install_package('libcap').with(
+ package_name: 'libcap2-bin',
+ version: '123'
+ )
+ }
+
+ it {
+ is_expected.to run_execute('setcap go-metro').with(
+ command: 'setcap cap_net_raw+ep /opt/datadog-agent/bin/go-metro'
+ )
+ }
+
+ it { is_expected.to add_datadog_monitor('go-metro') }
+
+ it 'renders expected YAML config file' do
+ expect(chef_run).to(
+ render_file('/etc/dd-agent/conf.d/go-metro.yaml')
+ .with_content { |content|
+ expect(YAML.safe_load(content).to_json).to be_json_eql(
+ YAML.safe_load(expected_yaml).to_json
+ )
+ }
+ )
+ end
+ end
+
+ context 'on a windows platform' do
+ cached(:chef_run) do
+ ChefSpec::SoloRunner.new(
+ step_into: ['datadog_monitor'], platform: 'windows', version: '2012R2'
+ ) do |node|
+ node.automatic['languages'] = { python: { version: '2.7.2' } }
+
+ node.set['datadog'] = {
+ api_key: 'someapikey'
+ }
+ end
+ end
+
+ it 'bails out with a fatal log message' do
+ allow(Chef::Log).to receive(:fatal).and_call_original
+ expect(Chef::Log).to receive(:fatal).with("And Chef thinks this machine is windows, not 'linux'")
+ expect { chef_run.converge(described_recipe) }.to raise_error(RuntimeError)
+ end
+ end
+end

ADD
templates/default/go-metro.yaml.erb
+# Generated by Chef, local modifications will be overwritten
+
+<%= JSON.parse(({ 'init_config' => @init_config, 'instances' => @instances}).to_json).to_yaml %>
+

Add recipe for go-metro integration (#484)

Fixes #35