diff --git a/manifests/integrations/tcp_check.pp b/manifests/integrations/tcp_check.pp new file mode 100644 index 00000000..4ec4b2aa --- /dev/null +++ b/manifests/integrations/tcp_check.pp @@ -0,0 +1,129 @@ +# Class: datadog_agent::integrations::tcp_check +# +# This class will install the necessary config to hook the tcp_check in the agent +# +# Parameters: +# name +# (Required) - Name of the service. +# This will be included as a tag: instance:. +# +# host +# (Required) - Host to be checked. +# This will be included as a tag: url::. +# +# port +# (Required) - Port to be checked. +# This will be included as a tag: url::. +# +# timeout +# (Optional) - Timeout for the check. Defaults to 10 seconds. +# +# threshold +# (Optional) - Used in conjunction with window. An alert will +# trigger if the check fails times in attempts. +# +# window +# (Optional) - Refer to threshold. +# +# collect_response_time +# (Optional) - Defaults to false. If this is not set to true, no +# response time metric will be collected. If it is set to true, the +# metric returned is network.tcp.response_time. +# +# skip_event +# The (optional) skip_event parameter will instruct the check to not +# create any event to avoid duplicates with a server side service check. +# This default to False. +# +# tags +# The (optional) tags to add to the check instance. +# +# Sample Usage: +# +# Add a class for each check instance: +# +# class { 'datadog_agent::integrations::tcp_check': +# name => 'localhost-ftp', +# host => 'ftp.example.com', +# port => '21', +# } +# +# class { 'datadog_agent::integrations::tcp_check': +# name => 'localhost-ssh', +# host => '127.0.0.1', +# port => '22', +# threshold => 1, +# window => 1, +# tags => ['production', 'ssh access'], +# } +# +# class { 'datadog_agent::integrations::tcp_check': +# name => 'localhost-web-response', +# host => '127.0.0.1', +# port => '80', +# timeout => '8', +# threshold => 1, +# window => 1, +# collect_response_time => 1, +# skip_event => 1, +# tags => ['production', 'webserver response time'], +# } +# +# Add multiple instances in one class declaration: +# +# class { 'datadog_agent::integrations::tcp_check': +# instances => [{ +# 'name' => 'www.example.com-http', +# 'host' => 'www.example.com', +# 'port' => '80', +# }, +# { +# 'name' => 'www.example.com-https', +# 'host' => 'www.example.com', +# 'port' => '443', +# }] +# } + + +class datadog_agent::integrations::tcp_check ( + $check_name = undef, + $host = undef, + $port = undef, + $timeout = 10, + $threshold = undef, + $window = undef, + $collect_response_time = undef, + $skip_event = undef, + $tags = [], + $instances = undef, +) inherits datadog_agent::params { + include datadog_agent + + if !$instances and $host { + $_instances = [{ + 'check_name' => $check_name, + 'host' => $host, + 'port' => $port, + 'timeout' => $timeout, + 'threshold' => $threshold, + 'window' => $window, + 'collect_response_time' => $collect_response_time, + 'skip_event' => $skip_event, + 'tags' => $tags, + }] + } elsif !$instances{ + $_instances = [] + } else { + $_instances = $instances + } + + file { "${datadog_agent::params::conf_dir}/tcp_check.yaml": + ensure => file, + owner => $datadog_agent::params::dd_user, + group => $datadog_agent::params::dd_group, + mode => '0600', + content => template('datadog_agent/agent-conf.d/tcp_check.yaml.erb'), + require => Package[$datadog_agent::params::package_name], + notify => Service[$datadog_agent::params::service_name] + } +} diff --git a/spec/classes/datadog_agent_integrations_tcp_check_spec.rb b/spec/classes/datadog_agent_integrations_tcp_check_spec.rb new file mode 100644 index 00000000..aadb6245 --- /dev/null +++ b/spec/classes/datadog_agent_integrations_tcp_check_spec.rb @@ -0,0 +1,96 @@ +require 'spec_helper' + +describe 'datadog_agent::integrations::tcp_check' do + let(:facts) {{ + operatingsystem: 'Ubuntu', + }} + let(:conf_dir) { '/etc/dd-agent/conf.d' } + let(:dd_user) { 'dd-agent' } + let(:dd_group) { 'root' } + let(:dd_package) { 'datadog-agent' } + let(:dd_service) { 'datadog-agent' } + let(:conf_file) { "#{conf_dir}/tcp_check.yaml" } + + it { should compile.with_all_deps } + it { should contain_file(conf_file).with( + owner: dd_user, + group: dd_group, + mode: '0600', + )} + it { should contain_file(conf_file).that_requires("Package[#{dd_package}]") } + it { should contain_file(conf_file).that_notifies("Service[#{dd_service}]") } + + context 'with default parameters' do + it { should contain_file(conf_file).without_content(%r{name: }) } + it { should contain_file(conf_file).without_content(%r{host: }) } + it { should contain_file(conf_file).without_content(%r{port: }) } + it { should contain_file(conf_file).without_content(%r{timeout: 1}) } + it { should contain_file(conf_file).without_content(%{threshold: }) } + it { should contain_file(conf_file).without_content(%r{window: }) } + it { should contain_file(conf_file).without_content(%r{collect_response_time: }) } + it { should contain_file(conf_file).without_content(%r{skip_event: }) } + it { should contain_file(conf_file).without_content(%r{tags: }) } + end + + context 'with parameters set' do + let(:params) {{ + check_name: 'foo.bar.baz', + host: 'foo.bar.baz', + port: '80', + timeout: 123, + threshold: 456, + window: 789, + collect_response_time: true, + skip_event: true, + }} + + it { should contain_file(conf_file).with_content(%r{name: foo.bar.baz}) } + it { should contain_file(conf_file).with_content(%r{host: foo.bar.baz}) } + it { should contain_file(conf_file).with_content(%r{port: 80}) } + it { should contain_file(conf_file).with_content(%r{timeout: 123}) } + it { should contain_file(conf_file).with_content(%r{threshold: 456}) } + it { should contain_file(conf_file).with_content(%r{window: 789}) } + it { should contain_file(conf_file).with_content(%r{collect_response_time: true}) } + it { should contain_file(conf_file).with_content(%r{skip_event: true}) } + end + + context 'with tags parameter array' do + let(:params) {{ + check_name: 'foo.bar.baz', + host: 'foo.bar.baz', + port: '80', + tags: [ 'foo', 'bar', 'baz' ], + }} + it { should contain_file(conf_file).with_content(/tags:\s+- foo\s+- bar\s+- baz\s*?[^-]/m) } + end + + context 'with tags parameter empty values' do + context 'mixed in with other tags' do + let(:params) {{ + check_name: 'foo.bar.baz', + host: 'foo.bar.baz', + port: '80', + tags: [ 'foo', '', 'baz' ] + }} + + it { should contain_file(conf_file).with_content(/tags:\s+- foo\s+- baz\s*?[^-]/m) } + end + + context 'single element array of an empty string' do + let(:params) {{ + tags: [''], + }} + + skip("undefined behavior") + end + + context 'single value empty string' do + let(:params) {{ + tags: '', + }} + + skip("doubly undefined behavior") + end + end + +end diff --git a/templates/agent-conf.d/tcp_check.yaml.erb b/templates/agent-conf.d/tcp_check.yaml.erb new file mode 100644 index 00000000..08979f00 --- /dev/null +++ b/templates/agent-conf.d/tcp_check.yaml.erb @@ -0,0 +1,31 @@ +init_config: + +instances: +<%- (Array(@_instances)).each do |instance| -%> + - name: <%= instance['check_name'] %> + host: <%= instance['host'] %> + port: <%= instance['port'] %> +<% if instance['timeout'] -%> + timeout: <%= instance['timeout'] %> +<% end -%> +<% if instance['threshold'] -%> + threshold: <%= instance['threshold'] %> +<% end -%> +<% if instance['window'] -%> + window: <%= instance['window'] %> +<% end -%> +<% if instance['collect_response_time'] -%> + collect_response_time: <%= instance['collect_response_time'] %> +<% end -%> +<% if instance['skip_event'] -%> + skip_event: <%= instance['skip_event'] %> +<% end -%> +<% if instance['tags'] and ! instance['tags'].empty? -%> + tags: + <%- Array(instance['tags']).each do |tag| -%> + <%- if tag != '' -%> + - <%= tag %> + <%- end -%> + <%- end -%> +<% end -%> +<% end -%>