Skip to content
Draft
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
11 changes: 5 additions & 6 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,10 @@ jobs:
--distro fedora \
--with podman-rootless \
--with selinux \
--copy "${candidate_cli_package[0]}:/var/lib/openshell-conformance/candidate/openshell.rpm" \
--copy "${candidate_gateway_package[0]}:/var/lib/openshell-conformance/candidate/openshell-gateway.rpm" \
--copy "${candidate_cli_package[0]}:/var/lib/openshell-test-guest/artifacts/openshell.rpm" \
--copy "${candidate_gateway_package[0]}:/var/lib/openshell-test-guest/artifacts/openshell-gateway.rpm" \
--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 openshell-rpm-gateway-upgrade \
--copy nix/test-guest/conformance-plans/gateway-restart.toml:/tmp/conformance-plan.toml \
--provision openshell-candidate-rpm-source \
--provision gateway-podman \
-- /tmp/openshell-conformance run --plan /tmp/conformance-plan.toml
92 changes: 60 additions & 32 deletions nix/test-guest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ nix/test-guest/
└── selinux.yml
└── provisioners/
└── roles/
├── gateway-rootless-podman/
├── openshell-development/
├── openshell-rpm/
└── openshell-rpm-gateway-upgrade/
├── gateway-podman/
├── openshell-candidate-binaries-source/
├── openshell-binaries-contract/
├── openshell-candidate-rpm-source/
├── openshell-rpm-contract/
├── openshell-latest-release-rpm-source/
└── openshell-rpm-source/
```

- `default.nix` assembles the guest and cache flake apps. It selects host architecture and acceleration, supplies the runtime tools, and exposes distro profiles and configuration playbooks as Nix-store catalogs.
Expand Down Expand Up @@ -144,18 +147,25 @@ nix run .#test-guest -- \

Configurations are Ansible playbooks stored under `nix/test-guest/configuration/`. Ansible runs on the host using the VM's ephemeral SSH key and loopback port. The guest does not install Ansible.

Configurations run in the order provided on the command line. OpenShell packages and copied files are installed after all configurations succeed.

`--install` packages and `--copy` files are applied by a dedicated per-run
Ansible playbook. `--copy` preserves each source file's ordinary permission
bits. They are not stored in prepared VM cache entries.
Configurations run in the order provided on the command line. Package and file
artifacts are applied after all configurations succeed. `--install` installs a
generic Debian or RPM package directly; `--copy` stages a file at a guest path
and preserves its ordinary permission bits. Neither is stored in prepared VM
cache entries.

## System provisioners

`--provision NAME` applies a target-specific system setup after packages and
`--provision NAME` applies target-specific system setup after packages and
copied artifacts are present. Unlike `--with`, provisioners are not cached.
They can therefore install and start an OpenShell system without coupling the
prepared guest image to a particular build or driver configuration.
Stage OpenShell artifacts with `--copy`, then use an ordered source installer
provisioner to make OpenShell available without coupling the prepared guest
image to a particular build or driver configuration.

OpenShell source provisioners run in command-line order. The first source
installs and publishes the initial OpenShell state; later sources only make
their packages and target-side apply commands available. This lets a scenario
prepare guest state before initial installation and gives lifecycle actions the
exact source artifacts they must install later.

Provisioners that support gateway continuity install a target-control command:

Expand All @@ -182,24 +192,27 @@ timeout_secs = 120
EOF
```

`openshell-development` expects these copied guest paths:
`openshell-candidate-binaries-source` makes staged raw candidate artifacts available.
When it is the first OpenShell source provisioner, it installs them into the
candidate binary OpenShell state. Stage these guest paths with `--copy`:

- `/usr/local/bin/openshell`
- `/usr/local/bin/openshell-gateway`
- `/usr/local/lib/openshell-sandbox.tar`
- `/var/lib/openshell-test-guest/artifacts/openshell`
- `/var/lib/openshell-test-guest/artifacts/openshell-gateway`
- `/var/lib/openshell-test-guest/artifacts/openshell-sandbox.tar`

