Source code for towerlib.entities.group

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: group.py
#
# Copyright 2018 Costas Tyfoxylos
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to
#  deal in the Software without restriction, including without limitation the
#  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
#  sell copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
#

"""
Main code for group.

.. _Google Python Style Guide:
   http://google.github.io/styleguide/pyguide.html

"""

import logging

from towerlib.towerlibexceptions import (InvalidHost,
                                         InvalidGroup,
                                         InvalidValue)
from .core import (Entity,
                   EntityManager,
                   validate_max_length,
                   validate_json)

__author__ = '''Costas Tyfoxylos <ctyfoxylos@schubergphilis.com>'''
__docformat__ = '''google'''
__date__ = '''2018-01-03'''
__copyright__ = '''Copyright 2018, Costas Tyfoxylos'''
__credits__ = ["Costas Tyfoxylos"]
__license__ = '''MIT'''
__maintainer__ = '''Costas Tyfoxylos'''
__email__ = '''<ctyfoxylos@schubergphilis.com>'''
__status__ = '''Development'''  # "Prototype", "Development", "Production".

# This is the main prefix used for logging.
LOGGER_BASENAME = '''group'''
LOGGER = logging.getLogger(LOGGER_BASENAME)
LOGGER.addHandler(logging.NullHandler())


[docs]class Group(Entity): """Models the group entity of ansible tower.""" def __init__(self, tower_instance, data): Entity.__init__(self, tower_instance, data) @property def name(self): """The name of the group. Returns: string: The name of the group. """ return self._data.get('name') @name.setter def name(self, value): """Update the name of the group. Returns: None: """ max_characters = 512 conditions = [validate_max_length(value, max_characters)] if all(conditions): self._update_values('name', value) else: raise InvalidValue(f'{value} is invalid. Condition max_characters must be less than or equal to ' f'{max_characters}') @property def description(self): """The description of the group. Returns: string: The description of the group. """ return self._data.get('description') @description.setter def description(self, value): """Update the description of the group. Returns: None: """ self._update_values('description', value) @property def inventory(self): """The inventory that the group is part of. Returns: Inventory: The inventory that the group is part of. """ return self._tower.get_inventory_by_id(self._data.get('inventory')) @property def variables(self): """The variables set on the group. Returns: string: A string of the variables set on the group usually in yaml format. """ return self._data.get('variables') @variables.setter def variables(self, value): """Update the variables of the group. Returns: None: """ conditions = [validate_json(value)] if all(conditions): self._update_values('variables', value) else: raise InvalidValue(f'{value} is not valid json.') @property def has_active_failures(self): """A flag on whether the group has active failures. Returns: bool: True if there are active failures, False if not. """ return self._data.get('has_active_failures') @property def total_hosts_count(self): """The total number of hosts in the group. Returns: integer: The number of group hosts. """ return self._data.get('total_hosts') @property def hosts_with_active_failures_count(self): """The number of hosts with active failures. Returns: integer: The number of hosts with active failures. """ return self._data.get('hosts_with_active_failures') @property def total_groups_count(self): """The number of groups. Returns: integer: The number of groups. """ return self._data.get('total_groups') @property def groups_with_active_failures_count(self): """The number of groups with active failures. Returns: integer: The number of groups with active failures. """ return self._data.get('groups_with_active_failures') @property def has_inventory_sources(self): """A flag of whether there are. Returns: bool: True if set, False otherwise. """ return self._data.get('has_inventory_sources') @property def created_by(self): """The user that created the group. Returns: User: The user that created the group. """ url = self._data.get('related', {}).get('created_by') return self._tower._get_object_by_url('User', url) # pylint: disable=protected-access def _add_host_by_id(self, id_): payload = {'id': id_} return self._post_host(payload) def _remove_host_by_id(self, id_): payload = {'id': id_, 'disassociate': 1} return self._post_host(payload) def _post_host(self, payload): url = f'{self._tower.api}/groups/{self.id}/hosts/' response = self._tower.session.post(url, json=payload) if not response.ok: self._logger.error('Error posting to url "%s", response was "%s"', url, response.text) return response.ok def _associate_group_by_id(self, id_): payload = {'id': id_} return self._post_group(payload) def _disassociate_group_by_id(self, id_): payload = {'id': id_, 'disassociate': 1} return self._post_group(payload) def _post_group(self, payload): url = f'{self._tower.api}/groups/{self.id}/children/' response = self._tower.session.post(url, json=payload) if not response.ok: self._logger.error('Error posting to url "%s", response was "%s"', url, response.text) return response.ok @property def hosts(self): """The hosts of the group. Returns: EntityManager: EntityManager of the hosts of the group. """ url = self._data.get('related', {}).get('hosts') return EntityManager(self._tower, entity_object='Host', primary_match_field='name', url=url)
[docs] def add_host_by_name(self, name): """Add a host to the group by name. Args: name: The name of the host to add to the group. Returns: bool: True on success, False otherwise. Raises: InvalidHost: The host provided as argument does not exist. """ host = self.inventory.get_host_by_name(name) if not host: raise InvalidHost(name) return self._add_host_by_id(host.id)
[docs] def remove_host_by_name(self, name): """Removes a host from the group. Args: name: The name of the host to remove. Returns: bool: True on success, False otherwise. Raises: InvalidHost: The host provided as argument does not exist. """ host = self.inventory.get_host_by_name(name) if not host: raise InvalidHost(name) return self._remove_host_by_id(host.id)
@property def groups(self): """The associated groups of the group. Returns: EntityManager: EntityManager of the groups of the group. """ url = self._data.get('related', {}).get('children') return EntityManager(self._tower, entity_object='Group', primary_match_field='name', url=url)
[docs] def associate_group_by_name(self, name): """Associate a group to the group by name. Args: name: The name of the group to associate with the group. Returns: bool: True on success, False otherwise. Raises: InvalidGroup: The group provided as argument does not exist. """ group = self.inventory.get_group_by_name(name) if not group: raise InvalidGroup(name) return self._associate_group_by_id(group.id)
[docs] def disassociate_group_by_name(self, name): """Disassociate a group from the group. Args: name: The name of the group to disassociate. Returns: bool: True on success, False otherwise. Raises: InvalidGroup: The group provided as argument does not exist. """ group = self.inventory.get_group_by_name(name) if not group: raise InvalidGroup(name) return self._disassociate_group_by_id(group.id)