diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 775eb9f83e..757609a456 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -178,6 +178,6 @@ jobs: --copy conformance-input/openshell-conformance:/tmp/openshell-conformance \ --copy nix/test-guest/conformance-plans/gateway-upgrade-restart.toml:/tmp/conformance-plan.toml \ --provision openshell-rpm-latest-release \ - --provision gateway-rootless-podman \ + --provision gateway-podman \ --provision openshell-rpm-gateway-upgrade \ -- /tmp/openshell-conformance run --plan /tmp/conformance-plan.toml diff --git a/nix/test-guest/README.md b/nix/test-guest/README.md index 1865f9a82f..58cf771679 100644 --- a/nix/test-guest/README.md +++ b/nix/test-guest/README.md @@ -40,6 +40,7 @@ nix/test-guest/ │ └── rocky.nix └── configuration/ ├── docker.yml + ├── podman-rootful.yml ├── podman-rootless.yml ├── tasks/ │ ├── podman-common.yml @@ -50,7 +51,7 @@ nix/test-guest/ └── selinux.yml └── provisioners/ └── roles/ - ├── gateway-rootless-podman/ + ├── gateway-podman/ ├── openshell-development/ ├── openshell-rpm/ └── openshell-rpm-gateway-upgrade/ @@ -70,13 +71,13 @@ The root [`flake.nix`](../../flake.nix) exposes this directory as the `test-gues ## Supported configurations -| Distro | Docker | Rootless Podman | SELinux | Package format | -| --- | --- | --- | --- | --- | -| Ubuntu 24.04 | Yes | No | No | `.deb` | -| Ubuntu 26.04 | Yes | Yes | No | `.deb` | -| CentOS Stream 10 | No | No | Yes | `.rpm` | -| Fedora 44 | No | Yes | Yes | `.rpm` | -| Rocky Linux 9 | Yes | No | Yes | `.rpm` | +| Distro | Docker | Rootful Podman | Rootless Podman | SELinux | Package format | +| --- | --- | --- | --- | --- | --- | +| Ubuntu 24.04 | Yes | Yes | No | No | `.deb` | +| Ubuntu 26.04 | Yes | Yes | Yes | No | `.deb` | +| CentOS Stream 10 | No | Yes | No | Yes | `.rpm` | +| Fedora 44 | No | Yes | Yes | Yes | `.rpm` | +| Rocky Linux 9 | Yes | Yes | No | Yes | `.rpm` | The `snapd` configuration is available for Ubuntu and prepares snapd for local Snap lifecycle experiments. It does not install Docker, because the Snap @@ -91,6 +92,13 @@ Both configurations verify rootless mode and the `pasta` network helper required by OpenShell sandbox callbacks. Ubuntu 24.04 ships Podman 4, which does not provide that helper. +`podman-rootful` installs Podman, enables its system API socket, and records +the selected mode for the `gateway-podman` provisioner. The provisioner then +starts the selected OpenShell installation as root. It does not write a +rootful-specific gateway setting; the gateway discovers the Podman socket +available to its service account. The rootless configuration records its mode +the same way and runs the gateway as the `openshell` user. + List the available distros and configurations: ```shell @@ -115,6 +123,7 @@ Other combinations use the same interface: ```shell nix run .#test-guest -- --distro rocky --with docker +nix run .#test-guest -- --distro fedora --with podman-rootful nix run .#test-guest -- --distro ubuntu-26-04 --with podman-rootless nix run .#test-guest -- --distro fedora --with podman-rootless ``` @@ -189,8 +198,11 @@ EOF - `/usr/local/bin/openshell-gateway` - `/usr/local/lib/openshell-sandbox.tar` -Compose it with `gateway-rootless-podman` to configure a rootless Podman -gateway. For example, run conformance after the provisioners complete: +Compose it with `gateway-podman` after either Podman configuration. The role +uses the recorded mode to select the corresponding service account. It +generates configuration only for development artifacts; RPM installations +retain their packaged service and first-start configuration. For example, run +conformance after the rootless provisioners complete: ```shell nix run .#test-guest -- \ @@ -200,7 +212,7 @@ nix run .#test-guest -- \ --copy ./openshell-gateway:/usr/local/bin/openshell-gateway \ --copy ./openshell-sandbox.tar:/usr/local/lib/openshell-sandbox.tar \ --provision openshell-development \ - --provision gateway-rootless-podman \ + --provision gateway-podman \ -- /usr/local/bin/openshell-conformance run --plan - <<'EOF' version = 1 @@ -218,13 +230,14 @@ EOF `openshell-rpm` expects OpenShell to have been installed with `--install`. It uses the RPM-owned `/usr/bin` binaries and `openshell-gateway` user service, without copied development artifacts or a supervisor archive. Compose it with -`gateway-rootless-podman` before an RPM action such as +`gateway-podman` to start the installed version. The existing upgrade flow uses +the same role with the rootless configuration before `openshell-rpm-gateway-upgrade`. `openshell-rpm-latest-release` downloads and installs the latest stable OpenShell GitHub release for the guest architecture, then publishes the same -RPM installation contract. Compose it with `gateway-rootless-podman` and an -RPM gateway action when testing an upgrade from the current release. +RPM installation contract. Compose it with `gateway-podman` and an RPM gateway +action when testing an upgrade from the current release. Versioned plans under `nix/test-guest/conformance-plans/` bind conformance scenarios to the stable action-command contracts installed by provisioners. @@ -284,7 +297,7 @@ Cache command options: ```text --distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky ---with NAME Apply docker, podman-rootless, selinux, or snapd; repeatable +--with NAME Apply docker, podman-rootful, podman-rootless, selinux, or snapd; repeatable --repository REF OCI repository without a tag --digest DIGEST Trusted OCI manifest digest required for pulls --cache-dir PATH Override the local prepared-disk cache directory @@ -361,7 +374,7 @@ from `000` through `777` for explicit modes. ```text --distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky ---with NAME Apply docker, podman-rootless, selinux, or snapd; repeatable +--with NAME Apply docker, podman-rootful, podman-rootless, selinux, or snapd; repeatable --install PATH Install a .deb or .rpm package; repeatable --copy SRC:DEST[:MODE] Copy a regular file into the guest; use MODE when provided, diff --git a/nix/test-guest/cache.sh b/nix/test-guest/cache.sh index f29a9b3492..54b09a058b 100644 --- a/nix/test-guest/cache.sh +++ b/nix/test-guest/cache.sh @@ -13,7 +13,7 @@ Usage: Options: --distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky - --with NAME Apply a configuration; repeatable (docker, podman-rootless, selinux, snapd) + --with NAME Apply a configuration; repeatable (docker, podman-rootful, podman-rootless, selinux, snapd) --repository REF OCI repository without a tag --digest DIGEST Trusted OCI manifest digest required for pulls --cache-dir PATH Override the local prepared-disk cache directory @@ -380,7 +380,8 @@ build_local() { for configuration in "${configurations[@]}"; do case "${configuration}" in docker) validation+='; docker info >/dev/null' ;; - podman-rootless) validation+='; podman info >/dev/null' ;; + podman-rootful) validation+='; sudo podman --url unix:///run/podman/podman.sock info >/dev/null; test "$(cat /etc/openshell-test-guest/podman-mode)" = rootful' ;; + podman-rootless) validation+='; podman info >/dev/null; test "$(cat /etc/openshell-test-guest/podman-mode)" = rootless' ;; selinux) validation+='; test "$(getenforce)" = Enforcing' ;; esac done diff --git a/nix/test-guest/configuration/podman-rootful.yml b/nix/test-guest/configuration/podman-rootful.yml new file mode 100644 index 0000000000..1fd0be24d3 --- /dev/null +++ b/nix/test-guest/configuration/podman-rootful.yml @@ -0,0 +1,36 @@ +--- +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- name: Configure rootful Podman + hosts: test_vm + become: true + gather_facts: true + tasks: + - name: Install common Podman prerequisites + ansible.builtin.import_tasks: tasks/podman-common.yml + + - name: Enable the rootful Podman API socket + ansible.builtin.systemd_service: + name: podman.socket + enabled: true + state: started + + - name: Verify rootful Podman mode + ansible.builtin.command: + argv: + - podman + - --url + - unix:///run/podman/podman.sock + - info + - --format + - "{% raw %}{{.Host.Security.Rootless}}{% endraw %}" + changed_when: false + register: podman_rootful_info + failed_when: podman_rootful_info.stdout != "false" + + - name: Record rootful Podman mode + ansible.builtin.copy: + dest: /etc/openshell-test-guest/podman-mode + content: "rootful\n" + mode: "0644" diff --git a/nix/test-guest/configuration/podman-rootless.yml b/nix/test-guest/configuration/podman-rootless.yml index 23fef05e5e..f9e0cf493b 100644 --- a/nix/test-guest/configuration/podman-rootless.yml +++ b/nix/test-guest/configuration/podman-rootless.yml @@ -34,3 +34,9 @@ - name: Configure shared rootless Podman settings ansible.builtin.import_tasks: tasks/podman-rootless/shared.yml + + - name: Record rootless Podman mode + ansible.builtin.copy: + dest: /etc/openshell-test-guest/podman-mode + content: "rootless\n" + mode: "0644" diff --git a/nix/test-guest/configuration/tasks/podman-common.yml b/nix/test-guest/configuration/tasks/podman-common.yml index 18a0f1304a..b5385daac8 100644 --- a/nix/test-guest/configuration/tasks/podman-common.yml +++ b/nix/test-guest/configuration/tasks/podman-common.yml @@ -11,3 +11,9 @@ ansible.builtin.package: name: podman state: present + +- name: Create test-guest state directory + ansible.builtin.file: + path: /etc/openshell-test-guest + state: directory + mode: "0755" diff --git a/nix/test-guest/default.nix b/nix/test-guest/default.nix index e3b19a5d83..8129198d7f 100644 --- a/nix/test-guest/default.nix +++ b/nix/test-guest/default.nix @@ -27,6 +27,7 @@ let configurations = { docker = ./configuration/docker.yml; + podman-rootful = ./configuration/podman-rootful.yml; podman-rootless = ./configuration/podman-rootless.yml; selinux = ./configuration/selinux.yml; snapd = ./configuration/snapd.yml; @@ -43,7 +44,7 @@ let "openshell-development" "openshell-rpm" "openshell-rpm-latest-release" - "gateway-rootless-podman" + "gateway-podman" "openshell-rpm-gateway-reinstall" "openshell-rpm-gateway-upgrade" ]; diff --git a/nix/test-guest/provisioners/roles/gateway-rootless-podman/defaults/main.yml b/nix/test-guest/provisioners/roles/gateway-podman/defaults/main.yml similarity index 77% rename from nix/test-guest/provisioners/roles/gateway-rootless-podman/defaults/main.yml rename to nix/test-guest/provisioners/roles/gateway-podman/defaults/main.yml index 3a50abfba1..ce0ec961dc 100644 --- a/nix/test-guest/provisioners/roles/gateway-rootless-podman/defaults/main.yml +++ b/nix/test-guest/provisioners/roles/gateway-podman/defaults/main.yml @@ -2,5 +2,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +openshell_gateway_service_command: /home/openshell/.local/bin/openshell-test-guest-as-gateway-user openshell_gateway_restart_command: /home/openshell/.local/bin/openshell-test-guest-gateway-restart openshell_gateway_diagnostics_command: /home/openshell/.local/bin/openshell-test-guest-diagnostics diff --git a/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/development-gateway.yml b/nix/test-guest/provisioners/roles/gateway-podman/tasks/development-gateway.yml similarity index 72% rename from nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/development-gateway.yml rename to nix/test-guest/provisioners/roles/gateway-podman/tasks/development-gateway.yml index 4c89402dda..27d9547559 100644 --- a/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/development-gateway.yml +++ b/nix/test-guest/provisioners/roles/gateway-podman/tasks/development-gateway.yml @@ -2,28 +2,40 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -- name: Create development gateway state directories +- name: Publish development gateway paths + ansible.builtin.set_fact: + openshell_gateway_state_root: "{{ openshell_gateway_service_home }}/.local/share/openshell-test-guest" + openshell_gateway_config_home: "{{ openshell_gateway_service_home }}/.config" + +- name: Create development gateway directories ansible.builtin.file: path: "{{ item }}" state: directory mode: "0700" + owner: "{{ openshell_gateway_service_user }}" + group: "{{ openshell_gateway_service_user }}" loop: - "{{ openshell_gateway_state_root }}" - "{{ openshell_gateway_state_root }}/xdg/config" - "{{ openshell_gateway_state_root }}/xdg/cache" - "{{ openshell_gateway_state_root }}/xdg/data" - "{{ openshell_gateway_state_root }}/xdg/state" - - /home/openshell/.config/systemd/user + - "{{ openshell_gateway_config_home }}/systemd/user" + become: true -- name: Generate development gateway certificates +- name: Generate development gateway credentials ansible.builtin.command: cmd: "{{ openshell_gateway_bin }} generate-certs --output-dir {{ openshell_gateway_state_root }}/pki" creates: "{{ openshell_gateway_state_root }}/pki/jwt/signing.pem" + become: true + become_user: "{{ openshell_gateway_service_user }}" -- name: Write rootless Podman gateway configuration +- name: Write development Podman gateway configuration ansible.builtin.copy: dest: "{{ openshell_gateway_state_root }}/gateway.toml" mode: "0600" + owner: "{{ openshell_gateway_service_user }}" + group: "{{ openshell_gateway_service_user }}" content: | [openshell] version = 1 @@ -50,6 +62,7 @@ image_pull_policy = "always" network_name = "openshell-test-guest" grpc_endpoint = "http://host.containers.internal:8080" + become: true - name: Check for the development supervisor image ansible.builtin.command: @@ -57,6 +70,8 @@ register: openshell_supervisor_image_exists changed_when: false failed_when: false + become: true + become_user: "{{ openshell_gateway_service_user }}" - name: Import the development supervisor image ansible.builtin.command: @@ -64,11 +79,15 @@ podman import --change 'ENTRYPOINT ["/openshell-sandbox"]' {{ openshell_supervisor_archive }} {{ openshell_supervisor_image }} when: openshell_supervisor_image_exists.rc != 0 + become: true + become_user: "{{ openshell_gateway_service_user }}" - name: Install the development gateway user service ansible.builtin.copy: - dest: "/home/openshell/.config/systemd/user/{{ openshell_gateway_service }}" + dest: "{{ openshell_gateway_config_home }}/systemd/user/{{ openshell_gateway_service }}" mode: "0600" + owner: "{{ openshell_gateway_service_user }}" + group: "{{ openshell_gateway_service_user }}" content: | [Unit] Description=OpenShell development test guest gateway @@ -84,3 +103,4 @@ [Install] WantedBy=default.target + become: true diff --git a/nix/test-guest/provisioners/roles/gateway-podman/tasks/lifecycle.yml b/nix/test-guest/provisioners/roles/gateway-podman/tasks/lifecycle.yml new file mode 100644 index 0000000000..ccd6615ff1 --- /dev/null +++ b/nix/test-guest/provisioners/roles/gateway-podman/tasks/lifecycle.yml @@ -0,0 +1,135 @@ +--- +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- name: Publish gateway user-manager environment + ansible.builtin.set_fact: + openshell_gateway_user_environment: + HOME: "{{ openshell_gateway_service_home }}" + XDG_RUNTIME_DIR: "/run/user/{{ openshell_gateway_service_uid }}" + DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ openshell_gateway_service_uid }}/bus" + +- name: Reload gateway user services + ansible.builtin.systemd_service: + daemon_reload: true + scope: user + environment: "{{ openshell_gateway_user_environment }}" + become: true + become_user: "{{ openshell_gateway_service_user }}" + +- name: Start the gateway user service + ansible.builtin.systemd_service: + name: "{{ openshell_gateway_service }}" + enabled: true + state: started + scope: user + environment: "{{ openshell_gateway_user_environment }}" + become: true + become_user: "{{ openshell_gateway_service_user }}" + +- name: Register the provisioned gateway with its service account + ansible.builtin.command: + cmd: "{{ openshell_cli_bin }} gateway add {{ openshell_gateway_endpoint }} --local --name test-guest" + environment: "{{ openshell_gateway_user_environment }}" + become: true + become_user: "{{ openshell_gateway_service_user }}" + +- name: Wait for gateway CLI health + ansible.builtin.command: + cmd: "{{ openshell_cli_bin }} status" + environment: "{{ openshell_gateway_user_environment }}" + become: true + become_user: "{{ openshell_gateway_service_user }}" + register: gateway_health + changed_when: false + retries: 60 + delay: 1 + until: gateway_health.rc == 0 + ignore_errors: true + +- name: Collect failed gateway service status + ansible.builtin.command: + cmd: "systemctl --user status {{ openshell_gateway_service }} --no-pager" + environment: "{{ openshell_gateway_user_environment }}" + become: true + become_user: "{{ openshell_gateway_service_user }}" + register: gateway_service_status + changed_when: false + failed_when: false + when: gateway_health is failed + +- name: Collect failed gateway service journal + ansible.builtin.command: + cmd: "journalctl --user -u {{ openshell_gateway_service }} --no-pager -n 200" + environment: "{{ openshell_gateway_user_environment }}" + become: true + become_user: "{{ openshell_gateway_service_user }}" + register: gateway_service_journal + changed_when: false + failed_when: false + when: gateway_health is failed + +- name: Report failed gateway service diagnostics + ansible.builtin.debug: + msg: | + {{ gateway_service_status.stdout }} + {{ gateway_service_journal.stdout }} + when: gateway_health is failed + +- name: Require gateway CLI health + ansible.builtin.assert: + that: gateway_health is not failed + fail_msg: The provisioned gateway did not become healthy. + +- name: Create the target gateway-control command directory + ansible.builtin.file: + path: "{{ openshell_gateway_restart_command | dirname }}" + state: directory + mode: "0700" + +- name: Install the gateway service-account command wrapper + ansible.builtin.copy: + dest: "{{ openshell_gateway_service_command }}" + mode: "0700" + content: | + #!/usr/bin/env bash + set -Eeuo pipefail + exec sudo -H -u {{ openshell_gateway_service_user }} env \ + HOME={{ openshell_gateway_service_home }} \ + XDG_RUNTIME_DIR=/run/user/{{ openshell_gateway_service_uid }} \ + DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/{{ openshell_gateway_service_uid }}/bus \ + "$@" + +- name: Install the target gateway restart command + ansible.builtin.copy: + dest: "{{ openshell_gateway_restart_command }}" + mode: "0700" + content: | + #!/usr/bin/env bash + set -Eeuo pipefail + gateway_user_command={{ openshell_gateway_service_command | quote }} + "${gateway_user_command}" systemctl --user restart {{ openshell_gateway_service }} + for _ in $(seq 1 60); do + if "${gateway_user_command}" {{ openshell_cli_bin }} status >/dev/null 2>&1; then + exit 0 + fi + sleep 1 + done + "${gateway_user_command}" systemctl --user status {{ openshell_gateway_service }} --no-pager >&2 || true + exit 1 + +- name: Install the target gateway diagnostics command + ansible.builtin.copy: + dest: "{{ openshell_gateway_diagnostics_command }}" + mode: "0700" + content: | + #!/usr/bin/env bash + set -u + gateway_user_command={{ openshell_gateway_service_command | quote }} + "${gateway_user_command}" systemctl --user status {{ openshell_gateway_service }} --no-pager || true + "${gateway_user_command}" journalctl --user -u {{ openshell_gateway_service }} --no-pager -n 200 || true + "${gateway_user_command}" podman info || true + "${gateway_user_command}" podman ps --all || true + if command -v getenforce >/dev/null 2>&1; then + getenforce || true + fi diff --git a/nix/test-guest/provisioners/roles/gateway-podman/tasks/main.yml b/nix/test-guest/provisioners/roles/gateway-podman/tasks/main.yml new file mode 100644 index 0000000000..6c04e08733 --- /dev/null +++ b/nix/test-guest/provisioners/roles/gateway-podman/tasks/main.yml @@ -0,0 +1,71 @@ +--- +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- name: Read the configured Podman mode + ansible.builtin.command: + argv: + - cat + - /etc/openshell-test-guest/podman-mode + register: openshell_podman_mode_command + changed_when: false + +- name: Publish the configured Podman mode + ansible.builtin.set_fact: + openshell_podman_mode: "{{ openshell_podman_mode_command.stdout | trim }}" + +- name: Require an OpenShell installation + ansible.builtin.assert: + that: + - openshell_install_source is defined + - openshell_cli_bin is defined + - openshell_gateway_bin is defined + - openshell_gateway_service is defined + - openshell_gateway_endpoint is defined + - openshell_install_source in ['development', 'rpm'] + - openshell_podman_mode in ['rootless', 'rootful'] + fail_msg: >- + gateway-podman requires an earlier OpenShell installation role and a + podman-rootless or podman-rootful test-guest configuration. + +- name: Select the Podman service account + ansible.builtin.set_fact: + openshell_podman_service_user: >- + {{ 'root' if openshell_podman_mode == 'rootful' else 'openshell' }} + +- name: Resolve the gateway service account + ansible.builtin.getent: + database: passwd + key: "{{ openshell_podman_service_user }}" + +- name: Publish the gateway service account + ansible.builtin.set_fact: + openshell_gateway_service_user: "{{ openshell_podman_service_user }}" + openshell_gateway_service_uid: "{{ ansible_facts.getent_passwd[openshell_podman_service_user][1] }}" + openshell_gateway_service_home: "{{ ansible_facts.getent_passwd[openshell_podman_service_user][4] }}" + +- name: Configure a development gateway + ansible.builtin.include_tasks: development-gateway.yml + when: openshell_install_source == 'development' + +- name: Enable the gateway service account user manager + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - "{{ openshell_gateway_service_user }}" + become: true + changed_when: false + +- name: Start the gateway service account user manager + ansible.builtin.systemd_service: + name: "user@{{ openshell_gateway_service_uid }}.service" + state: started + become: true + +- name: Run the gateway lifecycle + ansible.builtin.include_tasks: lifecycle.yml + +- name: Publish Podman gateway runtime + ansible.builtin.set_fact: + openshell_gateway_runtime: "{{ openshell_podman_mode }}-podman" diff --git a/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/lifecycle.yml b/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/lifecycle.yml deleted file mode 100644 index b90e66f26b..0000000000 --- a/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/lifecycle.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -- name: Reload gateway user services - ansible.builtin.systemd_service: - daemon_reload: true - scope: user - -- name: Start the gateway user service - ansible.builtin.systemd_service: - name: "{{ openshell_gateway_service }}" - enabled: true - state: started - scope: user - -- name: Register the provisioned gateway with the CLI - ansible.builtin.command: - cmd: "{{ openshell_cli_bin }} gateway add {{ openshell_gateway_endpoint }} --local --name test-guest" - -- name: Wait for gateway CLI health - ansible.builtin.command: - cmd: "{{ openshell_cli_bin }} status" - register: gateway_health - changed_when: false - retries: 60 - delay: 1 - until: gateway_health.rc == 0 - -- name: Create the target gateway-control command directory - ansible.builtin.file: - path: "{{ openshell_gateway_restart_command | dirname }}" - state: directory - mode: "0700" - -- name: Install the target gateway restart command - ansible.builtin.copy: - dest: "{{ openshell_gateway_restart_command }}" - mode: "0700" - content: | - #!/usr/bin/env bash - set -Eeuo pipefail - systemctl --user restart {{ openshell_gateway_service }} - for _ in $(seq 1 60); do - if {{ openshell_cli_bin }} status >/dev/null 2>&1; then - exit 0 - fi - sleep 1 - done - systemctl --user status {{ openshell_gateway_service }} --no-pager >&2 || true - exit 1 - -- name: Install the target gateway diagnostics command - ansible.builtin.copy: - dest: "{{ openshell_gateway_diagnostics_command }}" - mode: "0700" - content: | - #!/usr/bin/env bash - set -u - systemctl --user status {{ openshell_gateway_service }} --no-pager || true - journalctl --user -u {{ openshell_gateway_service }} --no-pager -n 200 || true - podman info || true - podman ps --all || true - if command -v getenforce >/dev/null 2>&1; then - getenforce || true - fi diff --git a/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/main.yml b/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/main.yml deleted file mode 100644 index 5a23e28406..0000000000 --- a/nix/test-guest/provisioners/roles/gateway-rootless-podman/tasks/main.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -- name: Require an OpenShell installation - ansible.builtin.assert: - that: - - openshell_install_source is defined - - openshell_cli_bin is defined - - openshell_gateway_bin is defined - - openshell_gateway_service is defined - - openshell_gateway_endpoint is defined - fail_msg: >- - gateway-rootless-podman requires an earlier OpenShell source provisioner, - such as openshell-development or openshell-rpm. - -- name: Configure development gateway for rootless Podman - ansible.builtin.include_tasks: development-gateway.yml - when: openshell_install_source == 'development' - -- ansible.builtin.import_tasks: lifecycle.yml - -- name: Publish rootless Podman gateway runtime - ansible.builtin.set_fact: - openshell_gateway_runtime: rootless-podman diff --git a/nix/test-guest/provisioners/roles/openshell-development/defaults/main.yml b/nix/test-guest/provisioners/roles/openshell-development/defaults/main.yml index 8c2eb312cf..2aae28bbe8 100644 --- a/nix/test-guest/provisioners/roles/openshell-development/defaults/main.yml +++ b/nix/test-guest/provisioners/roles/openshell-development/defaults/main.yml @@ -7,5 +7,4 @@ openshell_development_gateway_bin: /usr/local/bin/openshell-gateway openshell_development_sandbox_archive: /usr/local/lib/openshell-sandbox.tar openshell_development_gateway_service: openshell-test-guest-gateway.service openshell_development_gateway_endpoint: http://127.0.0.1:8080 -openshell_development_state_root: /home/openshell/.local/share/openshell-test-guest openshell_development_supervisor_image: localhost/openshell/supervisor:test-guest diff --git a/nix/test-guest/provisioners/roles/openshell-development/tasks/main.yml b/nix/test-guest/provisioners/roles/openshell-development/tasks/main.yml index 902646116a..dee9747279 100644 --- a/nix/test-guest/provisioners/roles/openshell-development/tasks/main.yml +++ b/nix/test-guest/provisioners/roles/openshell-development/tasks/main.yml @@ -26,7 +26,6 @@ openshell_gateway_bin: "{{ openshell_development_gateway_bin }}" openshell_gateway_service: "{{ openshell_development_gateway_service }}" openshell_gateway_endpoint: "{{ openshell_development_gateway_endpoint }}" - openshell_gateway_state_root: "{{ openshell_development_state_root }}" openshell_supervisor_source: archive openshell_supervisor_archive: "{{ openshell_development_sandbox_archive }}" openshell_supervisor_image: "{{ openshell_development_supervisor_image }}" diff --git a/nix/test-guest/run.sh b/nix/test-guest/run.sh index 282ba2c460..4e1d384b48 100644 --- a/nix/test-guest/run.sh +++ b/nix/test-guest/run.sh @@ -13,7 +13,7 @@ Usage: Options: --distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky - --with NAME Apply a configuration; repeatable (docker, podman-rootless, selinux, snapd) + --with NAME Apply a configuration; repeatable (docker, podman-rootful, podman-rootless, selinux, snapd) --provision NAME Apply a post-artifact system provisioner; repeatable --install PATH Install a .deb or .rpm package; repeatable --copy SRC:DEST[:MODE] @@ -177,12 +177,23 @@ fi # shellcheck disable=SC1090 . "${OPENSHELL_TEST_GUEST_DISTROS}/${distro}" - for item in "${configurations[@]}"; do - if [[ ! ${item} =~ ^[a-z0-9][a-z0-9-]*$ ]] || +podman_mode= +for item in "${configurations[@]}"; do + if [[ ! ${item} =~ ^[a-z0-9][a-z0-9-]*$ ]] || [ ! -f "${OPENSHELL_TEST_GUEST_CONFIGURATIONS}/${item}" ]; then echo "unknown configuration: ${item:-}" >&2 exit 2 fi + case "${item}" in + podman-rootful | podman-rootless) + item_podman_mode=${item#podman-} + if [ -n "${podman_mode}" ] && [ "${podman_mode}" != "${item_podman_mode}" ]; then + echo "podman-rootful and podman-rootless configurations are mutually exclusive" >&2 + exit 2 + fi + podman_mode=${item_podman_mode} + ;; + esac done for item in "${provisions[@]}"; do if [[ ! ${item} =~ ^[a-z0-9][a-z0-9-]*$ ]] || @@ -190,6 +201,10 @@ for item in "${provisions[@]}"; do echo "unknown provisioner: ${item:-}" >&2 exit 2 fi + if [ "${item}" = gateway-podman ] && [ -z "${podman_mode}" ]; then + echo "gateway-podman requires --with podman-rootful or --with podman-rootless" >&2 + exit 2 + fi done if [ -n "${requested_ssh_port}" ] && {