DEV-187 feat: added dynamic inventory plugin
parent
efd0f08293
commit
1bfe37cddf
@ -0,0 +1,2 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory_plugins = ./inventory_plugins
|
||||||
@ -0,0 +1 @@
|
|||||||
|
/__pycache__/
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = r"""
|
||||||
|
name: netgo-hcloud
|
||||||
|
plugin_type: inventory
|
||||||
|
author:
|
||||||
|
- netgo
|
||||||
|
short_description: Ansible dynamic inventory plugin for Hetzner hcloud servers.
|
||||||
|
requirements:
|
||||||
|
- python >= 2.10
|
||||||
|
description:
|
||||||
|
- Reads inventory data from the Hetzner Cloud API.
|
||||||
|
extends_documentation_fragment:
|
||||||
|
- constructed
|
||||||
|
- inventory_cache
|
||||||
|
options:
|
||||||
|
plugin:
|
||||||
|
description: Marks this as an instance of the "netgo-hcloud" plugin
|
||||||
|
required: true
|
||||||
|
choices: ["netgo-hcloud"]
|
||||||
|
api_token:
|
||||||
|
description: The Hetzner Cloud API token.
|
||||||
|
required: true
|
||||||
|
env:
|
||||||
|
- name: HETZNER_CLOUD_TOKEN
|
||||||
|
stage:
|
||||||
|
description: The Hetzner Cloud stage.
|
||||||
|
required: true
|
||||||
|
env:
|
||||||
|
- name: HETZNER_CLOUD_STAGE
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from ansible.errors import AnsibleError
|
||||||
|
from ansible.module_utils.urls import open_url
|
||||||
|
from ansible.module_utils._text import to_native
|
||||||
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||||
|
from ansible.release import __version__
|
||||||
|
|
||||||
|
|
||||||
|
class MyHcloudAPI:
|
||||||
|
|
||||||
|
BASE = "https://api.hetzner.cloud"
|
||||||
|
|
||||||
|
def __init__(self, token, stage):
|
||||||
|
self.token = token
|
||||||
|
self.stage = stage
|
||||||
|
|
||||||
|
def get_servers(self):
|
||||||
|
api_url = "%s/v1/servers?label_selector=stage=" % self.BASE + self.stage
|
||||||
|
try:
|
||||||
|
response = open_url(
|
||||||
|
api_url,
|
||||||
|
headers={"Authorization": "Bearer " + self.token},
|
||||||
|
)
|
||||||
|
result = json.loads(response.read())
|
||||||
|
return result["servers"]
|
||||||
|
except ValueError:
|
||||||
|
raise AnsibleError("Incorrect JSON payload")
|
||||||
|
except Exception as e:
|
||||||
|
raise AnsibleError("Error while fetching %s: %s" % (api_url, to_native(e)))
|
||||||
|
|
||||||
|
|
||||||
|
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
|
|
||||||
|
NAME = "netgo-hcloud"
|
||||||
|
|
||||||
|
def verify_file(self, path):
|
||||||
|
return super(InventoryModule, self).verify_file(path) and path.endswith(
|
||||||
|
(self.NAME + ".yaml", self.NAME + ".yml")
|
||||||
|
)
|
||||||
|
|
||||||
|
def _read_servers_from_API(self):
|
||||||
|
servers = MyHcloudAPI(
|
||||||
|
self.get_option("api_token"), self.get_option("stage")
|
||||||
|
).get_servers()
|
||||||
|
return servers
|
||||||
|
|
||||||
|
def parse(self, inventory, loader, path, cache=True):
|
||||||
|
super(InventoryModule, self).parse(inventory, loader, path, cache)
|
||||||
|
config = self._read_config_data(path)
|
||||||
|
cache_key = self.get_cache_key(path)
|
||||||
|
|
||||||
|
# `cache` may be True or False at this point to indicate if the
|
||||||
|
# inventory is being refreshed. Get the user's cache option too
|
||||||
|
# to see if we should save the cache when it is changing.
|
||||||
|
user_cache_setting = self.get_option("cache")
|
||||||
|
|
||||||
|
# Read if the user has caching enabled and the cache isn't being
|
||||||
|
# refreshed.
|
||||||
|
attempt_to_read_cache = user_cache_setting and cache
|
||||||
|
|
||||||
|
# Update if the user has caching enabled and the cache is being
|
||||||
|
# refreshed; update this value to True if the cache has expired below.
|
||||||
|
cache_needs_update = user_cache_setting and not cache
|
||||||
|
|
||||||
|
# Attempt to read the cache if inventory isn't being refreshed and
|
||||||
|
# the user has caching enabled.
|
||||||
|
if attempt_to_read_cache:
|
||||||
|
try:
|
||||||
|
servers = self._cache[cache_key]
|
||||||
|
except KeyError:
|
||||||
|
# This occurs if the cache_key is not in the cache or if
|
||||||
|
# the cache_key expired, so the cache needs to be updated.
|
||||||
|
servers = self._read_servers_from_API()
|
||||||
|
cache_needs_update = True
|
||||||
|
else:
|
||||||
|
servers = self._read_servers_from_API()
|
||||||
|
|
||||||
|
if cache_needs_update:
|
||||||
|
self._cache[cache_key] = servers
|
||||||
|
|
||||||
|
self.populate(self.get_option("stage"), servers)
|
||||||
|
|
||||||
|
def populate(self, stage, servers):
|
||||||
|
# Add a default top group 'hcloud'
|
||||||
|
self.inventory.add_group(group="hcloud")
|
||||||
|
|
||||||
|
# Add a default top group 'stage_XYZ'
|
||||||
|
self.inventory.add_group(group="stage_" + stage)
|
||||||
|
|
||||||
|
for server in servers:
|
||||||
|
serverName = server["name"]
|
||||||
|
serverLabels = server["labels"]
|
||||||
|
serverService = serverLabels["service"]
|
||||||
|
|
||||||
|
self.inventory.add_group(group=serverService)
|
||||||
|
|
||||||
|
self.inventory.add_host(serverName, group="hcloud")
|
||||||
|
self.inventory.add_host(serverName, group=serverService)
|
||||||
|
self.inventory.add_host(serverName, group="stage_" + stage)
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
plugin: netgo-hcloud
|
||||||
|
|
||||||
|
stage: dev
|
||||||
|
|
||||||
|
api_token: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
61353364633862333333623664376666363464386461646131616465356534393935383132653730
|
||||||
|
3166333033326265356565646431326431336533656434620a626336333234303062323930363562
|
||||||
|
39656365663139343863646466343938313064653935646462333163343363656438656334316263
|
||||||
|
6132653139313530630a613037643634326231623733393432633163666139306138623837646231
|
||||||
|
61316362396566656430363539333137356464663038313334306634633431363237303736356134
|
||||||
|
61393836656634336231616338633265393638633763626632633066313461333736666436373338
|
||||||
|
39653732393838643261343730323666373736386662623236343133373762663630653735613130
|
||||||
|
36636230623930336465
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
plugin: netgo-hcloud
|
||||||
|
|
||||||
|
stage: qa
|
||||||
|
|
||||||
|
api_token: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
61353364633862333333623664376666363464386461646131616465356534393935383132653730
|
||||||
|
3166333033326265356565646431326431336533656434620a626336333234303062323930363562
|
||||||
|
39656365663139343863646466343938313064653935646462333163343363656438656334316263
|
||||||
|
6132653139313530630a613037643634326231623733393432633163666139306138623837646231
|
||||||
|
61316362396566656430363539333137356464663038313334306634633431363237303736356134
|
||||||
|
61393836656634336231616338633265393638633763626632633066313461333736666436373338
|
||||||
|
39653732393838643261343730323666373736386662623236343133373762663630653735613130
|
||||||
|
36636230623930336465
|
||||||
Loading…
Reference in New Issue