Skip to content

Commit bec957f

Browse files
committed
Merge PR theforeman#501: Podman quadlet .image file support
2 parents 4fd5d4b + 0668f33 commit bec957f

67 files changed

Lines changed: 504 additions & 271 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/developer/deployment.md

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,85 @@ IOP (Insights Operating Platform) deploys on-premise Insights services for advis
5252

5353
See [IOP Architecture](iop.md) for details on the services deployed and configuration options.
5454

55-
### Authenticated Registry Handling
55+
### Image Management
5656

57-
If you need to pull images from private or authenticated container registries, you can configure registry authentication using Podman's auth file.
57+
foremanctl uses Podman quadlet `.image` units to separate image sourcing from container definitions. Each unique container image (foreman, candlepin, pulp, etc.) gets a corresponding `.image` file deployed to `/etc/containers/systemd/`. Container roles reference these by name rather than by full image URL:
5858

59-
#### Setting up Registry Authentication
59+
```ini
60+
# /etc/containers/systemd/foreman.image
61+
[Image]
62+
Image=quay.io/foreman/foreman:nightly
63+
```
64+
65+
```ini
66+
# /etc/containers/systemd/foreman.container (excerpt)
67+
[Container]
68+
Image=foreman.image
69+
```
70+
71+
All containers that share a base image (e.g., foreman, dynflow-sidekiq, foreman-recurring) reference the same `.image` unit. systemd ensures the image is pulled before any dependent container starts.
72+
73+
#### Image Precedence
74+
75+
During `foremanctl deploy`, foremanctl resolves which `.image` files to place in `/etc/containers/systemd/` using a three-tier precedence model:
76+
77+
1. **Admin overrides** (`/etc/foremanctl/images.d/`) — highest priority. Place custom `.image` files here to override any default.
78+
2. **Vendor/RPM overrides** (`/usr/share/foremanctl/images.d/`) — used by packaging or vendor layers to set image sources via RPM.
79+
3. **Generated defaults** — built from the image variables in `images.yml` during deploy.
80+
81+
This follows the standard Linux filesystem hierarchy: `/etc/` is for admin-controlled configuration, `/usr/share/` is for vendor-provided data that users should not edit.
82+
83+
#### Use Cases
84+
85+
**Upstream default (no user action):** No `.image` files exist in `/usr/share/foremanctl/images.d/` or `/etc/foremanctl/images.d/`. foremanctl generates default `.image` files from its built-in `images.yml`:
86+
87+
```ini
88+
# /etc/containers/systemd/foreman.image (generated by foremanctl)
89+
[Image]
90+
Image=quay.io/foreman/foreman:nightly
91+
```
6092

61-
1. **Login to your registry** using Podman and save credentials to the default auth file location:
93+
**RPM-provided image definitions (no user action):** An RPM installs pre-rendered `.image` files to the vendor directory (`/usr/share/foremanctl/images.d/foreman.image`, etc.). foremanctl copies them to `/etc/containers/systemd/` during deploy. The RPM's presence is the configuration:
94+
95+
```ini
96+
# /usr/share/foremanctl/images.d/foreman.image
97+
[Image]
98+
Image=registry.example.com/org/foreman:6.17
99+
AuthFile=/etc/foreman/registry-auth.json
100+
```
101+
102+
**User's own registry (user-configured):** The user creates `.image` files in `/etc/foremanctl/images.d/` pointing at their own registry (e.g., Foreman+Katello/Pulp). These override any vendor-provided files:
103+
104+
```ini
105+
# /etc/foremanctl/images.d/foreman.image
106+
[Image]
107+
Image=katello.example.com/Default_Organization/foreman:6.17
108+
AuthFile=/etc/foreman/registry-auth.json
109+
```
110+
111+
**Developer testing a container build:** The developer creates a `.image` file in `/etc/foremanctl/images.d/` to test a specific image build:
112+
113+
```ini
114+
# /etc/foremanctl/images.d/foreman.image
115+
[Image]
116+
Image=quay.io/foreman/foreman:pr-12345
117+
```
118+
119+
#### Authenticated Registry Handling
120+
121+
If you need to pull images from private or authenticated container registries:
122+
123+
1. **Login to your registry** using Podman and save credentials to an auth file:
62124
```bash
63125
podman login <registry> --authfile=/etc/foreman/registry-auth.json
64126
```
65127

