| Server IP : 85.214.239.14 / Your IP : 216.73.216.210 Web Server : Apache/2.4.65 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Mon Sep 30 15:36:27 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 8.2.29 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /lib/python3/dist-packages/ansible_collections/theforeman/foreman/plugins/modules/ |
Upload File : |
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2017, Andrew Kofink <ajkofink@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
---
module: activation_key
version_added: 1.0.0
short_description: Manage Activation Keys
description:
- Create and manage activation keys
author: "Andrew Kofink (@akofink)"
options:
name:
description:
- Name of the activation key
required: true
type: str
description:
description:
- Description of the activation key
type: str
lifecycle_environment:
description:
- Name of the lifecycle environment
type: str
content_view:
description:
- Name of the content view
type: str
subscriptions:
description:
- List of subscriptions that include either Name, Pool ID, or Upstream Pool ID.
- Pool IDs are preferred since Names and Upstream Pool IDs are not guaranteed to be unique. The module will fail if it finds more than one match.
type: list
elements: dict
suboptions:
name:
description:
- Name of the Subscription to be added.
- Mutually exclusive with I(pool_id) and I(upstream_pool_id).
type: str
required: false
pool_id:
description:
- Pool ID of the Subscription to be added.
- Mutually exclusive with I(name) and I(upstream_pool_id).
- Also named C(Candlepin Id) in the CSV export of the subscriptions,
- it is as well the C(UUID) as output by C(hammer subscription list).
type: str
required: false
upstream_pool_id:
description:
- Upstream Pool ID of the Subscription to be added.
- Mutually exclusive with I(name) and I(pool_id).
- Also named C(Master Pools) in the Red Hat Portal.
type: str
required: false
host_collections:
description:
- List of host collections to add to activation key
type: list
elements: str
content_overrides:
description:
- List of content overrides that include label and override state
- Label refers to repository C(content_label), e.g. rhel-7-server-rpms
- Override state ('enabled', 'disabled', or 'default') sets initial state of repository for newly registered hosts
type: list
elements: dict
suboptions:
label:
description:
- Repository C(content_label) to override when registering hosts with the activation key
type: str
required: true
override:
description:
- Override value to use for the repository when registering hosts with the activation key
choices:
- enabled
- disabled
- default
type: str
required: true
auto_attach:
description:
- Set Auto-Attach on or off
type: bool
release_version:
description:
- Set the content release version
type: str
service_level:
description:
- Set the service level
choices:
- Self-Support
- Standard
- Premium
type: str
max_hosts:
description:
- Maximum number of registered content hosts.
- Required if I(unlimited_hosts=false)
type: int
unlimited_hosts:
description:
- Can the activation key have unlimited hosts
type: bool
purpose_usage:
description:
- Sets the system purpose usage
type: str
purpose_role:
description:
- Sets the system purpose role
type: str
purpose_addons:
description:
- Sets the system purpose add-ons
type: list
elements: str
state:
description:
- State of the Activation Key
- If C(copied) the key will be copied to a new one with I(new_name) as the name and all other fields left untouched
- C(present_with_defaults) will ensure the entity exists, but won't update existing ones
default: present
choices:
- present
- present_with_defaults
- absent
- copied
type: str
new_name:
description:
- Name of the new activation key when state == copied
type: str
extends_documentation_fragment:
- theforeman.foreman.foreman
- theforeman.foreman.foreman.organization
'''
EXAMPLES = '''
- name: "Create client activation key"
theforeman.foreman.activation_key:
username: "admin"
password: "changeme"
server_url: "https://foreman.example.com"
name: "Clients"
organization: "Default Organization"
lifecycle_environment: "Library"
content_view: 'client content view'
host_collections:
- rhel7-servers
- rhel7-production
subscriptions:
- pool_id: "8a88e9826db22df5016dd018abdd029b"
- pool_id: "8a88e9826db22df5016dd01a23270344"
- name: "Red Hat Enterprise Linux"
content_overrides:
- label: rhel-7-server-optional-rpms
override: enabled
auto_attach: false
release_version: 7Server
service_level: Standard
'''
RETURN = '''
entity:
description: Final state of the affected entities grouped by their type.
returned: success
type: dict
contains:
activation_keys:
description: List of activation keys.
type: list
elements: dict
'''
from ansible_collections.theforeman.foreman.plugins.module_utils.foreman_helper import KatelloEntityAnsibleModule, PER_PAGE
def override_to_boolnone(override):
value = None
if isinstance(override, bool):
value = override
else:
override = override.lower()
if override == 'enabled':
value = True
elif override == 'disabled':
value = False
elif override == 'default':
value = None
return value
class KatelloActivationKeyModule(KatelloEntityAnsibleModule):
pass
def main():
module = KatelloActivationKeyModule(
foreman_spec=dict(
name=dict(required=True),
new_name=dict(),
description=dict(),
lifecycle_environment=dict(type='entity', flat_name='environment_id', scope=['organization']),
content_view=dict(type='entity', scope=['organization']),
host_collections=dict(type='entity_list', scope=['organization']),
auto_attach=dict(type='bool'),
release_version=dict(),
service_level=dict(choices=['Self-Support', 'Standard', 'Premium']),
max_hosts=dict(type='int'),
unlimited_hosts=dict(type='bool'),
purpose_usage=dict(),
purpose_role=dict(),
purpose_addons=dict(type='list', elements='str'),
),
argument_spec=dict(
subscriptions=dict(type='list', elements='dict', options=dict(
name=dict(),
pool_id=dict(),
upstream_pool_id=dict(),
),
required_one_of=[['name', 'pool_id', 'upstream_pool_id']],
mutually_exclusive=[['name', 'pool_id', 'upstream_pool_id']],
),
content_overrides=dict(type='list', elements='dict', options=dict(
label=dict(required=True),
override=dict(required=True, choices=['enabled', 'disabled', 'default']),
)),
state=dict(default='present', choices=['present', 'present_with_defaults', 'absent', 'copied']),
),
required_if=[
['state', 'copied', ['new_name']],
['unlimited_hosts', False, ['max_hosts']],
],
)
with module.api_connection():
entity = module.lookup_entity('entity')
scope = module.scope_for('organization')
if module.state == 'copied':
new_entity = module.find_resource_by_name('activation_keys', name=module.foreman_params['new_name'], params=scope, failsafe=True)
if new_entity is not None:
module.warn("Activation Key '{0}' already exists.".format(module.foreman_params['new_name']))
module.exit_json()
subscriptions = module.foreman_params.pop('subscriptions', None)
content_overrides = module.foreman_params.pop('content_overrides', None)
if not module.desired_absent:
module.lookup_entity('host_collections')
host_collections = module.foreman_params.pop('host_collections', None)
activation_key = module.run()
# only update subscriptions of newly created or updated AKs
# copied keys inherit the subscriptions of the origin, so one would not have to specify them again
# deleted keys don't need subscriptions anymore either
if module.state == 'present' or (module.state == 'present_with_defaults' and module.changed):
# the auto_attach, release_version and service_level parameters can only be set on an existing AK with an update,
# not during create, so let's force an update. see https://projects.theforeman.org/issues/27632 for details
if any(key in module.foreman_params for key in ['auto_attach', 'release_version', 'service_level']) and module.changed:
activation_key = module.ensure_entity('activation_keys', module.foreman_params, activation_key, params=scope)
ak_scope = {'activation_key_id': activation_key['id']}
ak_scope.update(scope)
if subscriptions is not None:
desired_subscriptions = []
for subscription in subscriptions:
if subscription.get('name') is not None:
desired_subscriptions.append(module.find_resource_by_name('subscriptions', subscription['name'], params=scope, thin=True))
if subscription.get('pool_id') is not None:
desired_subscriptions.append(module.find_resource_by_id('subscriptions', subscription['pool_id'], params=scope, thin=True))
if subscription.get('upstream_pool_id') is not None:
desired_subscriptions.append(
module.find_resource_by('subscriptions', 'upstream_pool_id', subscription['upstream_pool_id'], params=scope, thin=True)
)
desired_subscription_ids = set(item['id'] for item in desired_subscriptions)
current_subscriptions = module.list_resource('subscriptions', params=ak_scope) if entity else []
current_subscription_ids = set(item['id'] for item in current_subscriptions)
if desired_subscription_ids != current_subscription_ids:
module.record_before('activation_keys/subscriptions', {'id': activation_key['id'], 'subscriptions': current_subscription_ids})
module.record_after('activation_keys/subscriptions', {'id': activation_key['id'], 'subscriptions': desired_subscription_ids})
module.record_after_full('activation_keys/subscriptions', {'id': activation_key['id'], 'subscriptions': desired_subscription_ids})
ids_to_remove = current_subscription_ids - desired_subscription_ids
if ids_to_remove:
payload = {
'id': activation_key['id'],
'subscriptions': [{'id': item} for item in ids_to_remove],
}
payload.update(scope)
module.resource_action('activation_keys', 'remove_subscriptions', payload)
ids_to_add = desired_subscription_ids - current_subscription_ids
if ids_to_add:
payload = {
'id': activation_key['id'],
'subscriptions': [{'id': item, 'quantity': 1} for item in ids_to_add],
}
payload.update(scope)
module.resource_action('activation_keys', 'add_subscriptions', payload)
if content_overrides is not None:
if entity:
product_content = module.resource_action(
'activation_keys',
'product_content',
params={'id': activation_key['id'],
'content_access_mode_all': True,
'per_page': PER_PAGE},
ignore_check_mode=True,
)
else:
product_content = {'results': []}
current_content_overrides = {
product['content']['label']: product['enabled_content_override']
for product in product_content['results']
if product['enabled_content_override'] is not None
}
desired_content_overrides = {
product['label']: override_to_boolnone(product['override']) for product in content_overrides
}
changed_content_overrides = []
module.record_before('activation_keys/content_overrides', {'id': activation_key['id'], 'content_overrides': current_content_overrides.copy()})
module.record_after('activation_keys/content_overrides', {'id': activation_key['id'], 'content_overrides': desired_content_overrides})
module.record_after_full('activation_keys/content_overrides', {'id': activation_key['id'], 'content_overrides': desired_content_overrides})
for label, override in desired_content_overrides.items():
if override is not None and override != current_content_overrides.pop(label, None):
changed_content_overrides.append({'content_label': label, 'value': override})
for label in current_content_overrides.keys():
changed_content_overrides.append({'content_label': label, 'remove': True})
if changed_content_overrides:
payload = {
'id': activation_key['id'],
'content_overrides': changed_content_overrides,
}
module.resource_action('activation_keys', 'content_override', payload)
if host_collections is not None:
if not entity:
current_host_collection_ids = set()
elif 'host_collection_ids' in activation_key:
current_host_collection_ids = set(activation_key['host_collection_ids'])
else:
current_host_collection_ids = set(item['id'] for item in activation_key['host_collections'])
desired_host_collections = host_collections
desired_host_collection_ids = set(item['id'] for item in desired_host_collections)
if desired_host_collection_ids != current_host_collection_ids:
module.record_before('activation_keys/host_collections', {'id': activation_key['id'], 'host_collections': current_host_collection_ids})
module.record_after('activation_keys/host_collections', {'id': activation_key['id'], 'host_collections': desired_host_collection_ids})
module.record_after_full('activation_keys/host_collections', {'id': activation_key['id'], 'host_collections': desired_host_collection_ids})
ids_to_remove = current_host_collection_ids - desired_host_collection_ids
if ids_to_remove:
payload = {
'id': activation_key['id'],
'host_collection_ids': list(ids_to_remove),
}
module.resource_action('activation_keys', 'remove_host_collections', payload)
ids_to_add = desired_host_collection_ids - current_host_collection_ids
if ids_to_add:
payload = {
'id': activation_key['id'],
'host_collection_ids': list(ids_to_add),
}
module.resource_action('activation_keys', 'add_host_collections', payload)
if __name__ == '__main__':
main()