Skip to content

Commit 8bd3dcc

Browse files
authored
refactor(tmachine): separate installers from environments (#3419)
Signed-off-by: Simon Scatton <sscatton@nvidia.com>
1 parent 4b2cb7f commit 8bd3dcc

12 files changed

Lines changed: 132 additions & 113 deletions

File tree

‎.github/workflows/branch-e2e.yml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,9 @@ jobs:
223223
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
224224
test-matrix: >-
225225
[
226-
{"scenario":"ubuntu-docker-rootful","testsuite":"conformance"},
227-
{"scenario":"fedora-podman-rootful","testsuite":"conformance"},
228-
{"scenario":"fedora-podman-rootless","testsuite":"conformance"}
226+
{"environment":"ubuntu-docker-rootful","installer":"binaries","testsuite":"conformance"},
227+
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"conformance"},
228+
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"conformance"}
229229
]
230230
231231
# Run feature-specific integration tests:
@@ -242,8 +242,8 @@ jobs:
242242
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
243243
test-matrix: >-
244244
[
245-
{"scenario":"fedora-podman-rootful","testsuite":"provider-refresh"},
246-
{"scenario":"fedora-podman-rootless","testsuite":"provider-refresh"}
245+
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"provider-refresh"},
246+
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"provider-refresh"}
247247
]
248248
249249
# Run driver-specific integration tests:

‎.github/workflows/integration-runner.yml‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ on:
1919
required: false
2020
type: string
2121
test-matrix:
22-
description: JSON array of scenario and testsuite combinations
22+
description: JSON array of environment, installer, and testsuite combinations
2323
required: false
2424
type: string
2525
default: >-
2626
[
27-
{"scenario":"ubuntu-docker-rootful","testsuite":"conformance"},
28-
{"scenario":"fedora-podman-rootful","testsuite":"conformance"},
29-
{"scenario":"fedora-podman-rootless","testsuite":"conformance"}
27+
{"environment":"ubuntu-docker-rootful","installer":"binaries","testsuite":"conformance"},
28+
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"conformance"},
29+
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"conformance"}
3030
]
3131
3232
permissions:
@@ -40,7 +40,7 @@ concurrency:
4040

4141
jobs:
4242
integration:
43-
name: Integration test (${{ inputs.category }}, ${{ matrix.scenario }}, ${{ matrix.testsuite }})
43+
name: Integration test (${{ inputs.category }}, ${{ matrix.environment }}, ${{ matrix.installer }}, ${{ matrix.testsuite }})
4444
strategy:
4545
fail-fast: false
4646
matrix:
@@ -80,6 +80,7 @@ jobs:
8080

8181
- name: Run test suite
8282
env:
83-
SCENARIO: ${{ matrix.scenario }}
83+
ENVIRONMENT: ${{ matrix.environment }}
84+
INSTALLER: ${{ matrix.installer }}
8485
TESTSUITE: ${{ matrix.testsuite }}
85-
run: nix run .#tmachine -- test "${SCENARIO}" "${TESTSUITE}"
86+
run: nix run .#tmachine -- test "${ENVIRONMENT}" "${INSTALLER}" "${TESTSUITE}"

‎.github/workflows/integration-test.yml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ on:
1717
type: string
1818
default: conformance
1919
test-matrix:
20-
description: JSON array of scenario and testsuite combinations
20+
description: JSON array of environment, installer, and testsuite combinations
2121
required: true
2222
type: string
2323
default: >-
2424
[
25-
{"scenario":"ubuntu-docker-rootful","testsuite":"conformance"},
26-
{"scenario":"fedora-podman-rootful","testsuite":"conformance"},
27-
{"scenario":"fedora-podman-rootless","testsuite":"conformance"}
25+
{"environment":"ubuntu-docker-rootful","installer":"binaries","testsuite":"conformance"},
26+
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"conformance"},
27+
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"conformance"}
2828
]
2929
3030
permissions:

