Files
2025-12-18 11:25:41 +01:00

254 lines
6.5 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2024, Community
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Ansible module for managing NetBird groups."""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r'''
---
module: netbird_group
short_description: Manage NetBird groups
description:
- Create, update, and delete groups in NetBird.
- Groups are used to organize peers and define access policies.
version_added: "1.0.0"
author:
- Community
options:
state:
description:
- The desired state of the group.
type: str
choices: ['present', 'absent']
default: present
group_id:
description:
- The unique identifier of the group.
- Required when state is absent or when updating by ID.
type: str
name:
description:
- Name of the group.
- Required when creating a new group.
type: str
peers:
description:
- List of peer IDs to include in the group.
type: list
elements: str
default: []
resources:
description:
- List of resource objects for the group.
type: list
elements: dict
extends_documentation_fragment:
- community.ansible_netbird.netbird
requirements:
- python >= 3.6
'''
EXAMPLES = r'''
- name: Create a group
community.ansible_netbird.netbird_group:
api_url: "https://netbird.example.com"
api_token: "{{ netbird_token }}"
name: "developers"
state: present
- name: Create a group with peers
community.ansible_netbird.netbird_group:
api_url: "https://netbird.example.com"
api_token: "{{ netbird_token }}"
name: "production-servers"
peers:
- "peer-id-1"
- "peer-id-2"
state: present
- name: Update group peers
community.ansible_netbird.netbird_group:
api_url: "https://netbird.example.com"
api_token: "{{ netbird_token }}"
group_id: "group-id-123"
peers:
- "peer-id-1"
- "peer-id-2"
- "peer-id-3"
state: present
- name: Delete a group
community.ansible_netbird.netbird_group:
api_url: "https://netbird.example.com"
api_token: "{{ netbird_token }}"
group_id: "group-id-123"
state: absent
'''
RETURN = r'''
group:
description: The group object.
returned: success
type: dict
contains:
id:
description: Group ID.
type: str
name:
description: Group name.
type: str
peers_count:
description: Number of peers in the group.
type: int
peers:
description: List of peer IDs.
type: list
resources:
description: List of resources.
type: list
'''
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.ansible_netbird.plugins.module_utils.netbird_api import (
NetBirdAPI,
NetBirdAPIError,
netbird_argument_spec
)
def find_group_by_name(api, name):
"""Find a group by name."""
groups, _ = api.list_groups()
for group in groups:
if group.get('name') == name:
return group
return None
def group_needs_update(current, desired):
"""Check if group needs to be updated."""
if 'name' in desired and desired['name'] is not None:
if current.get('name') != desired['name']:
return True
if 'peers' in desired and desired['peers'] is not None:
current_peers = set(current.get('peers', []))
desired_peers = set(desired['peers'])
if current_peers != desired_peers:
return True
return False
def run_module():
"""Main module execution."""
argument_spec = netbird_argument_spec()
argument_spec.update(
state=dict(type='str', choices=['present', 'absent'], default='present'),
group_id=dict(type='str'),
name=dict(type='str'),
peers=dict(type='list', elements='str', default=[]),
resources=dict(type='list', elements='dict')
)
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
required_one_of=[
('group_id', 'name'),
]
)
api = NetBirdAPI(
module,
module.params['api_url'],
module.params['api_token'],
module.params['validate_certs']
)
state = module.params['state']
group_id = module.params['group_id']
name = module.params['name']
peers = module.params['peers']
resources = module.params['resources']
result = dict(
changed=False,
group={}
)
try:
# Find existing group
existing_group = None
if group_id:
try:
existing_group, _ = api.get_group(group_id)
except NetBirdAPIError as e:
if e.status_code != 404:
raise
elif name:
existing_group = find_group_by_name(api, name)
if state == 'absent':
if existing_group:
if not module.check_mode:
api.delete_group(existing_group['id'])
result['changed'] = True
result['msg'] = 'Group deleted successfully'
module.exit_json(**result)
# state == 'present'
if existing_group:
# Check if update is needed
desired = {
'name': name,
'peers': peers
}
if group_needs_update(existing_group, desired):
if not module.check_mode:
group, _ = api.update_group(
existing_group['id'],
name=name,
peers=peers,
resources=resources
)
result['group'] = group
else:
result['group'] = existing_group
result['changed'] = True
else:
result['group'] = existing_group
else:
# Create new group
if not name:
module.fail_json(msg="name is required when creating a new group")
if not module.check_mode:
group, _ = api.create_group(
name=name,
peers=peers,
resources=resources
)
result['group'] = group
result['changed'] = True
module.exit_json(**result)
except NetBirdAPIError as e:
module.fail_json(msg=str(e), status_code=e.status_code, response=e.response)
def main():
run_module()
if __name__ == '__main__':
main()