From 4bb9e6d02c8b5e94030df83f15e017707e6fd8f3 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Thu, 12 Feb 2026 15:25:28 +0100 Subject: [PATCH 1/3] add first feature metadata draft --- docs/feature-metadata.md | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/feature-metadata.md diff --git a/docs/feature-metadata.md b/docs/feature-metadata.md new file mode 100644 index 000000000..48ecdbac7 --- /dev/null +++ b/docs/feature-metadata.md @@ -0,0 +1,85 @@ +# Feature Metadata + +Users want to enable abstract features, which means the deployment needs to know how to translate a feature name to a set of changes (configuration files, services, etc). + +The metadata is a Hash with the feature name as the key and the feature definition as the value. +The feature definition itself is again a Hash with the various properties of the feature. + +```yaml +feature_one: + property1: value_of_property1 + property2: value_of_property2 + … +feature_two: + property1: another_value_of_property1 + property2: another_value_of_property2 + … +… +``` + +The following properties are defined: +* `description` (_String_): A human-readable description of the feature, can be used in documentation/help output. +* `internal` (_Boolean_): Whether the feature is user visible (shows up in documentation/help) or internal (just to perform additional configuration without user interaction). +* `foreman` (_String_): The name of the Foreman plugin to be enabled (via `FOREMAN_ENABLED_PLUGINS`). + If `roles/foreman/tasks/feature/{{ foreman_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. + * **FIXME**: task file not implemented yet +* `foreman_proxy` (_String_): The name of the Foreman Proxy plugin to be enabled (by deploying `roles/foreman_proxy/templates/settings.d/{{ foreman_proxy_plugin }}.yml.j2` to `/etc/foreman-proxy/settings.d`). + If `roles/foreman/tasks/feature/{{ foreman_proxy_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. +* `hammer` (_String_): The name of the Hammer plugin to be enabled. + * **FIXME**: Not implemented, right now we use the same list as Foreman plugins, but needs modification for foreman-tasks and friends +* `role` (_String_): The name of the Ansible role that should be executed if this feature is enabled. +* `dependencies` (_Array_ of _String_): List of features that are automatically enabled when the user requests this feature. Usually will point at features with `internal: true`. +* `requirements` (_Array_ of _String_): List of features that are required but can't be automatically enabled (possible reasons: requires manual configuration, can't be enabled after initial deployment). + Produces an error when the requirement is not met. + +Properties can be omitted. + +## Examples + +### REX + Dynflow + +```yaml +dynflow: + internal: true + foreman_proxy: dynflow + +remote_execution: + description: Foreman Remote Execution support + foreman: foreman_remote_execution + foreman_proxy: remote_execution_ssh + dependencies: + - dynflow +``` + +The `remote_execution` feature will enable the `foreman_remote_execution` plugin for Foreman and the `remote_execution_ssh` and `dynflow` plugins for Foreman Proxy. +The `dynflow` feature is hidden from the user and only present so that `remote_execution` can pull it in. + +### RH Cloud + Katello +```yaml +katello: + description: Katello + foreman: katello + +rh_cloud: + description: Foreman RH Cloud + foreman: foreman_rh_cloud + requirements: + - katello +``` + +The `rh_cloud` feature can't be enabled unless the `katello` feature is also present in the deployment. + +### Katello + tasks +```yaml +foreman-tasks: + foreman: foreman-tasks + hammer: foreman_tasks + +katello: + description: Katello + foreman: katello + dependencies: + - foreman-tasks +``` + +The `foreman-tasks` feature is automatically enabled when the user requests Katello, thus also gaining the Hammer integration for tasks which would be missing if we'd only let the Ruby gem dependency pull in `foreman-tasks`. From 38ee10a404d98593cdbb6c81af65bc7daebb829f Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Mon, 2 Mar 2026 14:51:11 +0100 Subject: [PATCH 2/3] update spec to match discussion - drop requirements - merge role into foreman/proxy sections - add bigger example --- docs/feature-metadata.md | 75 +++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/docs/feature-metadata.md b/docs/feature-metadata.md index 48ecdbac7..851d0695a 100644 --- a/docs/feature-metadata.md +++ b/docs/feature-metadata.md @@ -20,17 +20,18 @@ feature_two: The following properties are defined: * `description` (_String_): A human-readable description of the feature, can be used in documentation/help output. * `internal` (_Boolean_): Whether the feature is user visible (shows up in documentation/help) or internal (just to perform additional configuration without user interaction). -* `foreman` (_String_): The name of the Foreman plugin to be enabled (via `FOREMAN_ENABLED_PLUGINS`). - If `roles/foreman/tasks/feature/{{ foreman_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. - * **FIXME**: task file not implemented yet -* `foreman_proxy` (_String_): The name of the Foreman Proxy plugin to be enabled (by deploying `roles/foreman_proxy/templates/settings.d/{{ foreman_proxy_plugin }}.yml.j2` to `/etc/foreman-proxy/settings.d`). - If `roles/foreman/tasks/feature/{{ foreman_proxy_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. +* `foreman` (_Hash_): + * `plugin_name` (_String_): The name of the Foreman plugin to be enabled (via `FOREMAN_ENABLED_PLUGINS`). + If `roles/foreman/tasks/feature/{{ foreman_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. + * **FIXME**: task file not implemented yet + * `role` (_String_): The name of the Ansible role to be executed. +* `foreman_proxy` (_Hash_): + * `plugin_name` (_String_): The name of the Foreman Proxy plugin to be enabled (by deploying `roles/foreman_proxy/templates/settings.d/{{ foreman_proxy_plugin }}.yml.j2` to `/etc/foreman-proxy/settings.d`). + If `roles/foreman/tasks/feature/{{ foreman_proxy_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. + * `role` (_String_): The name of the Ansible role to be executed. * `hammer` (_String_): The name of the Hammer plugin to be enabled. * **FIXME**: Not implemented, right now we use the same list as Foreman plugins, but needs modification for foreman-tasks and friends -* `role` (_String_): The name of the Ansible role that should be executed if this feature is enabled. * `dependencies` (_Array_ of _String_): List of features that are automatically enabled when the user requests this feature. Usually will point at features with `internal: true`. -* `requirements` (_Array_ of _String_): List of features that are required but can't be automatically enabled (possible reasons: requires manual configuration, can't be enabled after initial deployment). - Produces an error when the requirement is not met. Properties can be omitted. @@ -63,7 +64,7 @@ katello: rh_cloud: description: Foreman RH Cloud foreman: foreman_rh_cloud - requirements: + dependencies: - katello ``` @@ -83,3 +84,59 @@ katello: ``` The `foreman-tasks` feature is automatically enabled when the user requests Katello, thus also gaining the Hammer integration for tasks which would be missing if we'd only let the Ruby gem dependency pull in `foreman-tasks`. + +### another example + +```yaml +dynflow: + internal: true + foreman_proxy: + plugin_name: dynflow + +foreman-tasks: + foreman: + plugin_name: foreman-tasks + hammer: foreman_tasks + dependencies: + - dynflow + +katello: + description: Katello + foreman: + plugin_name: katello + dependencies: + - foreman-tasks + +rh_cloud: + description: Foreman RH Cloud + foreman: + plugin_name: foreman_rh_cloud + dependencies: + - katello + +remote_execution: + description: REX + foreman: + plugin_name: foreman_remote_execution + foreman_proxy: + plugin_name: smart_proxy_remote_execution_ssh + dependencies: + - dynflow + +openscap: + description: OpenSCAP + foreman: + plugin_name: foreman_openscap + foreman_proxy: + plugin_name: smart_proxy_openscap + +iop: + description: IoP + foreman: + role: iop_core + +container_gateway: + description: gw is a proxy-only plugin + foreman_proxy: + plugin_name: smart_proxy_container_gateway +``` From 97b110fbd996fa11f1614211e7f12e42cf1bc0e5 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Wed, 4 Mar 2026 08:57:53 +0100 Subject: [PATCH 3/3] explain when a role should be used --- docs/feature-metadata.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/feature-metadata.md b/docs/feature-metadata.md index 851d0695a..8a0e3d0b1 100644 --- a/docs/feature-metadata.md +++ b/docs/feature-metadata.md @@ -20,15 +20,15 @@ feature_two: The following properties are defined: * `description` (_String_): A human-readable description of the feature, can be used in documentation/help output. * `internal` (_Boolean_): Whether the feature is user visible (shows up in documentation/help) or internal (just to perform additional configuration without user interaction). -* `foreman` (_Hash_): +* `foreman` (_Hash_): How this feature should be applied on the "main" system that offers the main user interaction via UI/API. * `plugin_name` (_String_): The name of the Foreman plugin to be enabled (via `FOREMAN_ENABLED_PLUGINS`). If `roles/foreman/tasks/feature/{{ foreman_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. * **FIXME**: task file not implemented yet - * `role` (_String_): The name of the Ansible role to be executed. -* `foreman_proxy` (_Hash_): + * `role` (_String_): The name of the Ansible role to be executed if the feature to be placed on the main system but is not implemented as a Foreman plugin. +* `foreman_proxy` (_Hash_): How this feature should be applied to a secondary system that is connected using the Proxy API to the main system. * `plugin_name` (_String_): The name of the Foreman Proxy plugin to be enabled (by deploying `roles/foreman_proxy/templates/settings.d/{{ foreman_proxy_plugin }}.yml.j2` to `/etc/foreman-proxy/settings.d`). If `roles/foreman/tasks/feature/{{ foreman_proxy_plugin }}.yaml` exists, it will be executed to perform any plugin-specific setup. - * `role` (_String_): The name of the Ansible role to be executed. + * `role` (_String_): The name of the Ansible role to be executed if the feature is not implemented as a Foreman Proxy plugin. * `hammer` (_String_): The name of the Hammer plugin to be enabled. * **FIXME**: Not implemented, right now we use the same list as Foreman plugins, but needs modification for foreman-tasks and friends * `dependencies` (_Array_ of _String_): List of features that are automatically enabled when the user requests this feature. Usually will point at features with `internal: true`.