‎.github/workflows/release-dev.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ jobs:
134134
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
135135
test-matrix: >-
136136
[
137-
{"scenario":"fedora-podman-rootful","testsuite":"provider-refresh"},
138-
{"scenario":"fedora-podman-rootless","testsuite":"provider-refresh"}
137+
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"provider-refresh"},
138+
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"provider-refresh"}
139139
]
140140
141141
docker-e2e:

‎.github/workflows/release-tag.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ jobs:
162162
integration-inputs-artifact-id: ${{ needs.prepare-integration.outputs.integration_inputs_artifact_id }}
163163
test-matrix: >-
164164
[
165-
{"scenario":"fedora-podman-rootful","testsuite":"provider-refresh"},
166-
{"scenario":"fedora-podman-rootless","testsuite":"provider-refresh"}
165+
{"environment":"fedora-podman-rootful","installer":"binaries","testsuite":"provider-refresh"},
166+
{"environment":"fedora-podman-rootless","installer":"binaries","testsuite":"provider-refresh"}
167167
]
168168
169169
docker-e2e:

‎architecture/build.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,18 @@ dependencies after installation. The Keycloak provider-refresh suite starts a
263263
guest-local Keycloak realm and verifies a successful OAuth refresh followed by
264264
revocation and the gateway's reauthorization-required recovery state.
265265

266-
The `tests/tmachine` setup and installation caches include a digest of the
266+
Tmachine environments define the guest machine and runtime setup, while named
267+
installers define how OpenShell is installed. This keeps the runtime mode
268+
independent from binary or package installation and lets multiple installers
269+
reuse the same prepared setup disk. The test command is
270+
`tmachine test <environment> <installer> <testsuite>`.
271+
272+
The `tests/tmachine` setup and install caches include a digest of the
267273
entire directory containing `ANSIBLE_CONFIG`, including local roles, task
268274
includes, templates, inventory, and requirements. The digest uses sorted
269275
relative paths, file contents, and executable permissions; source symlinks
270276
are unsupported. Both keys also retain the ordered playbook paths and contents,
271-
their base disk contents, and whether Galaxy is enabled; installation keys
277+
their base disk contents, and whether Galaxy is enabled; install keys
272278
include named binary inputs. The top-level `.roles` directory is excluded:
273279
Galaxy release pins in `requirements.yaml` are treated as immutable, including
274280
any transitive dependency pins. Cache misses with Galaxy enabled reinstall
@@ -279,7 +285,7 @@ with musl, and the gateway and supervisor with GNU. Image assembly stages
279285
the gateway, sandbox, and supervisor as separate binaries for their respective
280286
Dockerfiles. The helpers stage binaries under `artifacts/binaries` so local and
281287
CI builds expose the same inputs to tmachine and image assembly. The Ubuntu
282-
Docker and Fedora Podman scenarios import both local runtime images and
288+
Docker and Fedora Podman environments import both local runtime images and
283289
configure the gateway to use them.
284290

285291
## Python Wheel Packaging

‎tests/config.nix‎

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ let
3131
}
3232
];
3333

34-
scenarios = [
34+
environments = [
3535
{
3636
name = "ubuntu-docker-rootful";
3737
machine = "ubuntu";
@@ -42,19 +42,6 @@ let
4242
"ansible/playbooks/docker.yaml"
4343
];
4444
};
45-
install = {
46-
use_galaxy = false;
47-
playbooks = [
48-
"ansible/playbooks/openshell.yaml"
49-
"ansible/playbooks/gateway.yaml"
50-
];
51-
inputs = {
52-
openshell_cli_binary = "../artifacts/binaries/${muslTarget}/openshell";
53-
openshell_gateway_binary = "../artifacts/binaries/${gnuTarget}/openshell-gateway";
54-
openshell_supervisor_image = "../artifacts/images/openshell-supervisor-tmachine.tar";
55-
openshell_sandbox_image = "../artifacts/images/openshell-sandbox-tmachine.tar";
56-
};
57-
};
5845
}
5946
{
6047
name = "fedora-podman-rootful";
@@ -67,19 +54,6 @@ let
6754
"ansible/playbooks/podman-rootful.yaml"
6855
];
6956
};
70-
install = {
71-
use_galaxy = false;
72-
playbooks = [
73-
"ansible/playbooks/openshell.yaml"
74-
"ansible/playbooks/gateway.yaml"
75-
];
76-
inputs = {
77-
openshell_cli_binary = "../artifacts/binaries/${muslTarget}/openshell";
78-
openshell_gateway_binary = "../artifacts/binaries/${gnuTarget}/openshell-gateway";
79-
openshell_supervisor_image = "../artifacts/images/openshell-supervisor-tmachine.tar";
80-
openshell_sandbox_image = "../artifacts/images/openshell-sandbox-tmachine.tar";
81-
};
82-
};
8357
}
8458
{
8559
name = "fedora-podman-rootless";
@@ -92,18 +66,22 @@ let
9266
"ansible/playbooks/podman-rootless.yaml"
9367
];
9468
};
95-
install = {
96-
use_galaxy = false;
97-
playbooks = [
98-
"ansible/playbooks/openshell.yaml"
99-
"ansible/playbooks/gateway.yaml"
100-
];
101-
inputs = {
102-
openshell_cli_binary = "../artifacts/binaries/${muslTarget}/openshell";
103-
openshell_gateway_binary = "../artifacts/binaries/${gnuTarget}/openshell-gateway";
104-
openshell_supervisor_image = "../artifacts/images/openshell-supervisor-tmachine.tar";
105-
openshell_sandbox_image = "../artifacts/images/openshell-sandbox-tmachine.tar";
106-
};
69+
}
70+
];
71+
72+
installers = [
73+
{
74+
name = "binaries";
75+
use_galaxy = false;
76+
playbooks = [
77+
"ansible/playbooks/openshell.yaml"
78+
"ansible/playbooks/gateway.yaml"
79+
];
80+
inputs = {
81+
openshell_cli_binary = "../artifacts/binaries/${muslTarget}/openshell";
82+
openshell_gateway_binary = "../artifacts/binaries/${gnuTarget}/openshell-gateway";
83+
openshell_supervisor_image = "../artifacts/images/openshell-supervisor-tmachine.tar";
84+
openshell_sandbox_image = "../artifacts/images/openshell-sandbox-tmachine.tar";
10785
};
10886
}
10987
];

‎tests/tmachine/src/config.rs‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use serde::Deserialize;
1010
#[derive(Clone, Deserialize)]
1111
pub struct Config {
1212
pub machines: Vec<Machine>,
13-
pub scenarios: Vec<Scenario>,
13+
pub environments: Vec<Environment>,
14+
pub installers: Vec<Installer>,
1415
pub testsuites: Vec<Testsuite>,
1516
}
1617

@@ -21,11 +22,10 @@ pub struct Machine {
2122
}
2223

