aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-04 12:28:24 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-04 12:33:05 +0100
commit2499f7e73946cd5147a1158b48ebe4b06e4e530d (patch)
treeb1435c23f21afee1a8d150d0d96da40070916fc5 /modules
parent85abd2fdbad83430df4824843764719064afb9b4 (diff)
downloadPuppet-2499f7e73946cd5147a1158b48ebe4b06e4e530d.tar.gz
Puppet-2499f7e73946cd5147a1158b48ebe4b06e4e530d.tar.zst
Puppet-2499f7e73946cd5147a1158b48ebe4b06e4e530d.zip
Add helpers and remove logs from cronie
Diffstat (limited to 'modules')
-rw-r--r--modules/base_installation/files/cronie/puppet-post-merge2
-rw-r--r--modules/base_installation/files/scripts/puppet_reset_and_apply14
-rw-r--r--modules/base_installation/files/scripts/report_print.rb396
-rw-r--r--modules/base_installation/manifests/cronie.pp4
-rw-r--r--modules/base_installation/manifests/puppet.pp12
5 files changed, 425 insertions, 3 deletions
diff --git a/modules/base_installation/files/cronie/puppet-post-merge b/modules/base_installation/files/cronie/puppet-post-merge
index 35fa2d7..ac5e3ff 100644
--- a/modules/base_installation/files/cronie/puppet-post-merge
+++ b/modules/base_installation/files/cronie/puppet-post-merge
@@ -1,7 +1,7 @@
1#!/bin/bash 1#!/bin/bash
2## Run Puppet locally using puppet apply 2## Run Puppet locally using puppet apply
3git submodule update --init 3git submodule update --init
4/usr/bin/puppet apply --test `pwd`/manifests/site.pp 4/usr/bin/puppet apply `pwd`/manifests/site.pp
5 5
6## Log status of the Puppet run 6## Log status of the Puppet run
7if [ $? -eq 0 ] 7if [ $? -eq 0 ]
diff --git a/modules/base_installation/files/scripts/puppet_reset_and_apply b/modules/base_installation/files/scripts/puppet_reset_and_apply
new file mode 100644
index 0000000..ff71aa8
--- /dev/null
+++ b/modules/base_installation/files/scripts/puppet_reset_and_apply
@@ -0,0 +1,14 @@
1#!/bin/bash
2
3cd /etc/puppetlabs/code
4git fetch origin
5
6branch="master"
7if [ -n "$1" ]; then
8 branch="$1"
9fi
10
11git reset --hard origin/$1
12
13git submodule update --init
14puppet apply --test manifests/site.pp
diff --git a/modules/base_installation/files/scripts/report_print.rb b/modules/base_installation/files/scripts/report_print.rb
new file mode 100644
index 0000000..632374c
--- /dev/null
+++ b/modules/base_installation/files/scripts/report_print.rb
@@ -0,0 +1,396 @@
1#!/usr/bin/env ruby
2# This file was modified from its original version at
3# https://github.com/ripienaar/puppet-reportprint/
4#
5# Copyright 2013-2016 R.I.Pienaar and contributors
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18
19require 'puppet'
20require 'pp'
21require 'optparse'
22
23def get_server_reports_dir
24 Puppet.settings[:reportdir]
25end
26
27class ::Numeric
28 def bytes_to_human
29 # Prevent nonsense values being returned for fractions
30 if self >= 1
31 units = ['B', 'KB', 'MB' ,'GB' ,'TB']
32 e = (Math.log(self)/Math.log(1024)).floor
33 # Cap at TB
34 e = 4 if e > 4
35 s = "%.2f " % (to_f / 1024**e)
36 s.sub(/\.?0*$/, units[e])
37 else
38 "0 B"
39 end
40 end
41end
42
43def load_report(path)
44 YAML.load_file(path)
45end
46
47def report_resources(report)
48 report.resource_statuses
49end
50
51def resource_with_evaluation_time(report)
52 report_resources(report).select{|r_name, r| !r.evaluation_time.nil? }
53end
54
55def resource_by_eval_time(report)
56 report_resources(report).reject{|r_name, r| r.evaluation_time.nil? }.sort_by{|r_name, r| r.evaluation_time rescue 0}
57end
58
59def resources_of_type(report, type)
60 report_resources(report).select{|r_name, r| r.resource_type == type}
61end
62
63def color(code, msg, reset=false)
64 colors = {
65 :red => "",
66 :green => "",
67 :yellow => "",
68 :cyan => "",
69 :bold => "",
70 :underline => "",
71 :reset => "",
72 }
73
74 colors.merge!(
75 :changed => colors[:yellow],
76 :unchanged => colors[:green],
77 :failed => colors[:red]
78 )
79
80 return "%s%s%s%s" % [colors.fetch(code, ""), msg, colors[:reset], reset ? colors.fetch(reset, "") : ""] if @options[:color]
81
82 msg
83end
84
85def print_report_summary(report)
86 puts color(:bold, "Report for %s in environment %s at %s" % [color(:underline, report.host, :bold), color(:underline, report.environment, :bold), color(:underline, report.time, :bold)])
87 puts
88 puts " Report File: %s" % @options[:report]
89 puts " Report Status: %s" % report.status
90 puts " Puppet Version: %s" % report.puppet_version
91 puts " Report Format: %s" % report.report_format
92 puts " Configuration Version: %s" % report.configuration_version
93 puts " UUID: %s" % report.transaction_uuid rescue nil
94 puts " Log Lines: %s %s" % [report.logs.size, @options[:logs] ? "" : "(show with --log)"]
95
96 puts
97end
98
99def print_report_motd(report, motd_path)
100 motd = []
101 header = "# #{report.host} #"
102 headline = "#" * header.size
103 motd << headline << header << headline << ''
104
105 motd << "Last puppet run happened at %s in environment %s." % [report.time, report.environment]
106
107 motd << "The result of this puppet run was %s." % color(report.status.to_sym, report.status)
108
109 if report.metrics.empty? or report.metrics["events"].nil?
110 motd << 'No Report Metrics.'
111 else
112 motd << 'Events:'
113 report.metrics["events"].values.each do |metric|
114 i, m, v = metric
115 motd.last << ' ' << [m, v].join(': ') << '.'
116 end
117 end
118
119 motd << '' << ''
120
121 File.write(motd_path, motd.join("\n"))
122end
123
124def print_report_metrics(report)
125 if report.metrics.empty?
126 puts color(:bold, "No Report Metrics")
127 puts
128 return
129 end
130
131 puts color(:bold, "Report Metrics:")
132 puts
133
134 padding = report.metrics.map{|i, m| m.values}.flatten(1).map{|i, m, v| m.size}.sort[-1] + 6
135
136 report.metrics.sort_by{|i, m| m.label}.each do |i, metric|
137 puts " %s:" % metric.label
138
139 metric.values.sort_by{|j, m, v| v}.reverse.each do |j, m, v|
140 puts "%#{padding}s: %s" % [m, v]
141 end
142
143 puts
144 end
145
146 puts
147end
148
149def print_summary_by_type(report)
150 summary = {}
151
152 report_resources(report).each do |resource|
153 if resource[0] =~ /^(.+?)\[/
154 name = $1
155
156 summary[name] ||= 0
157 summary[name] += 1
158 else
159 STDERR.puts "ERROR: Cannot parse type %s" % resource[0]
160 end
161 end
162
163 puts color(:bold, "Resources by resource type:")
164 puts
165
166 summary.sort_by{|k, v| v}.reverse.each do |type, count|
167 puts " %4d %s" % [count, type]
168 end
169
170 puts
171end
172
173def print_slow_resources(report, number=20)
174 if report.report_format < 4
175 puts color(:red, " Cannot print slow resources for report versions %d" % report.report_format)
176 puts
177 return
178 end
179
180 resources = resource_by_eval_time(report)
181
182 number = resources.size if resources.size < number
183
184 puts color(:bold, "Slowest %d resources by evaluation time:" % number)
185 puts
186
187 resources[(0-number)..-1].reverse.each do |r_name, r|
188 puts " %7.2f %s" % [r.evaluation_time, r_name]
189 end
190
191 puts
192end
193
194def print_logs(report)
195 puts color(:bold, "%d Log lines:" % report.logs.size)
196 puts
197
198 report.logs.each do |log|
199 puts " %s" % log.to_report
200 end
201
202 puts
203end
204
205def print_summary_by_containment_path(report, number=20)
206 resources = resource_with_evaluation_time(report)
207
208 containment = Hash.new(0)
209
210 resources.each do |r_name, r|
211 r.containment_path.each do |containment_path|
212 #if containment_path !~ /\[/
213 containment[containment_path] += r.evaluation_time
214 #end
215 end
216 end
217
218 number = containment.size if containment.size < number
219
220 puts color(:bold, "%d most time consuming containment" % number)
221 puts
222
223 containment.sort_by{|c, s| s}[(0-number)..-1].reverse.each do |c_name, evaluation_time|
224 puts " %7.2f %s" % [evaluation_time, c_name]
225 end
226
227 puts
228end
229
230def print_files(report, number=20)
231 resources = resources_of_type(report, "File")
232
233 files = {}
234
235 resources.each do |r_name, r|
236 if r_name =~ /^File\[(.+)\]$/
237 file = $1
238
239 if File.exist?(file) && File.readable?(file) && File.file?(file) && !File.symlink?(file)
240 files[file] = File.size?(file) || 0
241 end
242 end
243 end
244
245 number = files.size if files.size < number
246
247 puts color(:bold, "%d largest managed files" % number) + " (only those with full path as resource name that are readable)"
248 puts
249
250 files.sort_by{|f, s| s}[(0-number)..-1].reverse.each do |f_name, size|
251 puts " %9s %s" % [size.bytes_to_human, f_name]
252 end
253
254 puts
255end
256
257def get_reports_for_node(nodename)
258 Dir.glob("%s/%s/*.yaml" % [get_server_reports_dir, nodename]).sort_by{|p|File.basename(p, ".*")}
259end
260
261def load_report_for_node(nodename, report)
262 report_path = "%s/%s/%s.yaml" % [get_server_reports_dir, nodename, report]
263 puts report_path
264 load_report(report_path) unless report_path.nil?
265end
266
267def load_report_by_id(report)
268 report_glob = "%s/*/%s.yaml" % [get_server_reports_dir, report]
269 Dir.glob(report_glob).map do |report_path|
270 puts report_path
271 load_report(report_path) unless report_path.nil?
272 end.first
273end
274
275def load_last_report_for_node(nodename)
276 report_path = get_reports_for_node(nodename).last
277 load_report(report_path) unless report_path.nil?
278end
279
280def print_reports_for_node(nodename)
281 puts color(:bold, "Reports for %s" % nodename)
282 get_reports_for_node(nodename).each do |report_path|
283 prefix = File.basename(report_path, ".*")
284 report = load_report(report_path)
285 print_report_oneliner(report, prefix)
286 end
287end
288
289def print_report_oneliner(report, prefix)
290 puts "%s: %s" % [prefix, color(report.status.to_sym, report.status)]
291end
292
293def print_node_oneliner(nodename)
294 report = load_last_report_for_node(nodename)
295 print_report_oneliner(report, report.name) unless report.nil?
296end
297
298def print_server_nodes_status
299 puts color(:bold, 'Nodes list')
300 dir = get_server_reports_dir
301 puts color(:bold, 'No nodes found!') unless Puppet::FileSystem.exist?(dir)
302 Dir.glob("%s/*/" % dir).each do |node_path|
303 print_node_oneliner(File.basename(node_path))
304 end
305end
306
307def initialize_puppet
308 require 'puppet/util/run_mode'
309 Puppet.settings.preferred_run_mode = :agent
310 Puppet.settings.initialize_global_settings([])
311 Puppet.settings.initialize_app_defaults(Puppet::Settings.app_defaults_for_run_mode(Puppet.run_mode))
312end
313
314initialize_puppet
315
316opt = OptionParser.new
317
318@options = {
319 :logs => false,
320 :history => false,
321 :server => false,
322 :node => nil,
323 :motd => false,
324 :motd_path => '/etc/motd',
325 :count => 20,
326 :report => Puppet[:lastrunreport],
327 :reportid => nil,
328 :color => STDOUT.tty?}
329
330opt.on("--logs", "Show logs") do |val|
331 @options[:logs] = val
332end
333
334opt.on("--nodelist", "(Puppet Server) List Puppet nodes and the status of their last report") do |val|
335 @options[:server] = val
336end
337
338opt.on("--node [NODE]", "(Puppet Server) Use last report of a node") do |val|
339 @options[:node] = val
340end
341
342opt.on("--history", "(with --node) Print the reports history for a node") do |val|
343 @options[:history] = val
344end
345
346opt.on("--motd", "Produce an output suitable for MOTD") do |val|
347 @options[:motd] = val
348end
349
350opt.on("--motd-path [PATH]", "Path to the MOTD file to overwrite with the --motd option") do |val|
351 @options[:motd_path] = val
352end
353
354opt.on("--count [RESOURCES]", Integer, "Number of resources to show evaluation times for") do |val|
355 @options[:count] = val
356end
357
358opt.on("--report [REPORT]", "Path to the Puppet last run report") do |val|
359 abort("Could not find report %s" % val) unless File.readable?(val)
360 @options[:report] = val
361end
362
363opt.on("--report-id [REPORTID]", "(with --node) ID of the report to load") do |val|
364 @options[:reportid] = val
365end
366
367opt.on("--[no-]color", "Colorize the report") do |val|
368 @options[:color] = val
369end
370
371opt.parse!
372
373report = load_report(@options[:report]) unless @options[:server] or @options[:node]
374if @options[:node] and not @options[:history] and not @options[:reportid]
375 report = load_last_report_for_node(@options[:node])
376elsif @options[:node] and @options[:reportid]
377 report = load_report_for_node(@options[:node], @options[:reportid])
378elsif @options[:reportid]
379 report = load_report_by_id(@options[:reportid])
380end
381
382if @options[:server]
383 print_server_nodes_status
384elsif @options[:node] and @options[:history]
385 print_reports_for_node(@options[:node])
386elsif @options[:motd]
387 print_report_motd(report, @options[:motd_path])
388else
389 print_report_summary(report)
390 print_report_metrics(report)
391 print_summary_by_type(report)
392 print_slow_resources(report, @options[:count])
393 print_files(report, @options[:count])
394 print_summary_by_containment_path(report, @options[:count])
395 print_logs(report) if @options[:logs]
396end
diff --git a/modules/base_installation/manifests/cronie.pp b/modules/base_installation/manifests/cronie.pp
index 4df0e37..72f2d8f 100644
--- a/modules/base_installation/manifests/cronie.pp
+++ b/modules/base_installation/manifests/cronie.pp
@@ -19,13 +19,13 @@ class base_installation::cronie inherits base_installation {
19 } 19 }
20 cron { 'puppet-apply': 20 cron { 'puppet-apply':
21 ensure => present, 21 ensure => present,
22 command => "cd $base_installation::puppet_code_path ; puppet apply --test $base_installation::puppet_code_path/manifests/site.pp", 22 command => "cd $base_installation::puppet_code_path ; puppet apply $base_installation::puppet_code_path/manifests/site.pp",
23 user => root, 23 user => root,
24 minute => '*/20' 24 minute => '*/20'
25 } 25 }
26 cron { 'puppet-apply-reboot': 26 cron { 'puppet-apply-reboot':
27 ensure => present, 27 ensure => present,
28 command => "cd $base_installation::puppet_code_path ; puppet apply --test $base_installation::puppet_code_path/manifests/site.pp", 28 command => "cd $base_installation::puppet_code_path ; puppet apply $base_installation::puppet_code_path/manifests/site.pp",
29 user => root, 29 user => root,
30 special => "reboot" 30 special => "reboot"
31 } 31 }
diff --git a/modules/base_installation/manifests/puppet.pp b/modules/base_installation/manifests/puppet.pp
index a8dc641..b3ce492 100644
--- a/modules/base_installation/manifests/puppet.pp
+++ b/modules/base_installation/manifests/puppet.pp
@@ -27,6 +27,18 @@ class base_installation::puppet (
27 } 27 }
28 ### 28 ###
29 29
30 file { '/usr/local/sbin/i_puppet_reset_and_apply':
31 mode => "0755",
32 ensure => present,
33 source => "puppet:///modules/base_installation/scripts/puppet_reset_and_apply"
34 }
35
36 file { '/usr/local/sbin/i_puppet_report_print':
37 mode => "0755",
38 ensure => present,
39 source => "puppet:///modules/base_installation/scripts/report_print.rb"
40 }
41
30 unless empty(find_file($password_seed)) { 42 unless empty(find_file($password_seed)) {
31 $ldap_password = generate_password(24, $password_seed, "ldap") 43 $ldap_password = generate_password(24, $password_seed, "ldap")
32 $ssha_ldap_seed = generate_password(5, $password_seed, "ldap_seed") 44 $ssha_ldap_seed = generate_password(5, $password_seed, "ldap_seed")