From 751d49446e32faad337b327a79b36c61d7fb0362 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Tue, 29 Apr 2014 17:21:23 -0700 Subject: [PATCH] Add tool to parse puppet reports puppetboard does not always tell us what we need to know. This tool is the beginning of trying to figure that out. Change-Id: I495986e40cdb2c062da9591a29feef5288f1bc57 --- tools/parse_puppet_report.py | 158 +++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 tools/parse_puppet_report.py diff --git a/tools/parse_puppet_report.py b/tools/parse_puppet_report.py new file mode 100644 index 0000000000..b113102c8b --- /dev/null +++ b/tools/parse_puppet_report.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import argparse +import yaml + + +class SafeYaml(yaml.YAMLObject): + yaml_loader = yaml.SafeLoader + + +class PuppetUtilMetric(SafeYaml): + yaml_tag = u'!ruby/object:Puppet::Util::Metric' + + def __init__(self, *args, **kwargs): + pass + + +class PuppetTransactionEvent(SafeYaml): + yaml_tag = u'!ruby/object:Puppet::Transaction::Event' + + def __init__(self, *args, **kwargs): + pass + + +class PuppetResourceStatus(object): + + def __init__( + self, resource, filename, line, evaluation_time, change_count, + out_of_sync_count, tags, time, events, out_of_sync, changed, + title, skipped, failed, resource_type): + self.resource = resource + self.filename = filename + self.line = line + self.evaluation_time = evaluation_time + self.change_count = change_count + self.out_of_sync_count = out_of_sync_count + self.tags = tags + self.time = time + self.events = events + self.out_of_sync = out_of_sync + self.changed = changed + self.title = title + self.skipped = skipped + self.failed = failed + self.resource_type = resource_type + if failed: + self.status = 'FAILED' + else: + self.status = 'SUCCEEDED' + + def __repr__(self): + if self.failed: + return 'FAILED: %s line %s' % (self.resource, self.line) + return "SUCCEEDED: %s" % self.resource + + +class PuppetTransactionReport(SafeYaml): + yaml_tag = u'!ruby/object:Puppet::Transaction::Report' + + def __init__( + self, status, metrics, host, configuration_version, + environment, puppet_version, time, report_format, + logs, resource_statuses, kind): + self.status = status + self.metrics = metrics + self.host = host + self.configuration_version = configuration_version, + self.environment = environment + self.puppet_version = puppet_version + self.time = time + self.report_format = report_format + self.logs = logs + self.resource_statuses = resource_statuses, + self.kind = kind + + def __repr__(self): + head = "## %s: %s - %s" % (self.status.upper(), self.host, self.time) + statuses = "\n".join([ + "%s: %s" % (resource, repr(status)) + for (resource, status) in self.resource_statuses.items()]) + logs = "\n".join([repr(log) for log in self.logs]) + return "%s\n%s\n%s" % (head, statuses, logs) + + def failed(self): + if self.status == 'failed': + return True + return any([s.failed for (r, s) in self.resource_statuses.items()]) + + +class PuppetUtilLog(SafeYaml): + yaml_tag = u'!ruby/object:Puppet::Util::Log' + + def __init__(self, level, tags, time, message, source): + self.level = level + self.tags = tags + self.time = time + self.message = message + self.source = source + + def __repr__(self): + return "%s: %s, %s" % (self.level, self.time, self.message) + + +class RubySym(object): + def __init__(self, value): + self.value = value + + def __repr__(self): + return self.value.upper() + + +def resource_constructor(loader, node): + value = loader.construct_mapping(node) + value['filename'] = value['file'] + del(value['file']) + return PuppetResourceStatus(**value) + + +def sym_constructor(loader, node): + value = loader.construct_scalar(node) + return RubySym(value) + + +def main(): + yaml.add_constructor( + u'!ruby/object:Puppet::Resource::Status', resource_constructor, + Loader=yaml.SafeLoader) + yaml.add_constructor(u'!ruby/sym', sym_constructor, Loader=yaml.SafeLoader) + + parser = argparse.ArgumentParser(description='Puppet Report Processor') + parser.add_argument('logfile') + parser.add_argument( + '-v', dest='verbose', action='store_true', help='verbose') + + args = parser.parse_args() + results = yaml.safe_load(open(args.logfile, 'r').read()) + if results.failed(): + print "FAILED", args.logfile + else: + print "SUCESS", args.logfile + if args.verbose: + print results + +if __name__ == '__main__': + main()