WIP! Added more processing. Getting there, but I want to go watch Krapopolis.
This commit is contained in:
parent
b360cc13b6
commit
d89d2bb89b
|
|
@ -60,7 +60,7 @@ from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cachea
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
# Specific for the NetbirdAPI Class
|
# Specific for the NetbirdAPI Class
|
||||||
import json
|
import json, jsonpickle
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import requests
|
import requests
|
||||||
|
|
@ -74,9 +74,6 @@ display = Display()
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
NAME = "dominion_solutions.netbird"
|
NAME = "dominion_solutions.netbird"
|
||||||
|
|
||||||
_redirected_names = ["netbird", "dominion_solutions.netbird"]
|
|
||||||
|
|
||||||
_load_name = NAME
|
_load_name = NAME
|
||||||
|
|
||||||
def _build_client(self, loader):
|
def _build_client(self, loader):
|
||||||
|
|
@ -100,11 +97,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
def _add_groups(self):
|
def _add_groups(self):
|
||||||
""" Add peer groups to the inventory. """
|
""" Add peer groups to the inventory. """
|
||||||
self.netbird_groups = set(
|
self.netbird_groups = set(
|
||||||
filter(None, [
|
filter(None,
|
||||||
peer.data.get("groups")
|
[group[0].get('name') for group in [item.data.get('groups') for l in self.peers for item in self.peers]])
|
||||||
for peer
|
|
||||||
in self.peers
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
for group in self.netbird_groups:
|
for group in self.netbird_groups:
|
||||||
self.inventory.add_group(group)
|
self.inventory.add_group(group)
|
||||||
|
|
@ -113,7 +107,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
""" Add peers to the groups in the inventory. """
|
""" Add peers to the groups in the inventory. """
|
||||||
for peer in self.peers:
|
for peer in self.peers:
|
||||||
for group in peer.data.get("groups"):
|
for group in peer.data.get("groups"):
|
||||||
self.inventory.add_host(peer.name, group=group)
|
self.inventory.add_host(peer.label, group=group.get('name'))
|
||||||
|
|
||||||
def _get_peer_inventory(self):
|
def _get_peer_inventory(self):
|
||||||
"""Get the inventory from the Netbird API"""
|
"""Get the inventory from the Netbird API"""
|
||||||
|
|
@ -128,8 +122,15 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
groups = self.get_option('groups')
|
groups = self.get_option('groups')
|
||||||
if groups:
|
if groups:
|
||||||
self.peers = [
|
self.peers = [
|
||||||
|
# 202410221-MJH: This list comprehension that filters the peers is a little hard to read. I'm sorry.
|
||||||
peer for peer in self.peers
|
peer for peer in self.peers
|
||||||
if any(group in peer.data['groups'] for group in groups)
|
if any(
|
||||||
|
group
|
||||||
|
in [
|
||||||
|
# Emulate a pluck here to grab the group names from the peer data.
|
||||||
|
g.get('name') for g in peer.data.get('groups')
|
||||||
|
]
|
||||||
|
for group in groups)
|
||||||
]
|
]
|
||||||
|
|
||||||
def _add_hostvars_for_peers(self):
|
def _add_hostvars_for_peers(self):
|
||||||
|
|
@ -141,7 +142,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
if ip_style == 'api' and hostvar_key in ['ip', 'ipv6']:
|
if ip_style == 'api' and hostvar_key in ['ip', 'ipv6']:
|
||||||
continue
|
continue
|
||||||
self.inventory.set_variable(
|
self.inventory.set_variable(
|
||||||
peer.name,
|
peer.label,
|
||||||
hostvar_key,
|
hostvar_key,
|
||||||
hostvars[hostvar_key]
|
hostvars[hostvar_key]
|
||||||
)
|
)
|
||||||
|
|
@ -191,7 +192,6 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
self.include_disconnected = self.get_option('include_disconnected')
|
self.include_disconnected = self.get_option('include_disconnected')
|
||||||
self._build_client(loader)
|
self._build_client(loader)
|
||||||
self._get_peer_inventory()
|
self._get_peer_inventory()
|
||||||
self._add_hostvars_for_peers()
|
|
||||||
|
|
||||||
if update_cache:
|
if update_cache:
|
||||||
self._cache[cache_key] = self._cacheable_inventory()
|
self._cache[cache_key] = self._cacheable_inventory()
|
||||||
|
|
@ -199,9 +199,32 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
self.populate()
|
self.populate()
|
||||||
|
|
||||||
def populate(self):
|
def populate(self):
|
||||||
|
""" Populate the inventory with the peers from the Netbird API. """
|
||||||
|
strict = self.get_option('strict')
|
||||||
|
|
||||||
self._filter_by_config()
|
self._filter_by_config()
|
||||||
|
|
||||||
self._add_groups()
|
self._add_groups()
|
||||||
self._add_peers_to_group()
|
self._add_peers_to_group()
|
||||||
|
self._add_hostvars_for_peers()
|
||||||
|
for peer in self.peers:
|
||||||
|
variables = self.inventory.get_host(peer.label).get_vars()
|
||||||
|
self._add_host_to_composed_groups(
|
||||||
|
self.get_option('groups'),
|
||||||
|
variables,
|
||||||
|
peer.label,
|
||||||
|
strict=strict)
|
||||||
|
self._add_host_to_keyed_groups(
|
||||||
|
self.get_option('keyed_groups'),
|
||||||
|
variables,
|
||||||
|
peer.label,
|
||||||
|
strict=strict)
|
||||||
|
self._set_composite_vars(
|
||||||
|
self.get_option('compose'),
|
||||||
|
variables,
|
||||||
|
peer.label,
|
||||||
|
strict=strict)
|
||||||
|
raise AnsibleError(f"self.inventory: {jsonpickle.encode(self.inventory)}")
|
||||||
|
|
||||||
|
|
||||||
# This is a very limited wrapper for the netbird API.
|
# This is a very limited wrapper for the netbird API.
|
||||||
|
|
@ -225,7 +248,7 @@ class NetbirdApi:
|
||||||
response = requests.request("GET", url, headers=headers)
|
response = requests.request("GET", url, headers=headers)
|
||||||
peer_json = json.loads(response.text)
|
peer_json = json.loads(response.text)
|
||||||
for current_peer_map in peer_json:
|
for current_peer_map in peer_json:
|
||||||
current_peer = Peer(current_peer_map["hostname"], current_peer_map["id"], current_peer_map)
|
current_peer = Peer(current_peer_map["hostname"], current_peer_map['dns_label'], current_peer_map["id"], current_peer_map)
|
||||||
peers.append(current_peer)
|
peers.append(current_peer)
|
||||||
return peers
|
return peers
|
||||||
|
|
||||||
|
|
@ -290,7 +313,8 @@ class Peer:
|
||||||
def _raw_json(self):
|
def _raw_json(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def __init__(self, name, id, data):
|
def __init__(self, name, label, id, data):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.label = label
|
||||||
self.id = id
|
self.id = id
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ cffi==1.16.0
|
||||||
cryptography==42.0.2
|
cryptography==42.0.2
|
||||||
epdb==0.15.1
|
epdb==0.15.1
|
||||||
Jinja2==3.1.3
|
Jinja2==3.1.3
|
||||||
|
jsonpickle==3.0.3
|
||||||
MarkupSafe==2.1.5
|
MarkupSafe==2.1.5
|
||||||
packaging==23.2
|
packaging==23.2
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
plugin: dominion_solutions.netbird
|
||||||
|
api_key: nbp_1234567890123456789012345678901234567
|
||||||
|
api_url: https://netbird.example.com/api/v1
|
||||||
|
include_disconnected: Yes
|
||||||
|
ip_style: plain
|
||||||
|
groups:
|
||||||
|
- "All"
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"accessible_peers_count": 1,
|
||||||
|
"approval_required": false,
|
||||||
|
"connected": false,
|
||||||
|
"dns_label": "apple.netbird.cloud",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": "2a3b4c5d6e7f8g9h0i1j",
|
||||||
|
"name": "All",
|
||||||
|
"peers_count": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hostname": "apple",
|
||||||
|
"id": "3a7b2c1d4e5f6g8h9i0j",
|
||||||
|
"ip": "100.0.0.42",
|
||||||
|
"last_login": "2024-02-10T22:01:27.744131502Z",
|
||||||
|
"last_seen": "2024-02-11T03:21:42.202104672Z",
|
||||||
|
"login_expiration_enabled": true,
|
||||||
|
"login_expired": false,
|
||||||
|
"name": "apple",
|
||||||
|
"os": "Linux Mint 21.3",
|
||||||
|
"ssh_enabled": false,
|
||||||
|
"ui_version": "netbird-desktop-ui/0.25.7",
|
||||||
|
"user_id": "auth0|ABC123xyz4567890",
|
||||||
|
"version": "0.25.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"accessible_peers_count": 1,
|
||||||
|
"approval_required": false,
|
||||||
|
"connected": true,
|
||||||
|
"dns_label": "banana.netbird.cloud",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": "2a3b4c5d6e7f8g9h0i1j",
|
||||||
|
"name": "All",
|
||||||
|
"peers_count": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hostname": "banana",
|
||||||
|
"id": "3a7b2c1d4e5f6g8h9i0j",
|
||||||
|
"ip": "100.0.0.61",
|
||||||
|
"last_login": "2024-02-02T11:20:05.934889112Z",
|
||||||
|
"last_seen": "2024-02-16T16:14:35.853243309Z",
|
||||||
|
"login_expiration_enabled": false,
|
||||||
|
"login_expired": false,
|
||||||
|
"name": "banana",
|
||||||
|
"os": "Alpine Linux 3.19.1",
|
||||||
|
"ssh_enabled": false,
|
||||||
|
"ui_version": "",
|
||||||
|
"user_id": "",
|
||||||
|
"version": "0.25.5"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -20,7 +20,7 @@ from ansible.utils.display import Display
|
||||||
from ansible_collections.dominion_solutions.netbird.plugins.inventory.netbird import InventoryModule, NetbirdApi, Peer
|
from ansible_collections.dominion_solutions.netbird.plugins.inventory.netbird import InventoryModule, NetbirdApi, Peer
|
||||||
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
import json
|
import json,jsonpickle
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ def netbird_api():
|
||||||
with open('tests/unit/module_utils/inventories/fixtures/peers.json') as peers_file:
|
with open('tests/unit/module_utils/inventories/fixtures/peers.json') as peers_file:
|
||||||
peers_map = json.load(peers_file)
|
peers_map = json.load(peers_file)
|
||||||
for data in peers_map:
|
for data in peers_map:
|
||||||
response_data.append(Peer(data['hostname'], data['id'], data))
|
response_data.append(Peer(data['hostname'], data['dns_label'], data['id'], data))
|
||||||
|
|
||||||
mock_netbird_api.ListPeers = MagicMock(return_value=response_data)
|
mock_netbird_api.ListPeers = MagicMock(return_value=response_data)
|
||||||
|
|
||||||
|
|
@ -73,4 +73,5 @@ def test_get_peer_data(inventory, netbird_api):
|
||||||
inventory.client = netbird_api
|
inventory.client = netbird_api
|
||||||
inventory.parse(InventoryData(), loader, path, False)
|
inventory.parse(InventoryData(), loader, path, False)
|
||||||
assert inventory.inventory is not None
|
assert inventory.inventory is not None
|
||||||
raise AnsibleError(inventory.inventory)
|
assert inventory.inventory.hosts is not None
|
||||||
|
assert len(inventory.inventory.hosts) == 1
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
requests>=2.31.0
|
requests>=2.31.0
|
||||||
|
jsonpickle==3.0.3
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue