Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions manifests/integrations/tcp_check.pp
Original file line number Diff line number Diff line change
@@ -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:<name>.
#
# host
# (Required) - Host to be checked.
# This will be included as a tag: url:<host>:<port>.
#
# port
# (Required) - Port to be checked.
# This will be included as a tag: url:<host>:<port>.
#
# 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 <threshold> times in <window> attempts.
#
# window
# (Optional) - Refer to �threshold�.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aepod the quotes here are not ASCII quotes, this is what's preventing the CI from running your tests. You should probably change them to regular quotes, or just remove them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting copy/paste/edit from the documentation on the check, oops. those quotes snuck through. I assume this was the "non-utf8" error, which was bugging me! haha I will sort this out, thanks for the heads up.

#
# 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 (
$name = undef,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will probably have to change this parameter name to something else or you'll get this error: The parameter $name redefines a built in parameter in the Host Class Definition. May I suggest sitename or hostname?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I sort of knew that when I switched it, but wasn't sure. I will switch it to something else and resubmit.

$host = undef,
$port = undef,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A required parameter should not have an optional value. I believe host and port are definitely mandatory. I would probably make sitename mandatory as well just to be safe.

$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 = [{
'name' => $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]
}
}
96 changes: 96 additions & 0 deletions spec/classes/datadog_agent_integrations_tcp_check_spec.rb
Original file line number Diff line number Diff line change
@@ -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) {{
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).without_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) {{
sitename: 'foo.bar.baz',
url: 'foo.bar.baz',
port: '80',
tags: %w{ 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) {{
sitename: 'foo.bar.baz',
url: '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
31 changes: 31 additions & 0 deletions templates/agent-conf.d/tcp_check.yaml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
init_config:

instances:
<%- (Array(@_instances)).each do |instance| -%>
- name: <%= instance['name'] %>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will have to update this to instance['sitename'] or whatever.

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 -%>