mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add a Scaleway dynamic inventory plugin (#38739)
This commit is contained in:
parent
0f3480d359
commit
e45a5e1c86
3 changed files with 161 additions and 8 deletions
|
@ -76,3 +76,12 @@ class ScalewayAPI(object):
|
||||||
|
|
||||||
def update(self, path, data=None, headers=None):
|
def update(self, path, data=None, headers=None):
|
||||||
return self.send("UPDATE", path, data, headers)
|
return self.send("UPDATE", path, data, headers)
|
||||||
|
|
||||||
|
|
||||||
|
SCALEWAY_LOCATION = {
|
||||||
|
'par1': {'name': 'Paris 1', 'country': 'FR', "api_endpoint": 'https://cp-par1.scaleway.com'},
|
||||||
|
'EMEA-FR-PAR1': {'name': 'Paris 1', 'country': 'FR', "api_endpoint": 'https://cp-par1.scaleway.com'},
|
||||||
|
|
||||||
|
'ams1': {'name': 'Amsterdam 1', 'country': 'NL', "api_endpoint": 'https://cp-ams1.scaleway.com'},
|
||||||
|
'EMEA-NL-EVS': {'name': 'Amsterdam 1', 'country': 'NL', "api_endpoint": 'https://cp-ams1.scaleway.com'}
|
||||||
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ import time
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.basic import env_fallback
|
from ansible.module_utils.basic import env_fallback
|
||||||
from ansible.module_utils.six.moves.urllib.parse import quote as urlquote
|
from ansible.module_utils.six.moves.urllib.parse import quote as urlquote
|
||||||
from ansible.module_utils.scaleway import ScalewayAPI
|
from ansible.module_utils.scaleway import ScalewayAPI, SCALEWAY_LOCATION
|
||||||
|
|
||||||
SCALEWAY_COMMERCIAL_TYPES = [
|
SCALEWAY_COMMERCIAL_TYPES = [
|
||||||
|
|
||||||
|
@ -189,13 +189,6 @@ SCALEWAY_COMMERCIAL_TYPES = [
|
||||||
'X64-120GB',
|
'X64-120GB',
|
||||||
]
|
]
|
||||||
|
|
||||||
SCALEWAY_LOCATION = {
|
|
||||||
'par1': {'name': 'Paris 1', 'country': 'FR', "api_endpoint": 'https://cp-par1.scaleway.com'},
|
|
||||||
'EMEA-FR-PAR1': {'name': 'Paris 1', 'country': 'FR', "api_endpoint": 'https://cp-par1.scaleway.com'},
|
|
||||||
'ams1': {'name': 'Amsterdam 1', 'country': 'NL', "api_endpoint": 'https://cp-ams1.scaleway.com'},
|
|
||||||
'EMEA-NL-EVS': {'name': 'Amsterdam 1', 'country': 'NL', "api_endpoint": 'https://cp-ams1.scaleway.com'},
|
|
||||||
}
|
|
||||||
|
|
||||||
SCALEWAY_SERVER_STATES = (
|
SCALEWAY_SERVER_STATES = (
|
||||||
'stopped',
|
'stopped',
|
||||||
'stopping',
|
'stopping',
|
||||||
|
|
151
lib/ansible/plugins/inventory/scaleway.py
Normal file
151
lib/ansible/plugins/inventory/scaleway.py
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# Copyright (c) 2017 Ansible Project
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
name: scaleway
|
||||||
|
plugin_type: inventory
|
||||||
|
authors:
|
||||||
|
- Remy Leone <rleone@online.net>
|
||||||
|
short_description: Scaleway inventory source
|
||||||
|
description:
|
||||||
|
- Get inventory hosts from Scaleway
|
||||||
|
options:
|
||||||
|
regions:
|
||||||
|
description: Filter results on a specific Scaleway region
|
||||||
|
type: list
|
||||||
|
default:
|
||||||
|
- ams1
|
||||||
|
- par1
|
||||||
|
tags:
|
||||||
|
description: Filter results on a specific tag
|
||||||
|
type: list
|
||||||
|
oauth_token:
|
||||||
|
description: Scaleway OAuth token.
|
||||||
|
env:
|
||||||
|
# in order of precedence
|
||||||
|
- name: SCW_TOKEN
|
||||||
|
- name: SCW_API_KEY
|
||||||
|
- name: SCW_OAUTH_TOKEN
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
# scaleway_inventory.yml file in YAML format
|
||||||
|
# Example command line: ansible-inventory --list -i scaleway_inventory.yml
|
||||||
|
|
||||||
|
plugin: scaleway
|
||||||
|
regions:
|
||||||
|
- ams1
|
||||||
|
- par1
|
||||||
|
tags:
|
||||||
|
- foobar
|
||||||
|
'''
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleError
|
||||||
|
from ansible.plugins.inventory import BaseInventoryPlugin
|
||||||
|
from ansible.module_utils.scaleway import SCALEWAY_LOCATION
|
||||||
|
from ansible.module_utils.urls import open_url
|
||||||
|
|
||||||
|
|
||||||
|
def _fetch_information(token, url):
|
||||||
|
try:
|
||||||
|
response = open_url(url,
|
||||||
|
headers={'X-Auth-Token': token,
|
||||||
|
'Content-type': 'application/json'})
|
||||||
|
except Exception:
|
||||||
|
raise AnsibleError("Error while fetching %s" % url)
|
||||||
|
|
||||||
|
try:
|
||||||
|
raw_json = json.loads(response.read())
|
||||||
|
except ValueError:
|
||||||
|
raise AnsibleError("Incorrect JSON payload")
|
||||||
|
|
||||||
|
try:
|
||||||
|
return raw_json["servers"]
|
||||||
|
except KeyError:
|
||||||
|
raise AnsibleError("Incorrect format from the Scaleway API response")
|
||||||
|
|
||||||
|
|
||||||
|
def _build_server_url(api_endpoint):
|
||||||
|
return "/".join([api_endpoint, "servers"])
|
||||||
|
|
||||||
|
|
||||||
|
class InventoryModule(BaseInventoryPlugin):
|
||||||
|
NAME = 'scaleway'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(InventoryModule, self).__init__()
|
||||||
|
|
||||||
|
self.token = self.get_option("oauth_token")
|
||||||
|
self.config_data = None
|
||||||
|
|
||||||
|
def verify_file(self, path):
|
||||||
|
return "scaleway" in path
|
||||||
|
|
||||||
|
def _fill_host_variables(self, server_id, server_info):
|
||||||
|
targeted_attributes = (
|
||||||
|
"arch",
|
||||||
|
"commercial_type",
|
||||||
|
"organization",
|
||||||
|
"state",
|
||||||
|
"hostname",
|
||||||
|
"state"
|
||||||
|
)
|
||||||
|
for attribute in targeted_attributes:
|
||||||
|
self.inventory.set_variable(server_id, attribute, server_info[attribute])
|
||||||
|
|
||||||
|
self.inventory.set_variable(server_id, "tags", server_info["tags"])
|
||||||
|
self.inventory.set_variable(server_id, "ipv4", server_info["public_ip"]["address"])
|
||||||
|
|
||||||
|
def _get_zones(self):
|
||||||
|
config_zones = self.get_option("regions")
|
||||||
|
return set(SCALEWAY_LOCATION.keys()).intersection(config_zones)
|
||||||
|
|
||||||
|
def _get_tags(self):
|
||||||
|
return self.get_option("tags")
|
||||||
|
|
||||||
|
def match_groups(self, server_info):
|
||||||
|
server_zone = server_info["location"]["zone_id"]
|
||||||
|
server_tags = server_info["tags"]
|
||||||
|
|
||||||
|
# If no filtering is defined, all tags are valid groups
|
||||||
|
if self._get_tags() is None:
|
||||||
|
return set(server_tags).union((server_zone,))
|
||||||
|
|
||||||
|
matching_tags = set(server_tags).intersection(self._get_tags())
|
||||||
|
|
||||||
|
if not matching_tags:
|
||||||
|
return set()
|
||||||
|
else:
|
||||||
|
return matching_tags.union((server_zone,))
|
||||||
|
|
||||||
|
def do_zone_inventory(self, zone):
|
||||||
|
self.inventory.add_group(zone)
|
||||||
|
zone_info = SCALEWAY_LOCATION[zone]
|
||||||
|
|
||||||
|
url = _build_server_url(zone_info["api_endpoint"])
|
||||||
|
all_servers = _fetch_information(url=url, token=self.token)
|
||||||
|
|
||||||
|
for server_info in all_servers:
|
||||||
|
|
||||||
|
groups = self.match_groups(server_info)
|
||||||
|
print(groups)
|
||||||
|
server_id = server_info["id"]
|
||||||
|
|
||||||
|
for group in groups:
|
||||||
|
self.inventory.add_group(group=group)
|
||||||
|
self.inventory.add_host(group=group, host=server_id)
|
||||||
|
self._fill_host_variables(server_id=server_id, server_info=server_info)
|
||||||
|
|
||||||
|
def parse(self, inventory, loader, path, cache=True):
|
||||||
|
super(InventoryModule, self).parse(inventory, loader, path)
|
||||||
|
self.config_data = self._read_config_data(path=path)
|
||||||
|
|
||||||
|
for zone in self._get_zones():
|
||||||
|
self.do_zone_inventory(zone=zone)
|
Loading…
Reference in a new issue