66-
2. **Deploy as usual** - foremanctl will automatically detect and use the authentication file:
128+
2. **Set the global auth file** so all generated `.image` units include it:
67129
```bash
68-
./foremanctl deploy
130+
./foremanctl deploy --registry-auth-file=/etc/foreman/registry-auth.json
69131
```
70132

71-
This approach integrates seamlessly with both the happy path and advanced deployment paths described above. The authentication is handled transparently during image pulling operations.
133+
This only affects generated defaults (tier 3). Admin and vendor `.image` files manage their own `AuthFile=` directives.
72134

73135
## Deployer Stages
74136

@@ -81,7 +143,7 @@ Some of the stages will be made available to the user to run independently.
81143
a. system requirements
82144
b. tuning requirements
83145
c. certificate requirements
84-
4. Place `.container` files
146+
4. Place `.image` and `.container` files
85147
5. Create podman secrets
86148
6. Reload systemd
87149
7. (re)start services
@@ -103,7 +165,9 @@ When the user provides parameters to alter the deployment, the deployment utilit
103165

104166
## Container changes (Upgrades)
105167

106-
When the running containers change because the stream was changed in the configuration, the deployment utility will pull the new images and use the new images when starting services.
168+
When the running containers change because the stream was changed in the configuration, the deployment utility regenerates `.image` units with the new image references and restarts services to pull and use the updated images.
169+
170+
Admin overrides in `/etc/foremanctl/images.d/` take precedence over `images.yml` values — if an admin-provided `.image` file pins a specific tag, it will not be changed by an upgrade.
107171

108172
As there is currently no way for the deployment utility to verify which image version is used by a running service, the user is advised to stop all services before performing an upgrade.
109173

src/playbooks/pull-images/pull-images.yaml

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,49 @@
1111
roles:
1212
- role: pre_install
1313
post_tasks:
14-
- name: Pull an image
15-
containers.podman.podman_image:
14+
- name: Deploy core image units
15+
ansible.builtin.include_role:
1616
name: "{{ item }}"
17-
environment:
18-
REGISTRY_AUTH_FILE: "{{ registry_auth_file }}"
19-
loop: "{{ images }}"
17+
tasks_from: image.yaml
18+
loop:
19+
- foreman
20+
- candlepin
21+
- pulp
22+
- redis
2023

21-
- name: Pull foreman_proxy images
22-
containers.podman.podman_image:
23-
name: "{{ item }}"
24-
environment:
25-
REGISTRY_AUTH_FILE: "{{ registry_auth_file }}"
26-
loop: "{{ foreman_proxy_images }}"
27-
when:
28-
- "'foreman-proxy' in enabled_features"
24+
- name: Deploy database image units
25+
ansible.builtin.include_role:
26+
name: postgresql
27+
tasks_from: image.yaml
28+
when: database_mode == 'internal'
29+
30+
- name: Deploy proxy image units
31+
ansible.builtin.include_role:
32+
name: foreman_proxy
33+
tasks_from: image.yaml
34+
when: "'foreman-proxy' in enabled_features"
2935

30-
- name: Pull database images
31-
containers.podman.podman_image:
36+
- name: Deploy IOP image units
37+
ansible.builtin.include_role:
3238
name: "{{ item }}"
33-
environment:
34-
REGISTRY_AUTH_FILE: "{{ registry_auth_file }}"
35-
loop: "{{ database_images }}"
36-
when:
37-
- database_mode == 'internal'
39+
tasks_from: image.yaml
40+
loop:
41+
- iop_kafka
42+
- iop_ingress
43+
- iop_puptoo
44+
- iop_yuptoo
45+
- iop_engine
46+
- iop_gateway
47+
- iop_inventory
48+
- iop_advisor
49+
- iop_remediation
50+
- iop_vmaas
51+
- iop_vulnerability
52+
- iop_advisor_frontend
53+
- iop_inventory_frontend
54+
- iop_vulnerability_frontend
55+
when: "'iop' in enabled_features"
56+
57+
- name: Run daemon reload
58+
ansible.builtin.systemd:
59+
daemon_reload: true

src/roles/candlepin/defaults/main.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ candlepin_ciphers:
1414
- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
1515
candlepin_container_image: quay.io/foreman/candlepin
1616
candlepin_container_tag: "4.4.14"
17-
candlepin_registry_auth_file: /etc/foreman/registry-auth.json
1817