2324
#[derive(Clone, Deserialize)]
24-
pub struct Scenario {
25+
pub struct Environment {
2526
pub name: String,
2627
pub machine: String,
2728
pub setup: Setup,
28-
pub install: Install,
2929
}
3030

3131
#[derive(Clone, Deserialize)]
@@ -35,7 +35,8 @@ pub struct Setup {
3535
}
3636

3737
#[derive(Clone, Deserialize)]
38-
pub struct Install {
38+
pub struct Installer {
39+
pub name: String,
3940
pub use_galaxy: bool,
4041
pub playbooks: Vec<PathBuf>,
4142
pub inputs: BTreeMap<String, PathBuf>,

‎tests/tmachine/src/main.rs‎

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::path::PathBuf;
55

66
use anyhow::{Context, Result};
77
use clap::{Parser, Subcommand};
8-
use config::{Config, Machine, Scenario};
8+
use config::{Config, Environment, Installer, Machine};
99

1010
mod ansible;
1111
mod config;
@@ -23,9 +23,18 @@ struct Cli {
2323

2424
#[derive(Subcommand)]
2525
enum Command {
26-
Setup { scenario: String },
27-
Install { scenario: String },
28-
Test { scenario: String, testsuite: String },
26+
Setup {
27+
environment: String,
28+
},
29+
Install {
30+
environment: String,
31+
installer: String,
32+
},
33+
Test {
34+
environment: String,
35+
installer: String,
36+
testsuite: String,
37+
},
2938
}
3039

3140
#[tokio::main(flavor = "current_thread")]
@@ -34,49 +43,64 @@ async fn main() -> Result<()> {
3443
let config = Config::load(&cli.config)?;
3544

3645
match cli.command {
37-
Command::Setup { scenario } => {
38-
let (machine, scenario) = find_scenario(&config, &scenario)?;
39-
qemu::setup(&machine, &scenario).await?;
46+
Command::Setup { environment } => {
47+
let (machine, environment) = find_environment(&config, &environment)?;
48+
qemu::setup(&machine, &environment).await?;
4049
}
41-
Command::Install { scenario } => {
42-
let (machine, scenario) = find_scenario(&config, &scenario)?;
43-
qemu::install(&machine, &scenario).await?;
50+
Command::Install {
51+
environment,
52+
installer,
53+
} => {
54+
let (machine, environment) = find_environment(&config, &environment)?;
55+
let installer = find_installer(&config, &installer)?;
56+
qemu::install(&machine, &environment, &installer).await?;
4457
}
4558
Command::Test {
46-
scenario,
59+
environment,
60+
installer,
4761
testsuite,
4862
} => {
49-
let (machine, scenario) = find_scenario(&config, &scenario)?;
63+
let (machine, environment) = find_environment(&config, &environment)?;
64+
let installer = find_installer(&config, &installer)?;
5065
let testsuite = config
5166
.testsuites
5267
.iter()
5368
.find(|candidate| candidate.name == testsuite)
5469
.with_context(|| format!("testsuite {testsuite:?} is not defined"))?;
55-
qemu::test(&machine, &scenario, testsuite).await?;
70+
qemu::test(&machine, &environment, &installer, testsuite).await?;
5671
}
5772
}
5873

5974
Ok(())
6075
}
6176

62-
fn find_scenario(config: &Config, name: &str) -> Result<(Machine, Scenario)> {
63-
let scenario = config
64-
.scenarios
77+
fn find_installer(config: &Config, name: &str) -> Result<Installer> {
78+
config
79+
.installers
80+
.iter()
81+
.find(|installer| installer.name == name)
82+
.with_context(|| format!("installer {name:?} is not defined"))
83+
.cloned()
84+
}
85+
86+
fn find_environment(config: &Config, name: &str) -> Result<(Machine, Environment)> {
87+
let environment = config
88+
.environments
6589
.iter()
66-
.find(|scenario| scenario.name == name)
67-
.with_context(|| format!("scenario {name:?} is not defined"))?
90+
.find(|environment| environment.name == name)
91+
.with_context(|| format!("environment {name:?} is not defined"))?
6892
.clone();
6993
let machine = config
7094
.machines
7195
.iter()
72-
.find(|machine| machine.name == scenario.machine)
96+
.find(|machine| machine.name == environment.machine)
7397
.with_context(|| {
7498
format!(
75-
"machine {:?} referenced by scenario {:?} is not defined",
76-
scenario.machine, scenario.name
99+
"machine {:?} referenced by environment {:?} is not defined",
100+
environment.machine, environment.name
77101
)
78102
})?
79103
.clone();
80104

81-
Ok((machine, scenario))
105+
Ok((machine, environment))
82106
}

0 commit comments

Comments
 (0)