diff --git a/README.md b/README.md index a3d0677..c1358a0 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,10 @@ Once the required libraries (see above) have been installed on the server: 1. Copy `datadog_callback.py` to your playbook callback directory (by default `callback_plugins/` in your playbook's root directory). Create the directory if it doesn't exist. -2. You have 3 ways to set your API key. The callback will first use the - environment variable, then the configuration file, then hostvars/vault. +2. You have 4 ways to set your API key. The callback will first use the + environment variable, then the configuration file, then hostvars/vault, + and a specific host's hostvars. For more information, see the environment + variable configuration. ##### Using environment variable @@ -37,6 +39,11 @@ variable `DATADOG_SITE=datadoghq.eu`. To send data to a custom URL you can set the environment variable `DATADOG_URL=`. +To configure the callback to use variables from a specific inventory host, +you can set the environment variable `ANSIBLE_DATADOG_CALLBACK_INVENTORY_HOST`. +The callback will then query that host's variables for the API key, datadog URL, +and datadog site. + ##### Using a yaml file Create a `datadog_callback.yml` file alongside `datadog_callback.py`, diff --git a/datadog_callback.py b/datadog_callback.py index 2a6703d..93f0c14 100644 --- a/datadog_callback.py +++ b/datadog_callback.py @@ -3,8 +3,10 @@ import getpass import logging import os +import socket import time + try: import datadog import yaml @@ -241,6 +243,25 @@ def v2_playbook_on_start(self, playbook): inventory = ','.join(inventory) self._inventory_name = ','.join([os.path.basename(os.path.realpath(name)) for name in inventory.split(',') if name]) + def get_from_hostvars(self, variable_name, required=False): + hostvars = self.play.get_variable_manager()._hostvars + if not hostvars: + raise Exception("hostvars could not be loaded") + hosts = [ 'localhost', socket.gethostname() ] + if os.environ.get("ANSIBLE_DATADOG_CALLBACK_INVENTORY_HOST"): + hosts.insert(0, os.environ.get("ANSIBLE_DATADOG_CALLBACK_INVENTORY_HOST")) + for host in hosts: + if host not in hostvars: + continue + value = hostvars[host].get(variable_name, None) + if value is not None: + return value + if required: + raise Exception("variable {} is not defined in the host vars for hosts: {}".format( + variable_name, hosts)) + else: + return None + def v2_playbook_on_play_start(self, play): # On Ansible v2, Ansible doesn't set `self.play` automatically self.play = play @@ -253,21 +274,17 @@ def v2_playbook_on_play_start(self, play): # If there is no api key defined in config file, try to get it from hostvars if api_key == '': - hostvars = self.play.get_variable_manager()._hostvars - - if not hostvars: - print("No api_key found in the config file ({0}) and hostvars aren't set: disabling Datadog callback plugin".format(config_path)) + try: + api_key = self.get_from_hostvars('datadog_api_key', True) + if not dd_url: + dd_url = self.get_from_hostvars('datadog_url') + + if not dd_site: + dd_site = self.get_from_hostvars('datadog_site') + except Exception as e: + print('No "api_key" found in the config file ({0}) and could not load from the inventory ({1}): disabling Datadog callback plugin'. + format(config_path, e)) self.disabled = True - else: - try: - api_key = hostvars['localhost']['datadog_api_key'] - if not dd_url: - dd_url = hostvars['localhost'].get('datadog_url') - if not dd_site: - dd_site = hostvars['localhost'].get('datadog_site') - except Exception as e: - print('No "api_key" found in the config file ({0}) and "datadog_api_key" is not set in the hostvars: disabling Datadog callback plugin'.format(config_path)) - self.disabled = True if not dd_url: if dd_site: