Skip to content

Commit

Permalink
Merge pull request #87 from RedHatSatellite/rel510
Browse files Browse the repository at this point in the history
Release 5.1.0
  • Loading branch information
evgeni authored Dec 6, 2024
2 parents 501f491 + 057b1dc commit 6f8fcca
Show file tree
Hide file tree
Showing 39 changed files with 196 additions and 114 deletions.
28 changes: 25 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ concurrency:
cancel-in-progress: true

jobs:
sanity:
name: Sanity (Ⓐ${{ matrix.ansible }})
strategy:
matrix:
ansible:
- stable-2.15
- stable-2.16
- stable-2.17
- stable-2.18
- devel

runs-on: ubuntu-latest

steps:
# Run sanity tests inside a Docker container.
# The docker container has all the pinned dependencies that are
# required and all Python versions Ansible supports.
- name: Perform sanity testing
uses: ansible-community/ansible-test-gh-action@release/v1
with:
ansible-core-version: ${{ matrix.ansible }}
testing-type: sanity
pull-request-change-detection: false
pre-test-cmd: rm -rf tests/fixtures tests/test_playbooks/fixtures

build:
runs-on: ubuntu-20.04
container: ${{ matrix.container }}
Expand Down Expand Up @@ -86,9 +111,6 @@ jobs:
run: make test-other
- name: Run dist tests
run: make dist-test
- name: Run sanity tests
run: make SANITY_OPTS="--docker" sanity
if: matrix.ansible != 'v2.10.4' && matrix.ansible != 'stable-2.11' && matrix.ansible != 'stable-2.12' && matrix.ansible != 'stable-2.13' && matrix.ansible != 'stable-2.14'

checkmode:
runs-on: ubuntu-latest
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ redhat.satellite Release Notes

This changelog describes changes after version 0.8.1.

v5.1.0
======

Minor Changes
-------------

- templates_import - Support configuring HTTP Proxy behaviour for template import

Bugfixes
--------

- inventory - Drop fallback to Host API when Reports API fails, as this leads to possibly wrong data being used

v5.0.0
======

Expand Down
11 changes: 11 additions & 0 deletions changelogs/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -928,3 +928,14 @@ releases:
- drop-ansible-29.yaml
- drop-python-pre-36.yaml
release_date: '2024-11-22'
5.1.0:
changes:
bugfixes:
- inventory - Drop fallback to Host API when Reports API fails, as this leads
to possibly wrong data being used
minor_changes:
- templates_import - Support configuring HTTP Proxy behaviour for template
import
fragments:
- drop-host-api-fallback.yml
release_date: '2024-12-06'
File renamed without changes.
3 changes: 2 additions & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ authors:
- "Yifat Makias <[email protected]>"
- "ab <[email protected]>"
- "achevalet <[email protected]>"
- "adamlazik1 <[email protected]>"
- "alesc <[email protected]>"
- "bob <[email protected]>"
- "calvingsmith <[email protected]>"
Expand All @@ -109,7 +110,7 @@ authors:
- "russianguppie <[email protected]>"
- "willtome <[email protected]>"
- "yuqo2450 <[email protected]>"
version: "5.0.0"
version: "5.1.0"
license:
- "GPL-3.0-or-later"
tags:
Expand Down
2 changes: 1 addition & 1 deletion generate_action_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
runtime['action_groups']['satellite'] = sorted(set(ALL_MODULES) - set(EXCLUDED_MODULES))

with open(META_RUNTIME, 'w') as runtime_file:
yaml.safe_dump(runtime, runtime_file, default_flow_style=False, explicit_start=True)
yaml.safe_dump(runtime, runtime_file, default_flow_style=False, explicit_start=True)
11 changes: 4 additions & 7 deletions plugins/inventory/foreman.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,10 @@ def _get_hostname(self, properties, hostnames, strict=False):
def _populate_report_api(self):
self.groups = dict()
self.hosts = dict()
try:
# We need a deep copy of the data, as we modify it below and this would also modify the cache
host_data = copy.deepcopy(self._post_request())
except Exception as exc:
self.display.warning("Failed to use Reports API, falling back to Hosts API: {0}".format(exc))
self._populate_host_api()
return

# We need a deep copy of the data, as we modify it below and this would also modify the cache
host_data = copy.deepcopy(self._post_request())

self.group_prefix = self.get_option('group_prefix')

hostnames = self.get_option('hostnames')
Expand Down
103 changes: 16 additions & 87 deletions plugins/module_utils/foreman_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import os
import operator
import re
import time
import traceback

from contextlib import contextmanager
Expand Down Expand Up @@ -397,7 +396,6 @@ def __init__(self, **kwargs):
self.fail_json(msg="The server URL needs to be either HTTPS or HTTP!")

self.task_timeout = 60
self.task_poll = 4

self._thin_default = False
self.state = 'undefined'
Expand Down Expand Up @@ -608,12 +606,12 @@ def connect(self):
that are required by the module.
"""

self.foremanapi = apypie.Api(
self.foremanapi = apypie.ForemanApi(
uri=self._foremanapi_server_url,
username=to_bytes(self._foremanapi_username),
password=to_bytes(self._foremanapi_password),
api_version=2,
verify_ssl=self._foremanapi_validate_certs,
task_timeout=self.task_timeout,
)

_status = self.status()
Expand Down Expand Up @@ -651,18 +649,6 @@ def status(self):

return self.foremanapi.resource('home').call('status')

def _resource(self, resource):
if resource not in self.foremanapi.resources:
raise Exception("The server doesn't know about {0}, is the right plugin installed?".format(resource))
return self.foremanapi.resource(resource)

def _resource_call(self, resource, *args, **kwargs):
return self._resource(resource).call(*args, **kwargs)

def _resource_prepare_params(self, resource, action, params):
api_action = self._resource(resource).action(action)
return api_action.prepare_params(params)

@_exception2fail_json(msg='Failed to show resource: {0}')
def show_resource(self, resource, resource_id, params=None):
"""
Expand All @@ -676,16 +662,7 @@ def show_resource(self, resource, resource_id, params=None):
:type params: Union[dict,None], optional
"""

if params is None:
params = {}
else:
params = params.copy()

params['id'] = resource_id

params = self._resource_prepare_params(resource, 'show', params)

return self._resource_call(resource, 'show', params)
return self.foremanapi.show(resource, resource_id, params)

@_exception2fail_json(msg='Failed to list resource: {0}')
def list_resource(self, resource, search=None, params=None):
Expand All @@ -700,18 +677,7 @@ def list_resource(self, resource, search=None, params=None):
:type params: Union[dict,None], optional
"""

if params is None:
params = {}
else:
params = params.copy()

if search is not None:
params['search'] = search
params['per_page'] = PER_PAGE

params = self._resource_prepare_params(resource, 'index', params)

return self._resource_call(resource, 'index', params)['results']
return self.foremanapi.list(resource, search, params)

def find_resource(self, resource, search, params=None, failsafe=False, thin=None):
list_params = {}
Expand Down Expand Up @@ -1024,9 +990,7 @@ def _validate_supported_payload(self, resource, action, payload):
:return: The payload as it can be submitted to the API
:rtype: dict
"""
filtered_payload = self._resource_prepare_params(resource, action, payload)
# On Python 2 dict.keys() is just a list, but we need a set here.
unsupported_parameters = set(payload.keys()) - set(_recursive_dict_keys(filtered_payload))
filtered_payload, unsupported_parameters = self.foremanapi.validate_payload(resource, action, payload)
if unsupported_parameters:
warn_msg = "The following parameters are not supported by your server when performing {0} on {1}: {2}. They were ignored."
self.warn(warn_msg.format(action, resource, unsupported_parameters))
Expand All @@ -1050,14 +1014,12 @@ def _create_entity(self, resource, desired_entity, params, foreman_spec):
"""
payload = _flatten_entity(desired_entity, foreman_spec)
self._validate_supported_payload(resource, 'create', payload)
self.set_changed()
if not self.check_mode:
if params:
payload.update(params)
return self.resource_action(resource, 'create', payload)
return self.foremanapi.create(resource, payload, params)
else:
fake_entity = desired_entity.copy()
fake_entity['id'] = -1
self.set_changed()
return fake_entity

def _update_entity(self, resource, desired_entity, current_entity, params, foreman_spec):
Expand Down Expand Up @@ -1111,16 +1073,14 @@ def _update_entity(self, resource, desired_entity, current_entity, params, forem
if new_value != old_value:
payload[key] = value
if self._validate_supported_payload(resource, 'update', payload):
self.set_changed()
payload['id'] = current_flat_entity['id']
if not self.check_mode:
if params:
payload.update(params)
return self.resource_action(resource, 'update', payload)
return self.foremanapi.update(resource, payload, params)
else:
# In check_mode we emulate the server updating the entity
fake_entity = current_flat_entity.copy()
fake_entity.update(payload)
self.set_changed()
return fake_entity
else:
# Nothing needs changing
Expand Down Expand Up @@ -1183,29 +1143,18 @@ def _delete_entity(self, resource, current_entity, params):
:return: The new current state of the entity
:rtype: Union[dict,None]
"""
payload = {'id': current_entity['id']}
if params:
payload.update(params)
entity = self.resource_action(resource, 'destroy', payload)

# this is a workaround for https://projects.theforeman.org/issues/26937
if entity and isinstance(entity, dict) and 'error' in entity and 'message' in entity['error']:
self.fail_json(msg=entity['error']['message'])

return None
self.set_changed()
if not self.check_mode:
return self.foremanapi.delete(resource, current_entity, params)
else:
return None

def resource_action(self, resource, action, params, options=None, data=None, files=None,
ignore_check_mode=False, record_change=True, ignore_task_errors=False):
resource_payload = self._resource_prepare_params(resource, action, params)
if options is None:
options = {}
try:
result = None
if ignore_check_mode or not self.check_mode:
result = self._resource_call(resource, action, resource_payload, options=options, data=data, files=files)
is_foreman_task = isinstance(result, dict) and 'action' in result and 'state' in result and 'started_at' in result
if is_foreman_task:
result = self.wait_for_task(result, ignore_errors=ignore_task_errors)
result = self.foremanapi.resource_action(resource, action, params, options, data, files, ignore_task_errors)
except Exception as e:
msg = 'Error while performing {0} on {1}: {2}'.format(
action, resource, to_native(e))
Expand All @@ -1216,18 +1165,7 @@ def resource_action(self, resource, action, params, options=None, data=None, fil
return result

def wait_for_task(self, task, ignore_errors=False):
duration = self.task_timeout
while task['state'] not in ['paused', 'stopped']:
duration -= self.task_poll
if duration <= 0:
self.fail_json(msg="Timeout waiting for Task {0}".format(task['id']))
time.sleep(self.task_poll)

resource_payload = self._resource_prepare_params('foreman_tasks', 'show', {'id': task['id']})
task = self._resource_call('foreman_tasks', 'show', resource_payload)
if not ignore_errors and task['result'] != 'success':
self.fail_json(msg='Task {0}({1}) did not succeed. Task information: {2}'.format(task['action'], task['id'], task['humanized']['errors']))
return task
return self.foremanapi.wait_for_task(task, ignore_errors)

def fail_from_exception(self, exc, msg):
fail = {'msg': msg}
Expand Down Expand Up @@ -1759,15 +1697,6 @@ def _flatten_entity(entity, foreman_spec):
return result


def _recursive_dict_keys(a_dict):
"""Find all keys of a nested dictionary"""
keys = set(a_dict.keys())
for _k, v in a_dict.items():
if isinstance(v, dict):
keys.update(_recursive_dict_keys(v))
return keys


def _recursive_dict_without_none(a_dict, exclude=None):
"""
Remove all entries with `None` value from a dict, recursively.
Expand Down
20 changes: 20 additions & 0 deletions plugins/modules/templates_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,23 @@
- The directory within Git repo containing the templates.
required: false
type: str
http_proxy_policy:
description:
- HTTP proxy policy for template sync.
- You can choose no HTTP proxy, global HTTP proxy, or a custom HTTP proxy (C(selected))
- If you choose 'selected', provide the C(http_proxy) parameter.
required: false
type: str
choices:
- none
- global
- selected
http_proxy:
description:
- HTTP proxy to use for template sync.
- Use this parameter together with C(http_proxy_policy=selected)
required: false
type: str
attributes:
check_mode:
support: none
Expand Down Expand Up @@ -156,9 +173,12 @@ def main():
force=dict(type='bool'),
lock=dict(type='bool'),
negate=dict(type='bool'),
http_proxy_policy=dict(choices=['global', 'none', 'selected']),
http_proxy=dict(type='entity'),
),
supports_check_mode=False,
required_plugins=[('templates', ['*'])],
required_if=[('http_proxy_policy', 'selected', ['http_proxy'])],
)

with module.api_connection():
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
type: str
default_organization:
description:
- The organizxation that the user uses by default
- The organization that the user uses by default
required: false
type: str
auth_source:
Expand Down
4 changes: 4 additions & 0 deletions roles/activation_keys/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
galaxy_info:
description: Create and manage Activation Keys
standalone: false
4 changes: 4 additions & 0 deletions roles/auth_sources_ldap/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
galaxy_info:
description: Create and manage LDAP authentication sources
standalone: false
4 changes: 4 additions & 0 deletions roles/compute_profiles/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
galaxy_info:
description: Create and manage Compute Profiles
standalone: false
4 changes: 4 additions & 0 deletions roles/compute_resources/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
galaxy_info:
description: Create and manage Compute Resources
standalone: false
4 changes: 4 additions & 0 deletions roles/content_credentials/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
galaxy_info:
description: Create and manage Content Credentials
standalone: false
Loading

0 comments on commit 6f8fcca

Please sign in to comment.