diff --git a/development/ansible.cfg b/development/ansible.cfg index 15225a2c6..cfad47394 100644 --- a/development/ansible.cfg +++ b/development/ansible.cfg @@ -3,4 +3,5 @@ host_key_checking = False stdout_callback=debug stderr_callback=debug roles_path = ./roles:../src/roles +filter_plugins = ./filter_plugins:../src/filter_plugins display_skipped_hosts = no diff --git a/development/features.yaml b/development/features.yaml new file mode 100644 index 000000000..fc163c334 --- /dev/null +++ b/development/features.yaml @@ -0,0 +1,174 @@ +--- +katello: + development: + foreman: + github_repo: Katello/katello + settings_template: katello.yaml.j2 + extra_gemfiles: + - gemfile.d/test.rb + hammer: + gem: hammer_cli_katello + github_repo: Katello/hammer-cli-katello + module_config: katello.yml + +dynflow: + development: + foreman_proxy: + github_repo: theforeman/smart_proxy_dynflow + module_config: dynflow.yml + +remote-execution: + development: + foreman: + github_repo: theforeman/foreman_remote_execution + hammer: + github_repo: theforeman/hammer_cli_foreman_remote_execution + module_config: foreman_remote_execution.yml + foreman_proxy: + github_repo: theforeman/smart_proxy_remote_execution_ssh + module_config: remote_execution_ssh.yml + +ansible: + development: + foreman: + github_repo: theforeman/foreman_ansible + settings_template: foreman_ansible.yaml.j2 + hammer: + gem: hammer_cli_foreman_ansible + github_repo: theforeman/hammer-cli-foreman-ansible + module_config: foreman_ansible.yml + foreman_proxy: + github_repo: theforeman/smart_proxy_ansible + module_config: ansible.yml + +rh-cloud: + development: + foreman: + github_repo: theforeman/foreman_rh_cloud + hammer: + gem: hammer_cli_foreman_rh_cloud + github_repo: theforeman/hammer-cli-foreman-rh-cloud + module_config: foreman_rh_cloud.yml + +# Features not yet in src/features.yaml — full definitions below. + +foreman-tasks: + description: Foreman Tasks plugin + foreman: + plugin_name: foreman_tasks + hammer: foreman_tasks + dependencies: + - dynflow + development: + foreman: + github_repo: theforeman/foreman-tasks + hammer: + gem: hammer_cli_foreman_tasks + github_repo: theforeman/hammer-cli-foreman-tasks + module_config: foreman_tasks.yml + +discovery: + description: Discovery plugin for Foreman + foreman: + plugin_name: foreman_discovery + hammer: foreman_discovery + development: + foreman: + github_repo: theforeman/foreman_discovery + hammer: + gem: hammer_cli_foreman_discovery + github_repo: theforeman/hammer-cli-foreman-discovery + module_config: foreman_discovery.yml + foreman_proxy: + github_repo: theforeman/smart_proxy_discovery + module_config: discovery.yml + +openscap: + description: OpenSCAP plugin for Foreman + foreman: + plugin_name: foreman_openscap + hammer: foreman_openscap + development: + foreman: + github_repo: theforeman/foreman_openscap + hammer: + github_repo: theforeman/hammer_cli_foreman_openscap + module_config: foreman_openscap.yml + foreman_proxy: + github_repo: theforeman/smart_proxy_openscap + module_config: openscap.yml + +bootdisk: + description: Bootdisk plugin for Foreman + foreman: + plugin_name: foreman_bootdisk + hammer: foreman_bootdisk + development: + foreman: + github_repo: theforeman/foreman_bootdisk + hammer: + github_repo: theforeman/hammer_cli_foreman_bootdisk + module_config: foreman_bootdisk.yml + +theme-satellite: + description: Red Hat Satellite theme for Foreman + foreman: + plugin_name: foreman_theme_satellite + development: + foreman: + github_repo: redhatsatellite/foreman_theme_satellite + +webhooks: + description: Webhooks plugin for Foreman + foreman: + plugin_name: foreman_webhooks + hammer: foreman_webhooks + development: + foreman: + github_repo: theforeman/foreman_webhooks + hammer: + gem: hammer_cli_foreman_webhooks + github_repo: theforeman/hammer-cli-foreman-webhooks + module_config: foreman_webhooks.yml + foreman_proxy: + github_repo: theforeman/smart_proxy_shellhooks + module_config: shellhooks.yml + +templates: + description: Templates plugin for Foreman + foreman: + plugin_name: foreman_templates + hammer: foreman_templates + development: + foreman: + github_repo: theforeman/foreman_templates + hammer: + gem: hammer_cli_foreman_templates + github_repo: theforeman/hammer-cli-foreman-templates + module_config: foreman_templates.yml + +leapp: + description: Leapp plugin for Foreman + foreman: + plugin_name: foreman_leapp + hammer: foreman_leapp + development: + foreman: + github_repo: theforeman/foreman_leapp + hammer: + gem: hammer_cli_foreman_leapp + github_repo: theforeman/hammer-cli-foreman-leapp + module_config: foreman_leapp.yml + +puppet: + description: Puppet plugin for Foreman + foreman: + plugin_name: foreman_puppet + hammer: foreman_puppet + development: + foreman: + github_repo: theforeman/foreman_puppet + hammer: + gem: hammer_cli_foreman_puppet + github_repo: theforeman/hammer-cli-foreman-puppet + module_config: foreman_puppet.yml diff --git a/development/filter_plugins/foremanctl_dev.py b/development/filter_plugins/foremanctl_dev.py new file mode 100644 index 000000000..bbef9bd01 --- /dev/null +++ b/development/filter_plugins/foremanctl_dev.py @@ -0,0 +1,77 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import pathlib +import sys +import yaml + +# Make src filter_plugins importable to reuse dependency resolution logic +# and the shared FEATURE_MAP, avoiding duplication. +_src_filter_plugins = str(pathlib.Path(__file__).parent.parent.parent / 'src' / 'filter_plugins') +if _src_filter_plugins not in sys.path: + sys.path.insert(0, _src_filter_plugins) + +from foremanctl import FEATURE_MAP, filter_features, get_dependencies_for_feature # noqa: E402 + +_dev_features_yaml = pathlib.Path(__file__).parent.parent / 'features.yaml' + + +def _deep_merge(base, override): + """Recursively merge override into base, returning the merged dict.""" + merged = base.copy() + for key, value in override.items(): + if key in merged and isinstance(merged[key], dict) and isinstance(value, dict): + merged[key] = _deep_merge(merged[key], value) + else: + merged[key] = value + return merged + + +# Deep-merge development-specific feature extensions into the shared FEATURE_MAP. +# This adds development: blocks to existing src/ features and introduces +# dev-only features with full definitions. +with _dev_features_yaml.open() as _f: + for _feature, _data in yaml.safe_load(_f).items(): + if _feature in FEATURE_MAP: + FEATURE_MAP[_feature] = _deep_merge(FEATURE_MAP[_feature], _data) + else: + FEATURE_MAP[_feature] = _data + + +def _resolve_features(value): + """Resolve feature list including transitive dependencies, preserving order.""" + all_features = list(filter_features(value)) + deps = set() + for f in all_features: + deps.update(get_dependencies_for_feature(f)) + seen = set() + result = [] + for f in list(filter_features(list(value) + list(deps))): + if f not in seen: + seen.add(f) + result.append(f) + return result + + +def dev_plugins(value): + """Return list of development plugin configs for enabled features and their dependencies. + + Each entry is the development: block from features.yaml for features that have + any development data (foreman, hammer, or foreman_proxy). The calling tasks use + conditional guards to skip entries that lack a specific component. + """ + plugins = [] + for feature in _resolve_features(value): + dev_data = FEATURE_MAP.get(feature, {}).get('development', {}) + if dev_data: + plugins.append(dev_data) + return plugins + + +class FilterModule(object): + '''foremanctl development filters''' + + def filters(self): + return { + 'features_to_dev_plugins': dev_plugins, + } diff --git a/development/playbooks/_flavor_features/metadata.obsah.yaml b/development/playbooks/_flavor_features/metadata.obsah.yaml index d40913a1a..9d580ff47 100644 --- a/development/playbooks/_flavor_features/metadata.obsah.yaml +++ b/development/playbooks/_flavor_features/metadata.obsah.yaml @@ -2,5 +2,9 @@ variables: features: parameter: --add-feature - help: Additional features to enable in this deployment. + help: Additional features to enable in production form. + action: append_unique + dev_features: + parameter: --add-dev-feature + help: Additional features to enable in development form (git checkout). action: append_unique diff --git a/development/playbooks/deploy-dev/metadata.obsah.yaml b/development/playbooks/deploy-dev/metadata.obsah.yaml index 6ad314b3b..4b3d6f1d9 100644 --- a/development/playbooks/deploy-dev/metadata.obsah.yaml +++ b/development/playbooks/deploy-dev/metadata.obsah.yaml @@ -3,23 +3,6 @@ help: | Deploy and manage Foreman development environment with git-based Foreman and containerized backend services. variables: - foreman_development_enabled_plugins: - help: Plugin to enable (can be used multiple times) - action: append - parameter: --foreman-development-enabled-plugin - choices: - - foreman_remote_execution - - foreman_ansible - - foreman_rh_cloud - - foreman_discovery - - foreman_openscap - - foreman_bootdisk - - foreman_theme_satellite - - foreman_tasks - - foreman_webhooks - - foreman_templates - - foreman_leapp - - foreman_puppet target_host: help: Target hostname or IP address for deployment action: store diff --git a/development/roles/foreman_development/defaults/main.yaml b/development/roles/foreman_development/defaults/main.yaml index 854c9e3b3..ecbf09d36 100644 --- a/development/roles/foreman_development/defaults/main.yaml +++ b/development/roles/foreman_development/defaults/main.yaml @@ -35,119 +35,9 @@ foreman_development_database_password: "foreman" foreman_development_nodejs_stream: "22" -foreman_development_plugin_registry: - katello: - name: "katello/katello" - settings_template: "katello.yaml.j2" - manage_repo: true - extra_gemfiles: - - "gemfile.d/test.rb" - hammer: - gem: hammer_cli_katello - name: "Katello/hammer-cli-katello" - module_config: katello.yml - foreman_remote_execution: - name: "theforeman/foreman_remote_execution" - manage_repo: true - hammer: - name: "theforeman/hammer_cli_foreman_remote_execution" - module_config: foreman_remote_execution.yml - smart_proxy: - name: "theforeman/smart_proxy_remote_execution_ssh" - module_config: remote_execution_ssh.yml - foreman_ansible: - name: "theforeman/foreman_ansible" - settings_template: "foreman_ansible.yaml.j2" - manage_repo: true - hammer: - gem: hammer_cli_foreman_ansible - name: "theforeman/hammer-cli-foreman-ansible" - module_config: foreman_ansible.yml - smart_proxy: - name: "theforeman/smart_proxy_ansible" - module_config: ansible.yml - foreman_rh_cloud: - name: "theforeman/foreman_rh_cloud" - manage_repo: true - hammer: - gem: hammer_cli_foreman_rh_cloud - name: "theforeman/hammer-cli-foreman-rh-cloud" - module_config: foreman_rh_cloud.yml - foreman_discovery: - name: "theforeman/foreman_discovery" - manage_repo: true - hammer: - gem: hammer_cli_foreman_discovery - name: "theforeman/hammer-cli-foreman-discovery" - module_config: foreman_discovery.yml - smart_proxy: - name: "theforeman/smart_proxy_discovery" - module_config: discovery.yml - foreman_openscap: - name: "theforeman/foreman_openscap" - manage_repo: true - hammer: - name: "theforeman/hammer_cli_foreman_openscap" - module_config: foreman_openscap.yml - smart_proxy: - name: "theforeman/smart_proxy_openscap" - module_config: openscap.yml - foreman_bootdisk: - name: "theforeman/foreman_bootdisk" - manage_repo: true - hammer: - name: "theforeman/hammer_cli_foreman_bootdisk" - module_config: foreman_bootdisk.yml - foreman_theme_satellite: - name: "redhatsatellite/foreman_theme_satellite" - manage_repo: true - foreman_tasks: - name: "theforeman/foreman-tasks" - manage_repo: true - hammer: - gem: hammer_cli_foreman_tasks - name: "theforeman/hammer-cli-foreman-tasks" - module_config: foreman_tasks.yml - smart_proxy: - name: "theforeman/smart_proxy_dynflow" - module_config: dynflow.yml - foreman_webhooks: - name: "theforeman/foreman_webhooks" - manage_repo: true - hammer: - gem: hammer_cli_foreman_webhooks - name: "theforeman/hammer-cli-foreman-webhooks" - module_config: foreman_webhooks.yml - smart_proxy: - name: "theforeman/smart_proxy_shellhooks" - module_config: shellhooks.yml - foreman_templates: - name: "theforeman/foreman_templates" - manage_repo: true - hammer: - gem: hammer_cli_foreman_templates - name: "theforeman/hammer-cli-foreman-templates" - module_config: foreman_templates.yml - foreman_leapp: - name: "theforeman/foreman_leapp" - manage_repo: true - hammer: - gem: hammer_cli_foreman_leapp - name: "theforeman/hammer-cli-foreman-leapp" - module_config: foreman_leapp.yml - foreman_puppet: - name: "theforeman/foreman_puppet" - manage_repo: true - hammer: - gem: hammer_cli_foreman_puppet - name: "theforeman/hammer-cli-foreman-puppet" - module_config: foreman_puppet.yml - -foreman_development_default_plugins: +foreman_development_default_features: - katello - - foreman_remote_execution - -foreman_development_enabled_plugins: [] + - remote-execution foreman_development_packages: - git diff --git a/development/roles/foreman_development/tasks/hammer/main.yml b/development/roles/foreman_development/tasks/hammer/main.yml index f2d520177..ead7f3608 100644 --- a/development/roles/foreman_development/tasks/hammer/main.yml +++ b/development/roles/foreman_development/tasks/hammer/main.yml @@ -22,17 +22,17 @@ - name: Setup plugins ansible.builtin.include_tasks: hammer/plugin.yml vars: - foreman_development_plugin_config: "{{ (foreman_development_plugin_registry[plugin_item] | default({})).hammer | default({}) }}" - foreman_development_plugin_name: "{{ foreman_development_plugin_config.name.split('/')[1] }}" - foreman_development_plugin_gem: "{{ foreman_development_plugin_config.gem }}" - foreman_development_plugin_org: "{{ foreman_development_plugin_config.name.split('/')[0] }}" - foreman_development_plugin_repo_url: "https://github.com/{{ foreman_development_plugin_config.name }}.git" + foreman_development_plugin_config: "{{ plugin_item.hammer | default({}) }}" + foreman_development_plugin_name: "{{ foreman_development_plugin_config.github_repo.split('/')[1] }}" + foreman_development_plugin_gem: "{{ foreman_development_plugin_config.gem | default(foreman_development_plugin_config.github_repo.split('/')[1]) }}" + foreman_development_plugin_org: "{{ foreman_development_plugin_config.github_repo.split('/')[0] }}" + foreman_development_plugin_repo_url: "https://github.com/{{ foreman_development_plugin_config.github_repo }}.git" foreman_development_plugin_manage_repo: "{{ foreman_development_plugin_config.manage_repo | default(true) }}" foreman_development_plugin_settings_template: "{{ foreman_development_plugin_config.settings_template | default('') }}" foreman_development_plugin_module_config: "{{ foreman_development_plugin_config.module_config | default('') }}" foreman_development_plugin_extra_gemfiles: [] when: foreman_development_plugin_config != {} - loop: "{{ foreman_development_default_plugins + foreman_development_enabled_plugins }}" + loop: "{{ (dev_features + foreman_development_default_features) | features_to_dev_plugins }}" loop_control: loop_var: plugin_item diff --git a/development/roles/foreman_development/tasks/main.yaml b/development/roles/foreman_development/tasks/main.yaml index f6356496f..9673b7f84 100644 --- a/development/roles/foreman_development/tasks/main.yaml +++ b/development/roles/foreman_development/tasks/main.yaml @@ -149,14 +149,14 @@ - name: Setup plugins ansible.builtin.include_tasks: plugin.yaml vars: - foreman_development_plugin_config: "{{ foreman_development_plugin_registry[plugin_item] }}" - foreman_development_plugin_name: "{{ foreman_development_plugin_config.name.split('/')[1] }}" - foreman_development_plugin_org: "{{ foreman_development_plugin_config.name.split('/')[0] }}" - foreman_development_plugin_repo_url: "https://github.com/{{ foreman_development_plugin_config.name }}.git" - foreman_development_plugin_manage_repo: "{{ foreman_development_plugin_config.manage_repo | default(true) }}" - foreman_development_plugin_settings_template: "{{ foreman_development_plugin_config.settings_template | default('') }}" - foreman_development_plugin_extra_gemfiles: "{{ foreman_development_plugin_config.extra_gemfiles | default([]) }}" - loop: "{{ foreman_development_default_plugins + foreman_development_enabled_plugins }}" + foreman_development_plugin_name: "{{ plugin_item.foreman.github_repo.split('/')[1] }}" + foreman_development_plugin_org: "{{ plugin_item.foreman.github_repo.split('/')[0] }}" + foreman_development_plugin_repo_url: "https://github.com/{{ plugin_item.foreman.github_repo }}.git" + foreman_development_plugin_manage_repo: "{{ plugin_item.foreman.manage_repo | default(true) }}" + foreman_development_plugin_settings_template: "{{ plugin_item.foreman.settings_template | default('') }}" + foreman_development_plugin_extra_gemfiles: "{{ plugin_item.foreman.extra_gemfiles | default([]) }}" + when: plugin_item.foreman is defined + loop: "{{ (dev_features + foreman_development_default_features) | features_to_dev_plugins }}" loop_control: loop_var: plugin_item diff --git a/development/roles/foreman_development/tasks/smart-proxy/main.yml b/development/roles/foreman_development/tasks/smart-proxy/main.yml index ebc914bd9..c70fd1bd8 100644 --- a/development/roles/foreman_development/tasks/smart-proxy/main.yml +++ b/development/roles/foreman_development/tasks/smart-proxy/main.yml @@ -44,18 +44,18 @@ - name: Setup smart-proxy plugins ansible.builtin.include_tasks: smart-proxy/plugin.yml vars: - foreman_development_plugin_config: "{{ (foreman_development_plugin_registry[plugin_item] | default({})).smart_proxy | default({}) }}" - foreman_development_plugin_name: "{{ foreman_development_plugin_config.name.split('/')[1] }}" - foreman_development_plugin_gem: "{{ foreman_development_plugin_config.gem | default(foreman_development_plugin_config.name.split('/')[1]) }}" - foreman_development_plugin_org: "{{ foreman_development_plugin_config.name.split('/')[0] }}" - foreman_development_plugin_repo_url: "https://github.com/{{ foreman_development_plugin_config.name }}.git" + foreman_development_plugin_config: "{{ plugin_item.foreman_proxy | default({}) }}" + foreman_development_plugin_name: "{{ foreman_development_plugin_config.github_repo.split('/')[1] }}" + foreman_development_plugin_gem: "{{ foreman_development_plugin_config.gem | default(foreman_development_plugin_config.github_repo.split('/')[1]) }}" + foreman_development_plugin_org: "{{ foreman_development_plugin_config.github_repo.split('/')[0] }}" + foreman_development_plugin_repo_url: "https://github.com/{{ foreman_development_plugin_config.github_repo }}.git" foreman_development_plugin_manage_repo: "{{ foreman_development_plugin_config.manage_repo | default(true) }}" foreman_development_plugin_settings_template: "{{ foreman_development_plugin_config.settings_template | default('') }}" foreman_development_plugin_module_config: "{{ foreman_development_plugin_config.module_config | default('') }}" foreman_development_plugin_bundler_path_prefix: "../../" foreman_development_plugin_extra_gemfiles: [] when: foreman_development_plugin_config != {} - loop: "{{ foreman_development_default_plugins + foreman_development_enabled_plugins }}" + loop: "{{ (dev_features + foreman_development_default_features) | features_to_dev_plugins }}" loop_control: loop_var: plugin_item diff --git a/docs/developer/development-environment.md b/docs/developer/development-environment.md index 7fa78ede2..a1ea58867 100644 --- a/docs/developer/development-environment.md +++ b/docs/developer/development-environment.md @@ -67,46 +67,34 @@ All the projects set up as part of the feature are deployed as git checkouts. ## Plugin Management -### Enabled Plugins (Default) +Plugins are managed through the feature system. The development environment supports two mechanisms for enabling features: -- `katello` -- `foreman_remote_execution` +- `--add-feature` enables a feature in its **production form** (gem/package). +- `--add-dev-feature` enables a feature in its **development form** (git checkout). -### Plugin Registry +Feature definitions in `development/features.yaml` extend `src/features.yaml` with development-specific metadata (git repos, settings templates, etc.). -The system includes a plugin registry with predefined configurations: -- `katello` - Katello subscription management -- `foreman_remote_execution` - Remote execution plugin -- `foreman_ansible` - Ansible integration -- `foreman_rh_cloud` - Red Hat Cloud integration -- `foreman_discovery` - Host discovery -- `foreman_openscap` - OpenSCAP compliance -- `foreman_bootdisk` - Boot disk creation -- `foreman_openscap` - Foreman plug-in for displaying OpenSCAP audit reports -- `foreman_theme_satellite` - Branding for Satellite -- `foreman_tasks` - Tasks management engine and plugin for Foreman -- `foreman_webhooks` - Call external webhooks from Foreman -- `foreman_templates` - A plugin for Foreman to sync provisioning templates from an external source -- `foreman_leapp` - A plugin that allows to run inplace upgrades for RHEL hosts in Foreman using Leapp tool. -- `foreman_puppet` - A plugin that adds Puppet External node classification functionality to Foreman. +### Default Development Features -### Enabling Additional Plugins +- `katello` +- `remote-execution` (and its dependency `dynflow`) -#### At Deployment Time +These are always set up from git checkouts. -Use the `--foreman-development-enabled-plugin` parameter (can be used multiple times): +### Enabling Additional Features -```bash -# Enable specific plugins -./forge deploy-dev start --foreman-development-enabled-plugin katello --foreman-development-enabled-plugin foreman_ansible --foreman-development-enabled-plugin foreman_discovery +Use `--add-dev-feature` to set up a feature from git for active development: -# Enable single plugin -./forge deploy-dev start --foreman-development-enabled-plugin katello +```bash +# Enable features for development (git checkout) +./forge deploy-dev --add-dev-feature=ansible --add-dev-feature=discovery -# Enable all available plugins -./forge deploy-dev start --foreman-development-enabled-plugin katello --foreman-development-enabled-plugin foreman_remote_execution --foreman-development-enabled-plugin foreman_ansible --foreman-development-enabled-plugin foreman_rh_cloud --foreman-development-enabled-plugin foreman_discovery --foreman-development-enabled-plugin foreman_openscap --foreman-development-enabled-plugin foreman_bootdisk +# Mix production and development features +./forge deploy-dev --add-feature=puppet --add-dev-feature=ansible ``` +Use `--add-feature` to enable a feature in production form without a git checkout. + ## Development Workflow ### Initial Setup diff --git a/docs/developer/feature-metadata.md b/docs/developer/feature-metadata.md index 47fc59941..8ba134452 100644 --- a/docs/developer/feature-metadata.md +++ b/docs/developer/feature-metadata.md @@ -32,6 +32,19 @@ The following properties are defined: * `hammer` (_String_): The name of the Hammer plugin to be enabled (the package installed will be `hammer-cli-plugin-{{ hammer }}`). * `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`. +* `development` (_Hash_): Development environment metadata for this feature, used by the `development/` playbooks. This block is typically defined in `development/features.yaml` rather than `src/features.yaml`, and is deep-merged into the feature definition at runtime. Contains component-specific sub-hashes: + * `foreman` (_Hash_): Development config for the Foreman plugin. + * `github_repo` (_String_): GitHub `org/repo` for git checkout (e.g., `theforeman/foreman_remote_execution`). + * `settings_template` (_String_): Jinja2 template for plugin settings (optional). + * `extra_gemfiles` (_Array_ of _String_): Additional Gemfile paths to include (optional). + * `hammer` (_Hash_): Development config for the Hammer CLI plugin. + * `gem` (_String_): Ruby gem name, if different from the repo name (optional). + * `github_repo` (_String_): GitHub `org/repo` for git checkout. + * `module_config` (_String_): Hammer module config filename (optional). + * `foreman_proxy` (_Hash_): Development config for the Smart Proxy plugin. + * `github_repo` (_String_): GitHub `org/repo` for git checkout. + * `module_config` (_String_): Smart proxy module config filename (optional). + Properties can be omitted. ## Examples @@ -139,3 +152,41 @@ container_gateway: foreman_proxy: plugin_name: smart_proxy_container_gateway ``` + +## Development Feature Overlay + +The development environment extends `src/features.yaml` with `development/features.yaml`. At runtime, the development filter plugin deep-merges the two files: + +- **Existing features** (those already in `src/features.yaml`): The development file adds a `development:` block only. All other fields (`plugin_name`, `hammer`, `dependencies`, etc.) are inherited from `src/`. +- **New features** (not in `src/features.yaml`): The development file carries a full feature definition including top-level properties and a `development:` block. + +### Example + +In `src/features.yaml`: +```yaml +remote-execution: + description: Remote Execution plugin for Foreman + foreman: + plugin_name: foreman_remote_execution + foreman_proxy: + plugin_name: remote_execution_ssh + hammer: foreman_remote_execution + dependencies: + - dynflow +``` + +In `development/features.yaml`: +```yaml +remote-execution: + development: + foreman: + github_repo: theforeman/foreman_remote_execution + hammer: + github_repo: theforeman/hammer_cli_foreman_remote_execution + module_config: foreman_remote_execution.yml + foreman_proxy: + github_repo: theforeman/smart_proxy_remote_execution_ssh + module_config: remote_execution_ssh.yml +``` + +The merged result retains all `src/` fields and adds the `development:` block with git repository and config information used by the development playbooks. diff --git a/src/vars/defaults.yml b/src/vars/defaults.yml index 7fae5df26..77da7456f 100644 --- a/src/vars/defaults.yml +++ b/src/vars/defaults.yml @@ -4,4 +4,5 @@ database_mode: internal tuning: default flavor: katello features: [] -enabled_features: "{{ (flavor_features + features) }}" +dev_features: [] +enabled_features: "{{ (flavor_features + features + dev_features) }}"