#!/usr/bin/python # Copyright (c) 2015 IBM # # This module is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this software. If not, see . import json import os import requests DOCUMENTATION = ''' --- module: puppet_post_puppetdb short_description: Posts facts and logfile to a puppetdb server description: - Posts facts and logfile to a puppetdb server version_added: "2.0" options: puppetdb: description: - The hostname of the puppetdb server to post to required: true hostvars: desciption: - Ansible hostvars to pull facts from required: true logfile: desciption: - Absolute path of the Puppet logfile to post required: true whoami: description: - FQDN of the host that is contacting the puppetdb required: true environment: desciption: - Puppet environment to be used. required: false default: production requirements: [ puppet ] author: "Monty Taylor (@emonty)" ''' EXAMPLES = ''' # Post the facter facts to puppetdb.openstack.org - puppet_post_facts: hostvars: hostvars[inventory_hostname] puppetdb: puppetdb.openstack.org logfile: /var/lib/puppet/reports/review.openstack.org/20151030.json whoami: puppetmaster.openstack.org ''' def main(): module = AnsibleModule( argument_spec=dict( puppetdb=dict(required=True), hostvars=dict(required=True), logfile=dict(required=True), whoami=dict(required=True), environment=dict(required=False, default='production'), ), supports_check_mode=True, ) p = module.params endpoint = '{puppetdb}/v3/commands'.format(puppetdb=p['puppetdb']) fqdn = p['hostvars']['inventory_hostname'] whoami = p['whoami'] cert = '/var/lib/puppet/ssl/certs/{whoami}.pem'.format(whoami=whoami) key = '/var/lib/puppet/ssl/private_keys/{whoami}.pem'.format(whoami=whoami) cacert = '/var/lib/puppet/ssl/ca/ca_crt.pem' requests_kwargs = dict(cert=(cert, key), verify=cacert) try: dt = os.path.basename(p['logfile']).split('_')[0] timestamp = "{0}-{1}-{2}".format(dt[0:4], dt[4:6], dt[6:8]) except: # we don't REALLY care about this - but might as well give it a stab timestamp = '2015-01-01' facts = {} for k, v in p['hostvars'].items(): if k.startswith('facter_'): facts[k[7:]] = v # remove some problematic facts from facts (if they exist) # files can be a long list of files in a directory if facts.get('files') is not None: del facts['files'] # groups can be the entire ansible inventory if facts.get('groups') is not None: del facts['groups'] if facts: # Don't post facts update if we don't have facts payload = { "command": "replace facts", "version": 3, "payload": { "name": fqdn, "environment": p['environment'], "producer-timestamp": timestamp, "values": facts }} payload_dump = p['logfile'][:-4] + "facts_payload.json" with open(payload_dump, 'w') as f: f.write(json.dumps(payload)) try: r = requests.post(endpoint, json=payload, **requests_kwargs) except Exception as e: module.fail_json( msg="Exception: {e}".format(e=e), puppetdb=p['puppetdb'], endpoint=endpoint, logfile=payload_dump) log_data = json.load(open(p['logfile'], 'r')) try: r = requests.post(endpoint, json=log_data, **requests_kwargs) except Exception as e: module.fail_json( msg="Exception: {e}".format(e=e), puppetdb=p['puppetdb'], endpoint=endpoint, logfile=p['logfile']) if r.status_code != 200: module.fail_json( rc=r.status_code, msg="Failed to post log data to {puppetdb}".format( puppetdb=p['puppetdb'])) # success with changes module.exit_json(rc=0, changed=True) # import module snippets from ansible.module_utils.basic import * if __name__ == '__main__': main()