Compose it with `gateway-rootless-podman` to configure a rootless Podman
gateway. For example, run conformance after the provisioners complete:
Compose the binary candidate source with `gateway-podman` to configure
a rootless Podman gateway. For example, run conformance after the provisioners
complete:

```shell
nix run .#test-guest -- \
--distro fedora --with podman-rootless --with selinux \
--copy ./openshell:/usr/local/bin/openshell \
--copy ./openshell:/var/lib/openshell-test-guest/artifacts/openshell \
--copy ./openshell-conformance:/usr/local/bin/openshell-conformance \
--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 \
--copy ./openshell-gateway:/var/lib/openshell-test-guest/artifacts/openshell-gateway \
--copy ./openshell-sandbox.tar:/var/lib/openshell-test-guest/artifacts/openshell-sandbox.tar \
--provision openshell-candidate-binaries-source \
--provision gateway-podman \
-- /usr/local/bin/openshell-conformance run --plan - <<'EOF'
version = 1

Expand All @@ -214,16 +227,31 @@ timeout_secs = 120
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
`openshell-rpm-gateway-upgrade`.
`openshell-candidate-rpm-source` makes staged candidate RPMs available and publishes a
target-side candidate apply command. Stage the CLI and gateway packages as
`/var/lib/openshell-test-guest/artifacts/openshell.rpm` and
`/var/lib/openshell-test-guest/artifacts/openshell-gateway.rpm`.

`openshell-latest-release-rpm-source` downloads the latest stable OpenShell GitHub
release for the guest architecture, stores its versioned RPMs under
`/var/lib/openshell-conformance/baseline`, and publishes a target-side
latest-release apply command.

For gateway restart continuity, provision the candidate source first so it
initializes the guest:

```shell
--provision openshell-candidate-rpm-source \
--provision gateway-podman
```

The gateway-restart plan runs one `gateway-restart` action to verify continuity
across the restart.

`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.
`openshell-binaries-contract`, `openshell-rpm-contract`, and
`openshell-rpm-source` are internal composition roles used by the public source
provisioners. They are listed for the runner's role resolution but are not
normal `--provision` entry points.

Versioned plans under `nix/test-guest/conformance-plans/` bind conformance
scenarios to the stable action-command contracts installed by provisioners.
Expand Down
6 changes: 6 additions & 0 deletions nix/test-guest/configuration/podman-rootless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
6 changes: 6 additions & 0 deletions nix/test-guest/configuration/tasks/podman-common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,10 @@ version = 1
command = "/home/openshell/.local/bin/openshell-test-guest-diagnostics"
timeout_secs = 60

[[runs]]
scenario = "smoke"

[[runs]]
scenario = "sandbox-continuity"
workload_expectation = "reconciled"

[[runs.actions]]
name = "gateway-upgrade"
command = "/home/openshell/.local/bin/openshell-test-guest-gateway-upgrade"
timeout_secs = 120

[[runs.actions]]
name = "gateway-restart"
command = "/home/openshell/.local/bin/openshell-test-guest-gateway-restart"
Expand Down
13 changes: 7 additions & 6 deletions nix/test-guest/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ let
];

provisionerRoles = [
"openshell-development"
"openshell-rpm"
"openshell-rpm-latest-release"
"gateway-rootless-podman"
"openshell-rpm-gateway-reinstall"
"openshell-rpm-gateway-upgrade"
"openshell-candidate-binaries-source"
"openshell-binaries-contract"
"openshell-candidate-rpm-source"
"openshell-rpm-contract"
"openshell-latest-release-rpm-source"
"openshell-rpm-source"
"gateway-podman"
];

mkDistroProfile =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -50,25 +62,32 @@
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:
cmd: "podman image exists {{ openshell_supervisor_image }}"
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:
cmd: >-
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
Expand All @@ -84,3 +103,4 @@

[Install]
WantedBy=default.target
become: true
Loading
Loading