Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/branch-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ jobs:
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
test-matrix: >-
[
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"driver-podman"},
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"e2e-podman"},
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"driver-podman"}
{"environment":"fedora-podman-rootful","installer":"rpm","testsuite":"driver-podman"},
{"environment":"fedora-podman-rootless","installer":"rpm","testsuite":"e2e-podman"},
{"environment":"fedora-podman-rootless","installer":"rpm","testsuite":"driver-podman"}
]

docker-e2e:
Expand Down
7 changes: 4 additions & 3 deletions CI.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ runs without optional E2E labels. Core integration qualification builds and inst
the DEB on Ubuntu with Docker and installs the CLI and gateway RPMs on Fedora with
rootful and rootless Podman. These lanes run conformance using the matching runtime
images. Release Dev and Release Tag use the same package installers.
Fedora provider-refresh tests also use RPMs. The Podman driver-specific suites
retain the binary installer because their fixtures configure its system service,
local HTTP gateway, and CLI path. The manual Integration Tests workflow defaults
Fedora provider-refresh tests also use RPMs. The Podman driver-specific branch
lanes use RPMs for rootful and rootless user-namespace comparisons and rootless
Podman E2E. Their fixtures use the installed gateway's registration, active
configuration, and service context. The manual Integration Tests workflow defaults
to the package installers and downloads the packages selected by its matrix.

Three opt-in labels enable the long-running E2E suites:
Expand Down
21 changes: 19 additions & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,27 @@ Run the portable subset in a disposable rootless Podman guest:

```shell
nix run .#build-artifacts
nix run .#tmachine -- test fedora-podman-rootless binaries e2e-podman
nix run .#tmachine -- test fedora-podman-rootless binaries driver-podman
nix run .#tmachine -- test fedora-podman-rootless rpm e2e-podman
nix run .#tmachine -- test fedora-podman-rootless rpm driver-podman
```

The driver suites also support the `binaries` installer. The shared installer
roles save the active gateway configuration, registration name, service scope,
service owner, and network name in `/var/lib/openshell-test/gateway.yaml`.
Suites resolve `openshell` from PATH and use that registration, including the
packaged gateway's HTTPS client credentials. Namespace fixtures modify the
active qualification configuration and restart its system or user service.
Failure diagnostics select the matching journal unit and user ID. Missing
metadata or credentials fail the run; suites do not replace package setup with
an HTTP gateway. Ansible sources participate in tmachine's installation cache
hash, so older cached installations are rebuilt with this metadata.

The `driver-podman` suite supports rootful and rootless Podman. The
`e2e-podman` archive requires rootless Podman for its host workload fixtures.
DEB and RPM installers share the gateway role; available environments pair
DEB with Ubuntu/Docker and RPM with Fedora/Podman. A DEB/Podman run requires an
Ubuntu Podman environment.

Print the exact tmachine archive selection as a shell `PODMAN_CI_TESTS` array:

```shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
- name: Wait for SSH
ansible.builtin.wait_for_connection:

- name: Resolve installed gateway context
ansible.builtin.include_role:
name: openshell_test_gateway

- name: Detect tmachine container runtime
ansible.builtin.include_role:
name: tmachine_container_runtime
Expand All @@ -38,7 +42,7 @@
- name: Read OpenShell gateway configuration
become: true
ansible.builtin.slurp:
src: /etc/openshell/gateway.toml
src: "{{ openshell_test_gateway.config_path }}"
register: openshell_gateway_config

- name: Require unconfigured Podman user namespaces
Expand Down
55 changes: 26 additions & 29 deletions tests/ansible/playbooks/drivers/podman/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@
- name: Wait for SSH
ansible.builtin.wait_for_connection:

- name: Resolve installed gateway context
ansible.builtin.include_role:
name: openshell_test_gateway

- name: Detect tmachine container runtime
ansible.builtin.include_role:
name: tmachine_container_runtime

- name: Require rootless Podman for the E2E workload fixtures
ansible.builtin.assert:
that:
- tmachine_container_runtime_name == 'podman'
- tmachine_container_runtime_is_rootless
fail_msg: The Podman E2E archive requires the rootless Podman environment

- name: Create Podman E2E test directory
become: true
ansible.builtin.file:
Expand Down Expand Up @@ -46,17 +61,7 @@
- "{{ podman_e2e_test_root }}/openshell-e2e-python-dev.tar"
environment:
HOME: /home/tmachine
XDG_RUNTIME_DIR: /run/user/1000

- name: Remove any previous OpenShell gateway registration
ansible.builtin.command:
argv: [/usr/local/bin/openshell, gateway, remove, tmachine]
changed_when: false
failed_when: false

- name: Register the configured OpenShell gateway
ansible.builtin.command:
argv: [/usr/local/bin/openshell, gateway, add, http://127.0.0.1:17670, --local, --name, tmachine]
XDG_RUNTIME_DIR: "/run/user/{{ tmachine_container_runtime_tmachine_uid.stdout }}"

- name: Run Podman E2E archive tests
ansible.builtin.command:
Expand All @@ -73,16 +78,16 @@
- --no-fail-fast
environment:
CONTAINER_ENGINE: podman
CONTAINER_HOST: unix:///run/user/1000/podman/podman.sock
CONTAINER_HOST: "unix://{{ tmachine_container_runtime_socket }}"
HOME: /home/tmachine
OPENSHELL_BIN: /usr/local/bin/openshell
OPENSHELL_BIN: "{{ openshell_test_cli.stdout }}"
OPENSHELL_E2E_CONTAINER_ENGINE_UNSET_XDG_CONFIG_HOME: "1"
OPENSHELL_E2E_DRIVER: podman
OPENSHELL_E2E_NETWORK_NAME: tmachine
OPENSHELL_E2E_NETWORK_NAME: "{{ openshell_test_gateway.network_name }}"
OPENSHELL_E2E_SANDBOX_NAMESPACE: tmachine
OPENSHELL_GATEWAY: tmachine
OPENSHELL_PODMAN_SOCKET: /run/user/1000/podman/podman.sock
XDG_RUNTIME_DIR: /run/user/1000
OPENSHELL_GATEWAY: "{{ openshell_test_gateway.name }}"
OPENSHELL_PODMAN_SOCKET: "{{ tmachine_container_runtime_socket }}"
XDG_RUNTIME_DIR: "/run/user/{{ tmachine_container_runtime_tmachine_uid.stdout }}"
register: podman_e2e_test_result
changed_when: false
failed_when: false
Expand All @@ -95,18 +100,10 @@
ansible.builtin.debug:
var: podman_e2e_test_result.stdout_lines

- name: Capture OpenShell gateway journal after Podman E2E test failure
become: true
ansible.builtin.command:
argv: [journalctl, --unit, openshell-gateway.service, --no-pager, --lines, "200"]
changed_when: false
failed_when: false
when: podman_e2e_test_result.rc != 0
register: podman_e2e_gateway_journal

- name: Show OpenShell gateway journal after Podman E2E test failure
ansible.builtin.debug:
var: podman_e2e_gateway_journal.stdout_lines
- name: Collect installed gateway diagnostics after test failure
ansible.builtin.include_role:
name: openshell_test_gateway
tasks_from: journal.yaml
when: podman_e2e_test_result.rc != 0

- name: Require Podman E2E archive success
Expand Down
39 changes: 10 additions & 29 deletions tests/ansible/playbooks/drivers/podman/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
- name: Wait for SSH
ansible.builtin.wait_for_connection:

- name: Resolve installed gateway context
ansible.builtin.include_role:
name: openshell_test_gateway

- name: Detect tmachine container runtime
ansible.builtin.include_role:
name: tmachine_container_runtime
Expand Down Expand Up @@ -39,21 +43,12 @@
owner: tmachine
group: tmachine

- name: Remove any previous OpenShell gateway registration
ansible.builtin.command:
argv: [/usr/local/bin/openshell, gateway, remove, tmachine]
changed_when: false
failed_when: false

- name: Register the configured OpenShell gateway
ansible.builtin.command:
argv: [/usr/local/bin/openshell, gateway, add, http://127.0.0.1:17670, --local, --name, tmachine]

- name: Run Podman archive tests
ansible.builtin.command:
argv: [cargo-nextest, nextest, run, --archive-file, "{{ podman_test_root }}/tests.tar.zst", --workspace-remap, "{{ podman_test_root }}", --no-capture]
environment:
OPENSHELL_BIN: /usr/local/bin/openshell
OPENSHELL_GATEWAY: "{{ openshell_test_gateway.name }}"
OPENSHELL_BIN: "{{ openshell_test_cli.stdout }}"
OPENSHELL_TEST_INPUT_DIR: "{{ podman_test_input_dir }}"
OPENSHELL_PODMAN_TEST_IMAGE: "{{ openshell_podman_test_image | default('') }}"
register: podman_test_result
Expand All @@ -68,24 +63,10 @@
ansible.builtin.debug:
var: podman_test_result.stdout_lines

- name: Capture OpenShell gateway journal after Podman test failure
become: true
ansible.builtin.command:
argv:
- journalctl
- --unit
- openshell-gateway.service
- --no-pager
- --lines
- "200"
changed_when: false
failed_when: false
when: podman_test_result.rc != 0
register: podman_gateway_journal

- name: Show OpenShell gateway journal after Podman test failure
ansible.builtin.debug:
var: podman_gateway_journal.stdout_lines
- name: Collect installed gateway diagnostics after test failure
ansible.builtin.include_role:
name: openshell_test_gateway
tasks_from: journal.yaml
when: podman_test_result.rc != 0

- name: Discover Podman containers after test failure
Expand Down
22 changes: 10 additions & 12 deletions tests/ansible/playbooks/drivers/podman/userns-profile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
- name: Wait for SSH
ansible.builtin.wait_for_connection:

- name: Resolve installed gateway context
ansible.builtin.include_role:
name: openshell_test_gateway

- name: Detect tmachine container runtime
ansible.builtin.include_role:
name: tmachine_container_runtime
Expand All @@ -38,21 +42,15 @@
- name: Apply the Podman user-namespace fixture
become: true
ansible.builtin.blockinfile:
path: /etc/openshell/gateway.toml
path: "{{ openshell_test_gateway.config_path }}"
insertafter: '^\[openshell\.drivers\.podman\]$'
marker: "# {mark} OpenShell Podman userns test fixture"
block: "{{ lookup('ansible.builtin.file', podman_userns_config) | trim }}"

- name: Restart OpenShell gateway with the Podman user-namespace fixture
become: true
ansible.builtin.systemd_service:
name: openshell-gateway.service
state: restarted

- name: Wait for the configured OpenShell gateway
ansible.builtin.wait_for:
host: 127.0.0.1
port: 17670
timeout: 60
- name: Restart installed gateway with the Podman user-namespace fixture
ansible.builtin.include_role:
name: openshell_test_gateway
tasks_from: restart.yaml

- name: Capture direct Podman user-namespace mapping
become: true
Expand Down
14 changes: 14 additions & 0 deletions tests/ansible/roles/openshell_client/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,17 @@
- --local
- --name
- "{{ openshell_client_gateway_name | default('tmachine') }}"

- name: Publish test gateway context
ansible.builtin.include_role:
name: openshell_test_gateway
tasks_from: publish.yaml
vars:
openshell_test_gateway_context:
name: "{{ openshell_client_gateway_name | default('tmachine') }}"
config_path: "{{ openshell_client_gateway_config_path | default('/etc/openshell/gateway.toml') }}"
service_scope: "{{ openshell_client_gateway_service_scope | default('system') }}"
service_user: "{{ openshell_gateway_user if openshell_client_gateway_service_scope | default('system') == 'user' else 'root' }}"
service_home: "{{ openshell_gateway_home if openshell_client_gateway_service_scope | default('system') == 'user' else '/root' }}"
service_uid: "{{ openshell_gateway_uid if openshell_client_gateway_service_scope | default('system') == 'user' else '0' }}"
network_name: "{{ openshell_client_gateway_network_name | default('tmachine') }}"
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,6 @@
vars:
openshell_client_gateway_endpoint: https://127.0.0.1:17670
openshell_client_gateway_name: openshell
openshell_client_gateway_config_path: /var/lib/openshell-qualification/gateway.toml
openshell_client_gateway_service_scope: user
openshell_client_gateway_network_name: openshell
22 changes: 22 additions & 0 deletions tests/ansible/roles/openshell_test_gateway/tasks/journal.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

---
# Root's packaged user unit can log to the system journal. Match journal
# fields instead of --user so both root and tmachine user units are captured.
- name: Capture installed gateway journal
become: true
ansible.builtin.command:
argv: >-
{{ ['journalctl']
+ (['_SYSTEMD_USER_UNIT=openshell-gateway.service', '_UID=' ~ openshell_test_gateway.service_uid]
if openshell_test_gateway.service_scope == 'user'
else ['--unit', 'openshell-gateway.service'])
+ ['--no-pager', '--lines', '200'] }}
register: openshell_test_gateway_journal
changed_when: false
failed_when: false

- name: Show installed gateway journal
ansible.builtin.debug:
var: openshell_test_gateway_journal.stdout_lines
42 changes: 42 additions & 0 deletions tests/ansible/roles/openshell_test_gateway/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

---
- name: Read installed gateway context
ansible.builtin.slurp:
src: /var/lib/openshell-test/gateway.yaml
register: openshell_test_gateway_metadata

- name: Load installed gateway context
ansible.builtin.set_fact:
openshell_test_gateway: "{{ (openshell_test_gateway_metadata.content | b64decode | from_yaml).openshell_test_gateway }}"

- name: Validate installed gateway context
ansible.builtin.assert:
that:
- openshell_test_gateway.service_scope in ['system', 'user']
- openshell_test_gateway.config_path is match('^/')
- openshell_test_gateway.name | length > 0

- name: Resolve installed OpenShell CLI from PATH
ansible.builtin.command:
argv: [/bin/sh, -c, command -v openshell]
register: openshell_test_cli
changed_when: false

- name: Check active gateway configuration
become: true
ansible.builtin.stat:
path: "{{ openshell_test_gateway.config_path }}"
register: openshell_test_gateway_config

- name: Require active gateway configuration
ansible.builtin.assert:
that: [openshell_test_gateway_config.stat.isreg | default(false)]

- name: Resolve gateway service environment
ansible.builtin.set_fact:
openshell_test_gateway_service_environment:
HOME: "{{ openshell_test_gateway.service_home }}"
XDG_RUNTIME_DIR: "/run/user/{{ openshell_test_gateway.service_uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ openshell_test_gateway.service_uid }}/bus"
23 changes: 23 additions & 0 deletions tests/ansible/roles/openshell_test_gateway/tasks/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

---
# Installation and suite execution are separate Ansible processes. Persist only
# non-secret metadata; the CLI keeps registration and mTLS credentials itself.
- name: Create test gateway metadata directory
become: true
ansible.builtin.file:
path: /var/lib/openshell-test
state: directory
owner: root
group: root
mode: "0755"

- name: Publish installed gateway context
become: true
ansible.builtin.copy:
dest: /var/lib/openshell-test/gateway.yaml
owner: root
group: root
mode: "0644"
content: "{{ {'openshell_test_gateway': openshell_test_gateway_context} | to_nice_yaml }}"
Loading
Loading