inventory: vultr: implement keyed groups and filter (#53869)
This commit is contained in:
parent
1e4dab822b
commit
ab238071e3
1 changed files with 78 additions and 16 deletions
|
@ -1,4 +1,5 @@
|
||||||
# (c) 2018, Yanis Guenane <yanis+ansible@guenane.org>
|
# Copyright (c) 2018, Yanis Guenane <yanis+ansible@guenane.org>
|
||||||
|
# Copyright (c) 2019, René Moser <mail@renemoser.net>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
@ -9,25 +10,35 @@ DOCUMENTATION = r'''
|
||||||
name: vultr
|
name: vultr
|
||||||
plugin_type: inventory
|
plugin_type: inventory
|
||||||
author:
|
author:
|
||||||
- "Yanis Guenane (@Spredzy)"
|
- Yanis Guenane (@Spredzy)
|
||||||
|
- René Moser (@resmo)
|
||||||
short_description: Vultr inventory source
|
short_description: Vultr inventory source
|
||||||
|
version_added: "2.7"
|
||||||
|
extends_documentation_fragment:
|
||||||
|
- constructed
|
||||||
description:
|
description:
|
||||||
- Get inventory hosts from Vultr public cloud.
|
- Get inventory hosts from Vultr public cloud.
|
||||||
- Uses C(api_config), C(~/.vultr.ini), C(./vultr.ini) or VULTR_API_CONFIG path to config file.
|
- Uses an YAML configuration file ending with either I(vultr.yml) or I(vultr.yaml) to set parameter values (also see examples).
|
||||||
|
- Uses I(api_config), I(~/.vultr.ini), I(./vultr.ini) or C(VULTR_API_CONFIG) pointing to a Vultr credentials INI file
|
||||||
|
(see U(https://docs.ansible.com/ansible/latest/scenario_guides/guide_vultr.html)).
|
||||||
options:
|
options:
|
||||||
plugin:
|
plugin:
|
||||||
description: token that ensures this is a source file for the 'vultr' plugin.
|
description: Token that ensures this is a source file for the 'vultr' plugin.
|
||||||
|
type: string
|
||||||
required: True
|
required: True
|
||||||
choices: ['vultr']
|
choices: [ vultr ]
|
||||||
api_account:
|
api_account:
|
||||||
description: Specify the account to be used.
|
description: Specify the account to be used.
|
||||||
|
type: string
|
||||||
default: default
|
default: default
|
||||||
api_config:
|
api_config:
|
||||||
description: Path to the vultr configuration file. If not specified will be taken from regular Vultr configuration.
|
description: Path to the vultr configuration file. If not specified will be taken from regular Vultr configuration.
|
||||||
|
type: path
|
||||||
env:
|
env:
|
||||||
- name: VULTR_API_CONFIG
|
- name: VULTR_API_CONFIG
|
||||||
api_key:
|
api_key:
|
||||||
description: Vultr API key. If not specified will be taken from regular Vultr configuration.
|
description: Vultr API key. If not specified will be taken from regular Vultr configuration.
|
||||||
|
type: string
|
||||||
env:
|
env:
|
||||||
- name: VULTR_API_KEY
|
- name: VULTR_API_KEY
|
||||||
hostname:
|
hostname:
|
||||||
|
@ -38,23 +49,46 @@ DOCUMENTATION = r'''
|
||||||
- v4_main_ip
|
- v4_main_ip
|
||||||
- v6_main_ip
|
- v6_main_ip
|
||||||
- name
|
- name
|
||||||
|
filter_by_tag:
|
||||||
|
description: Only return servers filtered by this tag
|
||||||
|
type: string
|
||||||
|
version_added: "2.8"
|
||||||
|
strict:
|
||||||
|
version_added: "2.8"
|
||||||
|
compose:
|
||||||
|
version_added: "2.8"
|
||||||
|
groups:
|
||||||
|
version_added: "2.8"
|
||||||
|
keyed_groups:
|
||||||
|
version_added: "2.8"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = r'''
|
||||||
# vultr_inventory.yml file in YAML format
|
# inventory_vultr.yml file in YAML format
|
||||||
# Example command line: ansible-inventory --list -i vultr_inventory.yml
|
# Example command line: ansible-inventory --list -i inventory_vultr.yml
|
||||||
|
|
||||||
|
# Group by a region as lower case and with prefix e.g. "vultr_region_amsterdam" and by OS without prefix e.g. "CentOS_7_x64"
|
||||||
plugin: vultr
|
plugin: vultr
|
||||||
|
keyed_groups:
|
||||||
|
- prefix: vultr_region
|
||||||
|
key: region | lower
|
||||||
|
- separator: ""
|
||||||
|
key: os
|
||||||
|
|
||||||
|
# Pass a tag filter to the API
|
||||||
|
plugin: vultr
|
||||||
|
filter_by_tag: Cache
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.plugins.inventory import BaseInventoryPlugin
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
||||||
from ansible.module_utils.six.moves import configparser
|
from ansible.module_utils.six.moves import configparser
|
||||||
from ansible.module_utils.urls import open_url
|
from ansible.module_utils.urls import open_url
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
from ansible.module_utils.vultr import Vultr, VULTR_API_ENDPOINT, VULTR_USER_AGENT
|
from ansible.module_utils.vultr import Vultr, VULTR_API_ENDPOINT, VULTR_USER_AGENT
|
||||||
|
from ansible.module_utils.six.moves.urllib.parse import quote
|
||||||
|
|
||||||
|
|
||||||
SCHEMA = {
|
SCHEMA = {
|
||||||
|
@ -104,8 +138,10 @@ def _load_conf(path, account):
|
||||||
return Vultr.read_ini_config(account)
|
return Vultr.read_ini_config(account)
|
||||||
|
|
||||||
|
|
||||||
def _retrieve_servers(api_key):
|
def _retrieve_servers(api_key, tag_filter=None):
|
||||||
api_url = '%s/v1/server/list' % VULTR_API_ENDPOINT
|
api_url = '%s/v1/server/list' % VULTR_API_ENDPOINT
|
||||||
|
if tag_filter is not None:
|
||||||
|
api_url = api_url + '?tag=%s' % quote(tag_filter)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = open_url(
|
response = open_url(
|
||||||
|
@ -121,9 +157,17 @@ def _retrieve_servers(api_key):
|
||||||
raise AnsibleError("Error while fetching %s: %s" % (api_url, to_native(e)))
|
raise AnsibleError("Error while fetching %s: %s" % (api_url, to_native(e)))
|
||||||
|
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin):
|
class InventoryModule(BaseInventoryPlugin, Constructable):
|
||||||
|
|
||||||
NAME = 'vultr'
|
NAME = 'vultr'
|
||||||
|
|
||||||
|
def verify_file(self, path):
|
||||||
|
valid = False
|
||||||
|
if super(InventoryModule, self).verify_file(path):
|
||||||
|
if path.endswith(('vultr.yaml', 'vultr.yml')):
|
||||||
|
valid = True
|
||||||
|
return valid
|
||||||
|
|
||||||
def parse(self, inventory, loader, path, cache=True):
|
def parse(self, inventory, loader, path, cache=True):
|
||||||
super(InventoryModule, self).parse(inventory, loader, path)
|
super(InventoryModule, self).parse(inventory, loader, path)
|
||||||
self._read_config_data(path=path)
|
self._read_config_data(path=path)
|
||||||
|
@ -135,14 +179,32 @@ class InventoryModule(BaseInventoryPlugin):
|
||||||
raise AnsibleError('Could not find an API key. Check inventory file and Vultr configuration files.')
|
raise AnsibleError('Could not find an API key. Check inventory file and Vultr configuration files.')
|
||||||
|
|
||||||
hostname_preference = self.get_option('hostname')
|
hostname_preference = self.get_option('hostname')
|
||||||
for server in _retrieve_servers(api_key):
|
|
||||||
|
# Add a top group 'vultr'
|
||||||
|
self.inventory.add_group(group='vultr')
|
||||||
|
|
||||||
|
# Filter by tag is supported by the api with a query
|
||||||
|
filter_by_tag = self.get_option('filter_by_tag')
|
||||||
|
for server in _retrieve_servers(api_key, filter_by_tag):
|
||||||
|
|
||||||
server = Vultr.normalize_result(server, SCHEMA)
|
server = Vultr.normalize_result(server, SCHEMA)
|
||||||
for group in ['region', 'os']:
|
|
||||||
self.inventory.add_group(group=server[group])
|
self.inventory.add_host(host=server['name'], group='vultr')
|
||||||
self.inventory.add_host(group=server[group], host=server['name'])
|
|
||||||
|
|
||||||
for attribute, value in server.items():
|
for attribute, value in server.items():
|
||||||
self.inventory.set_variable(server['name'], attribute, value)
|
self.inventory.set_variable(server['name'], attribute, value)
|
||||||
|
|
||||||
if hostname_preference != 'name':
|
if hostname_preference != 'name':
|
||||||
self.inventory.set_variable(server['name'], 'ansible_host', server[hostname_preference])
|
self.inventory.set_variable(server['name'], 'ansible_host', server[hostname_preference])
|
||||||
|
|
||||||
|
# Use constructed if applicable
|
||||||
|
strict = self.get_option('strict')
|
||||||
|
|
||||||
|
# Composed variables
|
||||||
|
self._set_composite_vars(self.get_option('compose'), server, server['name'], strict=strict)
|
||||||
|
|
||||||
|
# Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group
|
||||||
|
self._add_host_to_composed_groups(self.get_option('groups'), server, server['name'], strict=strict)
|
||||||
|
|
||||||
|
# Create groups based on variable values and add the corresponding hosts to it
|
||||||
|
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), server, server['name'], strict=strict)
|
||||||
|
|
Loading…
Reference in a new issue