From 80d53f0ff327f2ae0c04d28364dea077f488980d Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Mon, 16 Jun 2025 12:12:26 +0200 Subject: [PATCH] make features and flavors configurable This PR introduces two new concepts: `flavor`s and `feature`s. A feature is an abstract representation of "the deployed system can now do X", usually implemented by enabling a Foreman/Pulp/Hammer plugin (or a collection of these). A flavor is a set of features that are enabled by default and can not be disabled. This is to allow our common deployment types like "vanilla foreman", "katello", "satellite" and similar. The idea is to allow people to select a baseline using `--flavor` and then further adjust it to their liking using `--feature` and the code then figures out what foreman/hammer/pulp plugin (or combination of these) needs to be enabled for that. --- .github/workflows/test.yml | 20 +++++++++---------- DEVELOPMENT.md | 2 +- .../playbooks/deploy-dev/deploy-dev.yaml | 1 + docs/deployment.md | 19 ++++++++++++++++++ .../_flavor_features/metadata.obsah.yaml | 13 ++++++++++++ src/playbooks/deploy/deploy.yaml | 7 +++++++ src/playbooks/deploy/metadata.obsah.yaml | 1 + src/playbooks/pull-images/metadata.obsah.yaml | 1 + src/playbooks/pull-images/pull-images.yaml | 9 +++++++++ .../setup-foreman-proxy/metadata.obsah.yaml | 6 ------ .../setup-foreman-proxy.yaml | 16 --------------- .../setup-hammer/metadata.obsah.yaml | 6 ------ src/playbooks/setup-hammer/setup-hammer.yaml | 13 ------------ src/roles/foreman/tasks/main.yaml | 4 ++++ src/roles/hammer/defaults/main.yml | 9 ++++----- src/roles/pulp/defaults/main.yaml | 11 ++++++++++ src/vars/base.yaml | 5 +++++ src/vars/defaults.yml | 3 +++ src/vars/flavors/katello.yml | 6 ++++++ src/vars/images.yml | 3 +++ 20 files changed, 98 insertions(+), 57 deletions(-) create mode 100644 src/playbooks/_flavor_features/metadata.obsah.yaml delete mode 100644 src/playbooks/setup-foreman-proxy/metadata.obsah.yaml delete mode 100644 src/playbooks/setup-foreman-proxy/setup-foreman-proxy.yaml delete mode 100644 src/playbooks/setup-hammer/metadata.obsah.yaml delete mode 100644 src/playbooks/setup-hammer/setup-hammer.yaml create mode 100644 src/vars/flavors/katello.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f5c47260b..3eed81135 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -88,12 +88,12 @@ jobs: - name: Run deployment run: | ./foremanctl deploy --certificate-source=${{ matrix.certificate_source }} --foreman-initial-admin-password=changeme - - name: Setup hammer + - name: Add optional feature - hammer run: | - ./foremanctl setup-hammer - - name: Set up Foreman Proxy + ./foremanctl deploy --add-feature hammer + - name: Add optional feature - foreman-proxy run: | - ./foremanctl setup-foreman-proxy + ./foremanctl deploy --add-feature foreman-proxy - name: Run tests run: | ./forge test --pytest-args="--certificate-source=${{ matrix.certificate_source }}" @@ -194,6 +194,12 @@ jobs: - name: Run deployment run: | ./foremanctl deploy --foreman-initial-admin-password=changeme + - name: Add optional feature - hammer + run: | + ./foremanctl deploy --add-feature hammer + - name: Add optional feature - foreman-proxy + run: | + ./foremanctl deploy --add-feature foreman-proxy - name: Stop services run: vagrant ssh quadlet -- sudo systemctl stop foreman.target @@ -206,12 +212,6 @@ jobs: - name: Run deployment run: | ./foremanctl deploy - - name: Setup hammer - run: | - ./foremanctl setup-hammer - - name: Set up Foreman Proxy - run: | - ./foremanctl setup-foreman-proxy - name: Run tests run: | ./forge test diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 4e77c6dd6..469713510 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -34,7 +34,7 @@ source .venv/bin/activate ``` ./forge setup-repositories -./foremanctl setup-hammer +./foremanctl deploy --add-feature hammer ``` To teardown the environment: diff --git a/development/playbooks/deploy-dev/deploy-dev.yaml b/development/playbooks/deploy-dev/deploy-dev.yaml index dfa10cee7..738381cd4 100644 --- a/development/playbooks/deploy-dev/deploy-dev.yaml +++ b/development/playbooks/deploy-dev/deploy-dev.yaml @@ -4,6 +4,7 @@ become: true vars_files: - "../../../src/vars/defaults.yml" + - "../../../src/vars/flavors/{{ flavor }}.yml" - "../../../src/vars/{{ certificate_source }}_certificates.yml" - "../../../src/vars/images.yml" - "../../../src/vars/database.yml" diff --git a/docs/deployment.md b/docs/deployment.md index 4c98e6942..90ded4159 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -23,6 +23,25 @@ For example, pre-pulling images to reduce the core deployment utility runtime. 6. Run deployment utility 7. Post deploy checks +### Features and Flavors + +To allow deployments with different sets of functionality enabled, the deployment utility supports features and flavors. + +- A feature is an abstract representation of "the deployed system can now do X", usually implemented by enabling a Foreman/Pulp/Hammer plugin (or a collection of these). +- A flavor is a set of features that are enabled by default and can not be disabled. This is to allow common deployment types like "vanilla foreman", "katello", "satellite" and similar. + +Additionally to the functionality offered by plugins, we define the following "base" features: +- `foreman` to deploy the main Rails app and make the deployment a "Server" +- `foreman-proxy` to deploy the Foreman Proxy code +- `hammer` to deploy the base CLI + +These base features control which plugins are enabled when a feature is requested. +- `foreman` + `remote_execution` = `foreman_remote_execution` +- `foreman-proxy` + `remote_execution` = `smart_proxy_remote_execution_ssh` +- `hammer` + `remote_execution` = `hammer_cli_foreman_remote_execution` + +A deployment can have multiple base features enabled. + ### Authenticated Registry Handling In the non-default case where the image sources are supplied from an authenticated location users will need to inject a login step. diff --git a/src/playbooks/_flavor_features/metadata.obsah.yaml b/src/playbooks/_flavor_features/metadata.obsah.yaml new file mode 100644 index 000000000..d20ed4ee2 --- /dev/null +++ b/src/playbooks/_flavor_features/metadata.obsah.yaml @@ -0,0 +1,13 @@ +--- +variables: + flavor: + help: Base flavor to use in this deployment. + features: + parameter: --add-feature + help: Additional features to enable in this deployment. + action: append_unique + remove_features: + parameter: --remove-feature + help: Additional features to disable in this deployment. + action: remove + dest: features diff --git a/src/playbooks/deploy/deploy.yaml b/src/playbooks/deploy/deploy.yaml index 59a525a80..6982ebb7c 100644 --- a/src/playbooks/deploy/deploy.yaml +++ b/src/playbooks/deploy/deploy.yaml @@ -5,6 +5,7 @@ become: true vars_files: - "../../vars/defaults.yml" + - "../../vars/flavors/{{ flavor }}.yml" - "../../vars/{{ certificate_source }}_certificates.yml" - "../../vars/images.yml" - "../../vars/database.yml" @@ -29,4 +30,10 @@ - pulp - foreman - role: systemd_target + - role: foreman_proxy + when: + - "'foreman-proxy' in enabled_features" + - role: hammer + when: + - "'hammer' in enabled_features" - post_install diff --git a/src/playbooks/deploy/metadata.obsah.yaml b/src/playbooks/deploy/metadata.obsah.yaml index 6e451d5db..997aaec98 100644 --- a/src/playbooks/deploy/metadata.obsah.yaml +++ b/src/playbooks/deploy/metadata.obsah.yaml @@ -17,3 +17,4 @@ include: - _database_mode - _database_connection - _tuning + - _flavor_features diff --git a/src/playbooks/pull-images/metadata.obsah.yaml b/src/playbooks/pull-images/metadata.obsah.yaml index f1c01fbd7..9f4f8ed05 100644 --- a/src/playbooks/pull-images/metadata.obsah.yaml +++ b/src/playbooks/pull-images/metadata.obsah.yaml @@ -4,3 +4,4 @@ help: | include: - _database_mode + - _flavor_features diff --git a/src/playbooks/pull-images/pull-images.yaml b/src/playbooks/pull-images/pull-images.yaml index 59c93b4b5..fff77f6e7 100644 --- a/src/playbooks/pull-images/pull-images.yaml +++ b/src/playbooks/pull-images/pull-images.yaml @@ -4,7 +4,9 @@ - quadlet vars_files: - "../../vars/defaults.yml" + - "../../vars/flavors/{{ flavor }}.yml" - "../../vars/images.yml" + - "../../vars/base.yaml" become: true tasks: - name: Install podman @@ -17,6 +19,13 @@ name: "{{ item }}" loop: "{{ images }}" + - name: Pull foreman_proxy images + containers.podman.podman_image: + name: "{{ item }}" + loop: "{{ foreman_proxy_images }}" + when: + - "'foreman-proxy' in enabled_features" + - name: Pull database images containers.podman.podman_image: name: "{{ item }}" diff --git a/src/playbooks/setup-foreman-proxy/metadata.obsah.yaml b/src/playbooks/setup-foreman-proxy/metadata.obsah.yaml deleted file mode 100644 index 04f85f245..000000000 --- a/src/playbooks/setup-foreman-proxy/metadata.obsah.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -help: | - Set up Foreman Proxy - -include: - - _certificate_source diff --git a/src/playbooks/setup-foreman-proxy/setup-foreman-proxy.yaml b/src/playbooks/setup-foreman-proxy/setup-foreman-proxy.yaml deleted file mode 100644 index c3ffb2891..000000000 --- a/src/playbooks/setup-foreman-proxy/setup-foreman-proxy.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -- name: Set up Foreman Proxy - hosts: - - quadlet - become: true - vars_files: - - "../../vars/defaults.yml" - - "../../vars/{{ certificate_source }}_certificates.yml" - - "../../vars/foreman.yml" - - "../../vars/images.yml" - vars: - foreman_url: "https://{{ ansible_facts['fqdn'] }}" - - roles: - - pre_install - - foreman_proxy diff --git a/src/playbooks/setup-hammer/metadata.obsah.yaml b/src/playbooks/setup-hammer/metadata.obsah.yaml deleted file mode 100644 index 83dd65828..000000000 --- a/src/playbooks/setup-hammer/metadata.obsah.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -help: | - Setup hammer - -include: - - _certificate_source diff --git a/src/playbooks/setup-hammer/setup-hammer.yaml b/src/playbooks/setup-hammer/setup-hammer.yaml deleted file mode 100644 index a1d125c66..000000000 --- a/src/playbooks/setup-hammer/setup-hammer.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- name: Setup hammer on the quadlet machine - hosts: - - quadlet - become: true - vars_files: - - "../../vars/defaults.yml" - - "../../vars/{{ certificate_source }}_certificates.yml" - - "../../vars/foreman.yml" - vars: - hammer_ca_certificate: "{{ server_ca_certificate }}" - roles: - - hammer diff --git a/src/roles/foreman/tasks/main.yaml b/src/roles/foreman/tasks/main.yaml index e748b04f0..f08bdb179 100644 --- a/src/roles/foreman/tasks/main.yaml +++ b/src/roles/foreman/tasks/main.yaml @@ -105,6 +105,7 @@ - 'foreman-client-key,type=mount,target=/etc/foreman/client_key.pem' env: FOREMAN_PUMA_WORKERS: "{{ foreman_puma_workers }}" + FOREMAN_ENABLED_PLUGINS: "{{ foreman_plugins | join(' ') }}" quadlet_options: - | [Install] @@ -135,6 +136,7 @@ env: DYNFLOW_REDIS_URL: "redis://localhost:6379/6" REDIS_PROVIDER: "DYNFLOW_REDIS_URL" + FOREMAN_ENABLED_PLUGINS: "{{ foreman_plugins | join(' ') }}" command: "/usr/libexec/foreman/sidekiq-selinux -e production -r ./extras/dynflow-sidekiq.rb -C /etc/foreman/dynflow/%i.yml" quadlet_options: - | @@ -173,6 +175,8 @@ - bin/rails db:migrate && bin/rails db:seed detach: false network: host + env: + FOREMAN_ENABLED_PLUGINS: "{{ foreman_plugins | join(' ') }}" secrets: - 'foreman-database-url,type=env,target=DATABASE_URL' - 'foreman-seed-admin-user,type=env,target=SEED_ADMIN_USER' diff --git a/src/roles/hammer/defaults/main.yml b/src/roles/hammer/defaults/main.yml index 030d4bfd1..ab69142d6 100644 --- a/src/roles/hammer/defaults/main.yml +++ b/src/roles/hammer/defaults/main.yml @@ -1,8 +1,7 @@ --- hammer_foreman_server_url: "https://{{ ansible_facts['fqdn'] }}" hammer_ca_certificate: "" -hammer_packages: - - hammer-cli-plugin-foreman - - hammer-cli-plugin-foreman_tasks - - hammer-cli-plugin-foreman_remote_execution - - hammer-cli-plugin-katello +hammer_default_plugins: + - foreman +hammer_plugins: [] +hammer_packages: "{{ (hammer_default_plugins+hammer_plugins) | map('regex_replace', '^', 'hammer-cli-plugin-') }}" diff --git a/src/roles/pulp/defaults/main.yaml b/src/roles/pulp/defaults/main.yaml index d2c5529ab..23eb05d39 100644 --- a/src/roles/pulp/defaults/main.yaml +++ b/src/roles/pulp/defaults/main.yaml @@ -21,6 +21,15 @@ pulp_pulp_url: "http://{{ ansible_facts['fqdn'] }}:24817" pulp_enable_analytics: false +pulp_default_plugins: + - pulp_certguard + - pulp_file + - pulp_smart_proxy +pulp_plugins: + - pulp_container + - pulp_rpm +pulp_enabled_plugins: "{{ pulp_default_plugins + pulp_plugins }}" + pulp_database_name: pulp pulp_database_user: pulp pulp_database_host: localhost @@ -35,6 +44,8 @@ pulp_settings_database_env: PULP_DATABASES__default__PORT: "{{ pulp_database_port }}" PULP_DATABASES__default__OPTIONS__sslmode: "{{ pulp_database_ssl_mode }}" PULP_DATABASES__default__OPTIONS__sslrootcert: "{{ pulp_database_ssl_ca }}" + PULP_ENABLED_PLUGINS: >- + {{ pulp_enabled_plugins }} # The arrays (AUTH_BACKENDS, AUTH_CLASSES) need to be strings # that get parsed to array by dynaconf, so we're using block scalars for them diff --git a/src/vars/base.yaml b/src/vars/base.yaml index 5ad8d2f70..32c6f2c3f 100644 --- a/src/vars/base.yaml +++ b/src/vars/base.yaml @@ -20,6 +20,7 @@ foreman_client_key: "{{ client_key }}" foreman_client_certificate: "{{ client_certificate }}" foreman_oauth_consumer_key: abcdefghijklmnopqrstuvwxyz123456 foreman_oauth_consumer_secret: abcdefghijklmnopqrstuvwxyz123456 +foreman_plugins: "{{ enabled_features | reject('contains', 'content/') | difference(['hammer', 'foreman-proxy', 'foreman']) }}" foreman_url: "https://{{ ansible_facts['fqdn'] }}" httpd_server_ca_certificate: "{{ server_ca_certificate }}" @@ -29,3 +30,7 @@ httpd_server_key: "{{ server_key }}" pulp_content_origin: "https://{{ ansible_facts['fqdn'] }}" pulp_pulp_url: "https://{{ ansible_facts['fqdn'] }}" +pulp_plugins: "{{ enabled_features | select('contains', 'content/') | map('replace', 'content/', 'pulp_') | list }}" + +hammer_ca_certificate: "{{ server_ca_certificate }}" +hammer_plugins: "{{ foreman_plugins | map('replace', 'foreman-tasks', 'foreman_tasks') | list }}" diff --git a/src/vars/defaults.yml b/src/vars/defaults.yml index 879ac747f..5ea8bd4c1 100644 --- a/src/vars/defaults.yml +++ b/src/vars/defaults.yml @@ -2,3 +2,6 @@ certificate_source: default database_mode: internal tuning_profile: development +flavor: katello +features: [] +enabled_features: "{{ (flavor_features + features) }}" diff --git a/src/vars/flavors/katello.yml b/src/vars/flavors/katello.yml new file mode 100644 index 000000000..465facc92 --- /dev/null +++ b/src/vars/flavors/katello.yml @@ -0,0 +1,6 @@ +--- +flavor_features: + - foreman + - katello + - content/container + - content/rpm diff --git a/src/vars/images.yml b/src/vars/images.yml index dc634981f..669d64fd7 100644 --- a/src/vars/images.yml +++ b/src/vars/images.yml @@ -21,3 +21,6 @@ images: database_images: - "{{ postgresql_container_image }}:{{ postgresql_container_tag }}" + +foreman_proxy_images: + - "{{ foreman_proxy_container_image }}:{{ foreman_proxy_container_tag }}"