Gage has submitted this change and it was merged.
Change subject: Allow puppetmaster to send reports to logstash
......................................................................
Allow puppetmaster to send reports to logstash
Add a Puppet report handler for sending data to logstash. Each report is
converted to a single log event which is sent as newline delimited json
to Logstash over a tcp transport.
On the Logstash side, the event's "host" field is fixed to contain the
hostname of the Puppet agent that originated the report rather than the
ip address of the Puppetmaster and tags for indexing in ElasticSearch.
This results in the full diff of the Puppet run being stored in
Logstash. As such, care should be taken in ensuring that the target
logstash cluster is properly secured for types of sensitive data that
this may reveal.
Bug: 60690
Change-Id: I604582a7faf902ba899985ca7127b95de1fa9b20
---
A files/logstash/filter-puppet.conf
M manifests/role/beta.pp
M manifests/role/logstash.pp
A modules/logstash/manifests/input/tcp.pp
A modules/logstash/templates/input/tcp.erb
A modules/puppetmaster/lib/puppet/reports/logstash.rb
A modules/puppetmaster/manifests/reporter/logstash.pp
A modules/puppetmaster/templates/30-logstash.conf.erb
A modules/puppetmaster/templates/reporter/logstash.yaml.erb
9 files changed, 179 insertions(+), 0 deletions(-)
Approvals:
Gage: Looks good to me, approved
jenkins-bot: Verified
diff --git a/files/logstash/filter-puppet.conf
b/files/logstash/filter-puppet.conf
new file mode 100644
index 0000000..a8ac1ef
--- /dev/null
+++ b/files/logstash/filter-puppet.conf
@@ -0,0 +1,10 @@
+filter {
+ if [type] == "puppet" {
+ mutate {
+ # The tcp input clobbers "host" with the inbound ip:port
+ replace => [ "host", "%{client}" ]
+ add_tag => [ "es" ]
+ remove_field => [ "client" ]
+ }
+ }
+}
diff --git a/manifests/role/beta.pp b/manifests/role/beta.pp
index df4d57c..cd6aac3 100644
--- a/manifests/role/beta.pp
+++ b/manifests/role/beta.pp
@@ -159,3 +159,12 @@
runners_gwt => 1,
}
}
+
+# = Class: role::beta::puppetmaster
+# Add nice things to the beta puppetmaster.
+class role::beta::puppetmaster {
+ class { 'puppetmaster::reporter::logstash':
+ logstash_host => 'deployment-logstash1.eqiad.wmflabs',
+ logstash_port => 5229,
+ }
+}
diff --git a/manifests/role/logstash.pp b/manifests/role/logstash.pp
index 01a38f7..64ebc45 100644
--- a/manifests/role/logstash.pp
+++ b/manifests/role/logstash.pp
@@ -136,8 +136,18 @@
channels => ['#wikimedia-labs'],
}
+ logstash::input::tcp { 'tcp_json':
+ port => 5229,
+ codec => 'json_lines',
+ }
+
logstash::conf { 'filter_irc_banglog':
source => 'puppet:///files/logstash/filter-irc-banglog.conf',
priority => 50,
}
+
+ logstash::conf { 'filter_puppet':
+ source => 'puppet:///files/logstash/filter-puppet.conf',
+ priority => 50,
+ }
}
diff --git a/modules/logstash/manifests/input/tcp.pp
b/modules/logstash/manifests/input/tcp.pp
new file mode 100644
index 0000000..eb3827e
--- /dev/null
+++ b/modules/logstash/manifests/input/tcp.pp
@@ -0,0 +1,31 @@
+# vim:sw=4 ts=4 sts=4 et:
+
+# = Define: logstash::input::tcp
+#
+# Configure logstash to collect input via a tcp socket.
+#
+# == Parameters:
+# - $ensure: Whether the config should exist. Default 'present'.
+# - $port: Port to listen for udp2log input on. Default '5229'.
+# - $codec: Codec to decode tcp stream input. Default 'plain'.
+# - $priority: Configuration loading priority. Default '10'.
+#
+# == Sample usage:
+#
+# logstash::input::tcp {
+# port => 5229,
+# codec => 'json_lines',
+# }
+#
+define logstash::input::tcp(
+ $ensure = present,
+ $port = 5229,
+ $codec = 'plain',
+ $priority = 10,
+) {
+ logstash::conf { "input-tcp-${title}":
+ ensure => $ensure,
+ content => template('logstash/input/tcp.erb'),
+ priority => $priority,
+ }
+}
diff --git a/modules/logstash/templates/input/tcp.erb
b/modules/logstash/templates/input/tcp.erb
new file mode 100644
index 0000000..1c0d0a0
--- /dev/null
+++ b/modules/logstash/templates/input/tcp.erb
@@ -0,0 +1,7 @@
+input {
+ tcp {
+ type => "tcp"
+ port => <%= @port %>
+ codec => "<%= @codec %>"
+ }
+}
diff --git a/modules/puppetmaster/lib/puppet/reports/logstash.rb
b/modules/puppetmaster/lib/puppet/reports/logstash.rb
new file mode 100644
index 0000000..43ca5ab
--- /dev/null
+++ b/modules/puppetmaster/lib/puppet/reports/logstash.rb
@@ -0,0 +1,69 @@
+# Puppet reporter to log events to logstash
+#
+# Based on https://github.com/logstash/puppet-logstash-reporter
+#
+# Copyright 2013 EvenUp Inc.
+# Copyright © 2014 Bryan Davis and Wikimedia Foundation.
+# License http://www.apache.org/licenses/LICENSE-2.0
+
+require 'puppet'
+require 'socket'
+require 'timeout'
+require 'json'
+require 'yaml'
+
+Puppet::Reports.register_report(:logstash) do
+ desc 'Send logs to a logstash instance'
+
+ config_file = File.join([File.dirname(Puppet.settings[:config]),
'logstash.yaml'])
+ begin
+ CONFIG = YAML.load_file(config_file)
+ rescue Exception => e
+ raise(Puppet::ParseError, "Failed to load logstash report config file
#{config_file}: #{e.message}")
+ end
+
+ SERVER_NAME = Socket.gethostbyname(Socket.gethostname).first
+
+ def process
+ # Convert Puppet::Transaction::Report object to a logstash event
+ event = {
+ '@timestamp' => self.logs.last.time.utc.iso8601,
+ '@version' => 1,
+ 'host' => self.host,
+ 'client' => self.host,
+ 'server' => SERVER_NAME,
+ 'message' => "Puppet run on #{self.host} -
#{self.status}",
+ 'type' => 'puppet',
+ 'channel' => self.kind,
+ 'environment' => self.environment,
+ 'report_format' => self.report_format,
+ 'transaction_uuid' => self.transaction_uuid,
+ 'configuration_version' => self.configuration_version,
+ 'puppet_version' => self.puppet_version,
+ 'status' => self.status,
+ 'start_time' => self.logs.first.time.utc.iso8601,
+ 'end_time' => self.logs.last.time.utc.iso8601,
+ 'log_messages' => self.logs.map(&:to_report),
+ 'metrics' => {},
+ }
+
+ self.metrics.each do |category,v|
+ event['metrics'][category] = {}
+ v.values.each do |metric|
+ # Each element is of the form [name, titleized_name, value]
+ event['metrics'][category][metric[0]] = metric[2]
+ end
+ end
+
+ begin
+ Timeout::timeout(CONFIG[:timeout]) do
+ sock = TCPSocket.new "#{CONFIG[:host]}" , CONFIG[:port]
+ sock.puts event.to_json
+ sock.flush
+ sock.close
+ end
+ rescue Exception => e
+ Puppet.err("Failed to write to #{CONFIG[:host]} on port
#{CONFIG[:port]}: #{e.message}")
+ end
+ end
+end
diff --git a/modules/puppetmaster/manifests/reporter/logstash.pp
b/modules/puppetmaster/manifests/reporter/logstash.pp
new file mode 100644
index 0000000..443305d
--- /dev/null
+++ b/modules/puppetmaster/manifests/reporter/logstash.pp
@@ -0,0 +1,34 @@
+# = Class: puppetmaster::logstash
+#
+# Deploy and configure a puppet reporter to send reports to logstash.
+#
+# This results in the full diff of the Puppet run being stored in Logstash. As
+# such, care should be taken in ensuring that the target logstash cluster is
+# properly secured for types of sensitive data that this may reveal.
+#
+# == Parameters
+# - logstash_host: Host to send log events to
+# - logstash_port: Port to send log events to
+# - timeout: Connection timeout for sending an event in seconds. Default is 5.
+class puppetmaster::reporter::logstash(
+ $logstash_host,
+ $logstash_port,
+ $timeout = 5,
+) {
+ file { '/etc/puppet/logstash.yaml':
+ ensure => file,
+ owner => 'puppet',
+ group => 'puppet',
+ mode => '0444',
+ content => template('puppetmaster/reporter/logstash.yaml.erb'),
+ }
+
+ file { '/etc/puppet/puppet.conf.d/30-logstash.conf':
+ require => File['/etc/puppet/puppet.conf.d'],
+ owner => 'root',
+ group => 'root',
+ mode => '0444',
+ content => template('puppetmaster/30-logstash.conf.erb'),
+ notify => Exec['compile puppet.conf']
+ }
+}
diff --git a/modules/puppetmaster/templates/30-logstash.conf.erb
b/modules/puppetmaster/templates/30-logstash.conf.erb
new file mode 100644
index 0000000..af45d00
--- /dev/null
+++ b/modules/puppetmaster/templates/30-logstash.conf.erb
@@ -0,0 +1,4 @@
+[master]
+report = true
+reports = store,logstash
+pluginsync = true
diff --git a/modules/puppetmaster/templates/reporter/logstash.yaml.erb
b/modules/puppetmaster/templates/reporter/logstash.yaml.erb
new file mode 100644
index 0000000..a4fb06f
--- /dev/null
+++ b/modules/puppetmaster/templates/reporter/logstash.yaml.erb
@@ -0,0 +1,5 @@
+---
+# This file is managed by puppet.
+:host: <%= @logstash_host %>
+:port: <%= @logstash_port %>
+:timeout: <%= @timeout %>
--
To view, visit https://gerrit.wikimedia.org/r/143788
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I604582a7faf902ba899985ca7127b95de1fa9b20
Gerrit-PatchSet: 13
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: BryanDavis <[email protected]>
Gerrit-Reviewer: BryanDavis <[email protected]>
Gerrit-Reviewer: Gage <[email protected]>
Gerrit-Reviewer: Giuseppe Lavagetto <[email protected]>
Gerrit-Reviewer: Greg Grossmeier <[email protected]>
Gerrit-Reviewer: Hashar <[email protected]>
Gerrit-Reviewer: Mark Bergsma <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: Yuvipanda <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits