Skip to content

Add mutually exclusive feature support via conflicts metadata#610

Open
ehelms wants to merge 1 commit into
theforeman:masterfrom
ehelms:mutually-exclusive-features
Open

Add mutually exclusive feature support via conflicts metadata#610
ehelms wants to merge 1 commit into
theforeman:masterfrom
ehelms:mutually-exclusive-features

Conversation

@ehelms

@ehelms ehelms commented Jul 1, 2026

Copy link
Copy Markdown
Member

Why are you introducing these changes? (Problem description, related links)

Features in foremanctl can declare dependencies but have no way to declare that two features conflict with each other. When incompatible features are both enabled — whether via --add-feature on the same command, from a previous deploy's persisted state, or from flavor defaults — the deploy proceeds silently and produces a broken deployment. For example, cloud-connector and iop both provide connectivity to the Red Hat Hybrid Cloud Console using different mechanisms and cannot coexist (see #569).

What are the changes introduced in this pull request?

  • Added conflicts property to the feature metadata schema in features.yaml, allowing features to declare mutual exclusivity alongside existing dependencies
  • Added conflicting_features Jinja2 filter in src/filter_plugins/foremanctl.py that checks enabled_features for conflict violations and returns deduplicated conflict pair descriptions
  • Added asymmetric_conflicts filter that validates all conflict declarations are bidirectional (both sides must declare the conflict)
  • Extended src/roles/check_features/tasks/main.yaml with a "Validate feature conflicts" assertion that fails the deploy early with a clear error message
  • Updated docs/developer/feature-metadata.md and docs/developer/how-to-add-a-feature.md with conflicts documentation and examples
  • Added unit tests for the new filter functions

How to test this pull request

Steps to reproduce:

  • Add a pair of conflicting features to src/features.yaml (e.g. when cloud-connector lands via Add cloud-connector as a native foremanctl feature #569, add conflicts: [iop] to it and conflicts: [cloud-connector] to iop)
  • Run ./foremanctl deploy --add-feature <feature-a> --add-feature <feature-b> with both conflicting features — deploy should fail with "Conflicting features detected" error
  • Run unit tests: .venv/bin/python -m pytest tests/unit/filter_test.py -vv --noconftest
  • Run ansible-lint: cd src; ansible-lint roles/check_features/tasks/main.yaml

Checklist

  • Tests added/updated (if applicable)
  • Documentation updated (if applicable)

@jeremylenz jeremylenz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like the bidirectional conflict validation here better than mine. 👍

@ehelms

ehelms commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

I wasn't a huge fan of having to declare it bidirectionally as that feels like repeating. The other option would be to keep a separate list of things that conflict with one another which didn't feel great either.

@jeremylenz

Copy link
Copy Markdown
Contributor

I thought your PR added the bidirectionality where mine didn't have it. I guess I failed to see what the other difference is here, other than separation of concerns?

Features can now declare conflicts in features.yaml to prevent
incompatible features from being enabled together. The check_features
role validates enabled_features for conflicts during deploy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ehelms ehelms force-pushed the mutually-exclusive-features branch from 6eeed47 to 1bfa50c Compare July 2, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants