Skip to content

Fixes ipahost idempotence issues#1383

Open
rjeffman wants to merge 3 commits intofreeipa:masterfrom
rjeffman:host_dns_record_idempotence
Open

Fixes ipahost idempotence issues#1383
rjeffman wants to merge 3 commits intofreeipa:masterfrom
rjeffman:host_dns_record_idempotence

Conversation

@rjeffman
Copy link
Copy Markdown
Member

@rjeffman rjeffman commented Aug 26, 2025

Fixes: #1296

Summary by Sourcery

Improve idempotence in the ipahost module by normalizing input values uniformly and refactoring host entry processing.

Bug Fixes:

  • Fix idempotence issues by normalizing host parameters (case, FQDN, SSH keys) before comparison and ignoring unsupported updatedns settings

Enhancements:

  • Refactor ipahost module to use EntryFactory for streamlined parameter conversion and entry iteration
  • Add conversion helpers (lowercase, uppercase, unique FQDN, SSH public key normalization) in ansible_freeipa_module
  • Update compare_args_ipa to include key context in debug messages and ignore updatedns during modifications
  • Refactor ipasudorule to use unique FQDN conversion for host entries

Tests:

  • Add integration tests to verify idempotence of mac_address casing and repeated host definitions in ipahost

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The new single_host flag logic (single_host=len(entry_factory)>1) no longer matches the original hosts is None semantics—please verify it still produces the intended batching behavior when processing multiple entries.
  • There’s still duplicated logic for splitting FQDN into host and domain in the DNS record sections—extracting that into a helper would reduce code repetition and minimize edge‐case bugs.
  • Even with the EntryFactory, the main function is extremely large; consider breaking out host command generation for each state/action into helper functions to improve readability and maintainability.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new single_host flag logic (`single_host=len(entry_factory)>1`) no longer matches the original `hosts is None` semantics—please verify it still produces the intended batching behavior when processing multiple entries.
- There’s still duplicated logic for splitting FQDN into host and domain in the DNS record sections—extracting that into a helper would reduce code repetition and minimize edge‐case bugs.
- Even with the EntryFactory, the main function is extremely large; consider breaking out host command generation for each state/action into helper functions to improve readability and maintainability.

## Individual Comments

### Comment 1
<location> `plugins/modules/ipahost.py:658` </location>
<code_context>
                 result["result"]["randompassword"]


+def convert_sshpubkey(value):
+    """Ensure sshpubkey values are correct."""
+    if isinstance(value, list):
+        value = [str(normalize_sshpubkey(key)) for key in value]
+    if isinstance(value, (str, unicode)):  # pylint: disable=E0606
+        value = str(normalize_sshpubkey(value))
+    return value
+
+
</code_context>

<issue_to_address>
convert_sshpubkey may not handle nested lists or None values robustly.

Please update convert_sshpubkey to handle None inputs and nested lists to prevent runtime errors.
</issue_to_address>

### Comment 2
<location> `plugins/module_utils/ansible_freeipa_module.py:540` </location>
<code_context>
     return value


+def convert_param_value_to_uppercase(value):
+    if isinstance(value, list):
+        value = [v.upper() for v in value]
+    if isinstance(value, (str, unicode)):
+        value = value.upper()
+    return value
+
+
</code_context>

<issue_to_address>
convert_param_value_to_uppercase does not handle None values.

Explicitly handle None to ensure consistent behavior and prevent unintended results in downstream code.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@rjeffman rjeffman force-pushed the host_dns_record_idempotence branch 5 times, most recently from 1ccd618 to 35ea5d7 Compare August 27, 2025 00:28
@rjeffman rjeffman requested a review from t-woerner August 27, 2025 00:30
@rjeffman rjeffman force-pushed the host_dns_record_idempotence branch 5 times, most recently from 0b4a6a0 to b246dff Compare August 27, 2025 20:42
@rjeffman rjeffman added the Candidate Good candidate for next minor release. label Aug 29, 2025
@rjeffman
Copy link
Copy Markdown
Member Author

rjeffman commented Sep 4, 2025

Dowstream tests are passing with these changes.

When comparing an argument dict to an IPA dict, the log messages were
inconsistent and did not provide enough information for debugging.

This change make the messages consistent and display the dict key being
evaluated if the key result in tagging the dicts as different.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
This patch moves the function used to ensure that hostnames used in
ipasurule are FQDN and unique to module_utils, so it can be used by
other modules than require the same behavior for a hostaname parameter.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
When using ipahost with the 'hosts' parameters several parameter
conversion routines were not being performed causing the module to try
to execute tasks it was not suposed to.

This issues were fixed by adapting the module to use EntryFactory.

Another issue was happening when 'update_dns: true' is used with some
parameters, like 'description', 'location' or 'mac_address', where, even
if no change was to be performed the plugin would evaluate that the
arguments were different, and tried to modify the object.

The fix for this issue is to ignore 'updatedns' when comparing the
parameters provided with the existing IPA object.

This modification also fix the case where duplicate entries used with
the 'name' parameter in case 'state: absent' would fail without
indicating the use of duplicate entries.

Fixes: freeipa#1296
Fixes: https://issues.redhat.com/browse/RHEL-111063

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
@rjeffman rjeffman force-pushed the host_dns_record_idempotence branch from b246dff to e7819b1 Compare November 11, 2025 18:12
Copy link
Copy Markdown
Collaborator

@varunmylaraiah varunmylaraiah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR LGTM.
I’ve tested it against the existing upstream and downstream test suites, and all tests are passing.


def module_params_get(module, name, allow_empty_list_item=False):
def module_params_get(
module, name, allow_empty_list_item=False, ignore_list_check=False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ignore_list_check is enabled, enabling allow_empty_list_item does not have any impact.
There is no description for ignore_list_check and the use case etc. Also not in the ipahost change later on, where it is used.

using_hosts = ansible_module.params_get("hosts") is not None

# Check parameters
invalid = []
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As invalid is now a variable that is used later on in the code, it should have a better name to make sure that it will not be used for something else.

@DorBreger
Copy link
Copy Markdown

Any news on this?

@DorBreger
Copy link
Copy Markdown

If I can be of any help on this PR, please let me know. I would really love to see this merged

@rjeffman
Copy link
Copy Markdown
Member Author

rjeffman commented Mar 6, 2026

@DorBreger this change will cause a huge impact on the way plugins are created, and we are postponing it for a few months. It is close to our radar, but we can't really do it right now as we have more pressure on other fronts.

And there are some "not optimal" design decisions I made on this PR that I feel need to be addressed before it could be merged.

A more realistic time frame (but still a crude estimate) is "second half of 2026". I'll certainly not touch it before May.

@DorBreger
Copy link
Copy Markdown

@DorBreger this change will cause a huge impact on the way plugins are created, and we are postponing it for a few months. It is close to our radar, but we can't really do it right now as we have more pressure on other fronts.

And there are some "not optimal" design decisions I made on this PR that I feel need to be addressed before it could be merged.

A more realistic time frame (but still a crude estimate) is "second half of 2026". I'll certainly not touch it before May.

I understand that this is a big change. We are facing an issue with ipa_dnsrecord not being idempotent, failing if the record already exists. Would you recommend submitting a fix to community.general for now?

@rjeffman
Copy link
Copy Markdown
Member Author

rjeffman commented Mar 6, 2026

We don't have any influence in the community.general project. We follow different approaches to managing IPA deployments (specially in the communication with the servers).

Note that ansible-freeipa plugins do not have underscore (_) on their names (this is the easiest way to differentiate them).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Candidate Good candidate for next minor release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ipa_dnsrecord no modifications to be performed when record already exists.

4 participants