1918
candlepin_database_host: localhost
2019
candlepin_database_port: 5432
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
- name: Deploy candlepin image unit
3+
ansible.builtin.include_role:
4+
name: images
5+
tasks_from: deploy_image.yaml
6+
vars:
7+
images_definition:
8+
name: candlepin
9+
image: "{{ candlepin_container_image }}:{{ candlepin_container_tag }}"

src/roles/candlepin/tasks/main.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
---
2+
- name: Deploy candlepin image
3+
ansible.builtin.include_tasks: image.yaml
4+
25
- name: Create log directories
36
ansible.builtin.file:
47
path: "{{ item }}"
@@ -55,17 +58,10 @@
5558
notify:
5659
- Restart candlepin
5760

58-
- name: Pull the Candlepin container image
59-
containers.podman.podman_image:
60-
name: "{{ candlepin_container_image }}:{{ candlepin_container_tag }}"
61-
state: present
62-
environment:
63-
REGISTRY_AUTH_FILE: "{{ candlepin_registry_auth_file }}"
64-
6561
- name: Deploy Candlepin quadlet
6662
containers.podman.podman_container:
6763
name: "candlepin"
68-
image: "{{ candlepin_container_image }}:{{ candlepin_container_tag }}"
64+
image: candlepin.image
6965
state: quadlet
7066
network: host
7167
hostname: "{{ ansible_facts['hostname'] }}.local"

src/roles/foreman/defaults/main.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
foreman_container_image: "quay.io/foreman/foreman"
33
foreman_container_tag: "nightly"
4-
foreman_registry_auth_file: /etc/foreman/registry-auth.json
54

65
foreman_database_name: foreman
76
foreman_database_user: foreman

src/roles/foreman/tasks/image.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
- name: Deploy foreman image unit
3+
ansible.builtin.include_role:
4+
name: images
5+
tasks_from: deploy_image.yaml
6+
vars:
7+
images_definition:
8+
name: foreman
9+
image: "{{ foreman_container_image }}:{{ foreman_container_tag }}"

src/roles/foreman/tasks/main.yaml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
---
2-
- name: Pull the Foreman container image
3-
containers.podman.podman_image:
4-
name: "{{ foreman_container_image }}:{{ foreman_container_tag }}"
5-
state: present
6-
environment:
7-
REGISTRY_AUTH_FILE: "{{ foreman_registry_auth_file }}"
2+
- name: Deploy foreman image
3+
ansible.builtin.include_tasks: image.yaml
84

95
- name: Create secret for DATABASE_URL
106
containers.podman.podman_secret:
@@ -98,7 +94,7 @@
9894
- name: Deploy Foreman Container
9995
containers.podman.podman_container:
10096
name: "foreman"
101-
image: "{{ foreman_container_image }}:{{ foreman_container_tag }}"
97+
image: foreman.image
10298
state: quadlet
10399
sdnotify: true
104100
network: host
@@ -136,7 +132,7 @@
136132
containers.podman.podman_container:
137133
name: "dynflow-sidekiq-%i"
138134
quadlet_filename: "dynflow-sidekiq@"
139-
image: "{{ foreman_container_image }}:{{ foreman_container_tag }}"
135+
image: foreman.image
140136
state: quadlet
141137
sdnotify: true
142138
network: host
@@ -191,7 +187,7 @@
191187
name: "foreman-recurring-{{ item.instance }}"
192188
quadlet_filename: "foreman-recurring@{{ item.instance }}"
193189
state: quadlet
194-
image: "{{ foreman_container_image }}:{{ foreman_container_tag }}"
190+
image: foreman.image
195191
sdnotify: false
196192
network: host
197193
hostname: "{{ ansible_facts['hostname'] }}.local"

src/roles/foreman_proxy/defaults/main.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
foreman_proxy_container_image: "quay.io/foreman/foreman-proxy"
33
foreman_proxy_container_tag: "nightly"
4-
foreman_proxy_registry_auth_file: /etc/foreman/registry-auth.json
54

65
foreman_proxy_name: "{{ ansible_facts['fqdn'] }}"
76
foreman_proxy_https_port: 8443
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
- name: Deploy foreman-proxy image unit
3+
ansible.builtin.include_role:
4+
name: images
5+
tasks_from: deploy_image.yaml
6+
vars:
7+
images_definition:
8+
name: foreman-proxy
9+
image: "{{ foreman_proxy_container_image }}:{{ foreman_proxy_container_tag }}"

0 commit comments

Comments
 (0)