Replace transient test labels with stable identifiers
This commit is contained in:
parent
4ca7526d50
commit
d0b745950b
17 changed files with 63 additions and 38 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,7 +1,5 @@
|
|||
# Development scratchpad
|
||||
scratchpad
|
||||
|
||||
# Development journal
|
||||
docs/journal
|
||||
|
||||
# TLC working directories
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ impl Harness {
|
|||
let coordination = CoordinationStore::connect(
|
||||
&required_env("REMORA_COORDINATION_URL"),
|
||||
format!(
|
||||
"{}wp22:{}:",
|
||||
"{}live-events:{}:",
|
||||
required_env("REMORA_COORDINATION_NAMESPACE"),
|
||||
nonce()
|
||||
),
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ impl Harness {
|
|||
let coordination = CoordinationStore::connect(
|
||||
&required_env("REMORA_COORDINATION_URL"),
|
||||
format!(
|
||||
"{}wp21:{}:",
|
||||
"{}public-api:{}:",
|
||||
required_env("REMORA_COORDINATION_NAMESPACE"),
|
||||
nonce()
|
||||
),
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl Harness {
|
|||
.unwrap();
|
||||
let coordination = CoordinationStore::connect(
|
||||
&coordination_url,
|
||||
format!("{}wp18:{name}:{}:", coordination_namespace(), nonce()),
|
||||
format!("{}worker-api:{name}:{}:", coordination_namespace(), nonce()),
|
||||
StoreConfig {
|
||||
global_limit: 16,
|
||||
lease_ttl: Duration::from_secs(10),
|
||||
|
|
|
|||
|
|
@ -37,7 +37,11 @@ impl Harness {
|
|||
.await
|
||||
.expect("connect postgres");
|
||||
migrate_schema(&pool).await.expect("schema migrate");
|
||||
let namespace = format!("{}wp15:{name}:{}:", coordination_namespace(), nonce());
|
||||
let namespace = format!(
|
||||
"{}attempt-authority:{name}:{}:",
|
||||
coordination_namespace(),
|
||||
nonce()
|
||||
);
|
||||
let coordination = CoordinationStore::connect(
|
||||
&coordination_url,
|
||||
namespace,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,11 @@ impl Harness {
|
|||
migrate_schema(&pool).await.expect("schema migrate");
|
||||
let coordination = CoordinationStore::connect(
|
||||
&coordination_url,
|
||||
format!("{}wp16:{name}:{}:", coordination_namespace(), nonce()),
|
||||
format!(
|
||||
"{}attempt-mutations:{name}:{}:",
|
||||
coordination_namespace(),
|
||||
nonce()
|
||||
),
|
||||
StoreConfig {
|
||||
global_limit: 16,
|
||||
lease_ttl: Duration::from_secs(10),
|
||||
|
|
|
|||
|
|
@ -132,7 +132,11 @@ impl Harness {
|
|||
.expect("reset recovery test state");
|
||||
let coordination = CoordinationStore::connect(
|
||||
&coordination_url,
|
||||
format!("{}wp17:{name}:{}:", coordination_namespace(), nonce()),
|
||||
format!(
|
||||
"{}attempt-recovery:{name}:{}:",
|
||||
coordination_namespace(),
|
||||
nonce()
|
||||
),
|
||||
StoreConfig {
|
||||
global_limit: 32,
|
||||
lease_ttl: Duration::from_secs(10),
|
||||
|
|
@ -460,7 +464,11 @@ async fn coordination_partition_rolls_back_and_restart_converges() {
|
|||
let proxy_url = proxy.url();
|
||||
let store = CoordinationStore::connect(
|
||||
&proxy_url,
|
||||
format!("{}wp17:partition:{}:", coordination_namespace(), nonce()),
|
||||
format!(
|
||||
"{}attempt-recovery:partition:{}:",
|
||||
coordination_namespace(),
|
||||
nonce()
|
||||
),
|
||||
StoreConfig::default(),
|
||||
)
|
||||
.await
|
||||
|
|
@ -501,7 +509,11 @@ async fn coordination_partition_rolls_back_and_restart_converges() {
|
|||
let resumed_proxy = CoordinationProxy::start(upstream, Some(address)).await;
|
||||
let resumed_store = CoordinationStore::connect(
|
||||
&resumed_proxy.url(),
|
||||
format!("{}wp17:partition:{}:", coordination_namespace(), nonce()),
|
||||
format!(
|
||||
"{}attempt-recovery:partition:{}:",
|
||||
coordination_namespace(),
|
||||
nonce()
|
||||
),
|
||||
StoreConfig::default(),
|
||||
)
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ fn coordination_namespace(suite: &str) -> String {
|
|||
.ok()
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or_else(|| "remora:test:".into());
|
||||
format!("{base}wp04:{suite}:")
|
||||
format!("{base}coordination-substrate:{suite}:")
|
||||
}
|
||||
|
||||
async fn test_store(
|
||||
|
|
|
|||
|
|
@ -358,6 +358,6 @@ async fn object_source_and_destination_resume_matrix() {
|
|||
.await
|
||||
.expect("version purge");
|
||||
} else if std::env::var("REMORA_TARGET_PROVIDER").as_deref() == Ok("versitygw") {
|
||||
panic!("VersityGW must support version-pinned WP-12 qualification");
|
||||
panic!("VersityGW must support version-pinned object-source qualification");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -331,7 +331,9 @@ async fn version_addressed_and_stale_version_matrix() {
|
|||
let provider =
|
||||
std::env::var("REMORA_TARGET_PROVIDER").unwrap_or_else(|_| "unknown".into());
|
||||
if provider == "versitygw" {
|
||||
panic!("versitygw must support bucket versioning for WP-08 matrix");
|
||||
panic!(
|
||||
"versitygw must support bucket versioning for the target compatibility matrix"
|
||||
);
|
||||
}
|
||||
}
|
||||
eprintln!(
|
||||
|
|
|
|||
|
|
@ -85,7 +85,11 @@ impl Harness {
|
|||
.unwrap();
|
||||
let coordination = CoordinationStore::connect(
|
||||
&coordination_url,
|
||||
format!("{}wp19:{name}:{}:", coordination_namespace(), nonce()),
|
||||
format!(
|
||||
"{}worker-runtime:{name}:{}:",
|
||||
coordination_namespace(),
|
||||
nonce()
|
||||
),
|
||||
StoreConfig {
|
||||
global_limit: 16,
|
||||
lease_ttl: Duration::from_secs(2),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Terms in this glossary are stable identifiers for use across Remora documentatio
|
|||
| `StorageAdapter` | The service boundary through which workers write to the target object store. |
|
||||
| `TargetStore` | The configured S3-compatible object store receiving downloaded objects. |
|
||||
| `JobProtocol` | The TLA+ specification defining distributed job state, coordination semantics, and safety and liveness properties. |
|
||||
| `TestComponent` | A repository-owned acceptance-test unit with its test code, runner image, manifest, acceptance command, and required compatibility families. |
|
||||
|
||||
## Scope
|
||||
|
||||
|
|
|
|||
|
|
@ -4,21 +4,21 @@ Backend integration and fault tests execute as Kubernetes `Job` resources inside
|
|||
|
||||
## Fixture lifecycle
|
||||
|
||||
`make check-dependencies` remains the dependency compatibility gate: it creates the full fixture, runs the released-image probes, and tears the fixture down. `make check-kind-sample` builds and loads a Remora-owned cargo-nextest runner, then exercises the full provider matrix around [`fixture-consumer-sample`](../../tests/kind/sample-job.yaml.in). Its init containers access the lane database, coordination namespace, OIDC discovery and signing keys, target bucket, and Vault path before cargo-nextest runs. That Job is the reference structure for a work-package test Job.
|
||||
`make check-dependencies` remains the dependency compatibility gate: it creates the full fixture, runs the released-image probes, and tears the fixture down. `make check-kind-sample` builds and loads a Remora-owned cargo-nextest runner, then exercises the full provider matrix around [`fixture-consumer-sample`](../../tests/kind/sample-job.yaml.in). Its init containers access the lane database, coordination namespace, OIDC discovery and signing keys, target bucket, and Vault path before cargo-nextest runs. That Job is the reference structure for a `TestComponent` test Job.
|
||||
|
||||
For interactive work, `tests/kind/setup.sh` creates a ready fixture and leaves it running. `tests/kind/destroy.sh` removes it. Setup replaces any fixture left by an earlier run, teardown is idempotent, and a host-runtime lock shared across worktrees serializes lifecycle mutations around the single `remora-testbed` cluster and `remora-wp02` containerd namespace. `REMORA_TESTBED_RETAIN=1` retains a failed all-in-one run for inspection.
|
||||
For interactive work, `tests/kind/setup.sh` creates a ready fixture and leaves it running. `tests/kind/destroy.sh` removes it. Setup replaces any fixture left by an earlier run, teardown is idempotent, and a host-runtime lock shared across worktrees serializes lifecycle mutations around the single `remora-testbed` cluster and `remora-dependency-testbed` containerd namespace. `REMORA_TESTBED_RETAIN=1` retains a failed all-in-one run for inspection.
|
||||
|
||||
The fixture owns an isolated kubeconfig at `tests/kind/.runtime/kubeconfig` and the `kind-remora-testbed` context. Every Kubernetes operation uses both explicitly. Package runners use the `kube` helper from `tests/kind/lib.sh`; they do not read or change the user's kubeconfig or current context.
|
||||
|
||||
## Package test Jobs
|
||||
|
||||
Each work package owns its test code, test-runner image, Job manifest, acceptance command, and required compatibility families. Its all-in-one runner follows [`run-sample-job.sh`](../../tests/kind/run-sample-job.sh): acquire the fixture lock, install a cleanup trap, call `setup_fixture <families...>`, load any package-owned image with `load_local_image <image> [containerd-namespace]`, and call `run_job_matrix <job-name> <manifest> <image> <families...>`. The image namespace defaults to `default`. A retained failure prints the isolated kubeconfig and context.
|
||||
Each `TestComponent` owns its test code, test-runner image, Job manifest, acceptance command, and required compatibility families. Its all-in-one runner follows [`run-sample-job.sh`](../../tests/kind/run-sample-job.sh): acquire the fixture lock, install a cleanup trap, call `setup_fixture <families...>`, load any component-owned image with `load_local_image <image> [containerd-namespace]`, and call `run_job_matrix <job-name> <manifest> <image> <families...>`. The image namespace defaults to `default`. A retained failure prints the isolated kubeconfig and context.
|
||||
|
||||
The selectable families are `base`, `durable`, `coordination`, `oidc`, `target`, `secret`, and `all`. `base` provisions only the cluster and common namespace for suites whose controlled fixtures run inside their test pod. Individual implementations are not selectors. A suite that requests `coordination`, `oidc`, and `target` runs the unchanged cargo-nextest archive against the full Redis/DragonflyDB × Keycloak/ZITADEL × Garage/VersityGW Cartesian product. Lanes run sequentially and stop on the first failure.
|
||||
|
||||
Before each lane, the runner recreates a lane database, allocates unique coordination keys, provisions an OIDC tenant/client/user/role grant, creates a target bucket and prefix, and allocates a Vault path as required by the selected families. The resulting environment is exposed both through environment variables and a ConfigMap-mounted `/run/remora-fixture/profile.env`. Package manifests use `@@JOB_NAME@@`, `@@PROFILE_NAME@@`, and `@@TEST_IMAGE@@` placeholders so only the profile and lane identity vary between Jobs.
|
||||
|
||||
Released third-party dependencies are always the digest-pinned images loaded by the fixture. Work packages may build Remora test-runner images locally; they do not rebuild or wrap dependency images. The Job manifest names every loaded image exactly and sets `imagePullPolicy: Never`.
|
||||
Released third-party dependencies are always the digest-pinned images loaded by the fixture. Test components may build Remora test-runner images locally; they do not rebuild or wrap dependency images. The Job manifest names every loaded image exactly and sets `imagePullPolicy: Never`.
|
||||
|
||||
A test Job:
|
||||
|
||||
|
|
@ -34,4 +34,4 @@ Package runners may create additional namespaced fixtures and fault injectors ne
|
|||
|
||||
Automated backend tests use cluster-local service discovery. Tests of Keycloak or ZITADEL issuer behavior use the `dnsPolicy` and `dnsConfig` pattern in [`fixture-consumer-sample`](../../tests/kind/sample-job.yaml.in) so discovery URLs and token issuers have one identity from every participating pod.
|
||||
|
||||
Port forwarding is for interactive diagnostics only and is not an acceptance-test transport. Ingress is introduced by deployment and system qualification, where routing is itself under test; substrate work packages do not install an ingress controller merely to reach fixture services.
|
||||
Port forwarding is for interactive diagnostics only and is not an acceptance-test transport. Ingress is introduced by deployment and system qualification, where routing is itself under test; substrate test components do not install an ingress controller merely to reach fixture services.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ FIXTURE_LOCK_DIR="${XDG_RUNTIME_DIR:-/tmp/remora-$(id -u)}"
|
|||
FIXTURE_LOCK_PATH="$FIXTURE_LOCK_DIR/remora-testbed-kind.lock"
|
||||
CONTEXT=kind-remora-testbed
|
||||
CLUSTER=remora-testbed
|
||||
NERDCTL_NAMESPACE=remora-wp02
|
||||
NERDCTL_NAMESPACE=remora-dependency-testbed
|
||||
FIXTURE_NAMESPACE=remora-testbed
|
||||
|
||||
set -a
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: probe-payload
|
||||
namespace: remora-testbed
|
||||
data:
|
||||
payload: remora-wp02-published-image-transfer
|
||||
payload: remora-dependency-testbed-published-image-transfer
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
|
|
@ -34,28 +34,28 @@ spec:
|
|||
- -v
|
||||
- ON_ERROR_STOP=1
|
||||
- -c
|
||||
- "CREATE TABLE wp02_probe (value text NOT NULL)"
|
||||
- "CREATE TABLE dependency_probe (value text NOT NULL)"
|
||||
- -c
|
||||
- "INSERT INTO wp02_probe VALUES ('passed')"
|
||||
- "INSERT INTO dependency_probe VALUES ('passed')"
|
||||
- -c
|
||||
- "SELECT value = 'passed' FROM wp02_probe"
|
||||
- "SELECT value = 'passed' FROM dependency_probe"
|
||||
env:
|
||||
- {name: PGPASSWORD, value: synthetic-postgres}
|
||||
- name: redis
|
||||
image: @@REDIS_IMAGE@@
|
||||
imagePullPolicy: Never
|
||||
command: [/bin/sh, -ec]
|
||||
args: ["redis-cli -h redis SET wp02 passed && test \"$(redis-cli -h redis GET wp02)\" = passed"]
|
||||
args: ["redis-cli -h redis SET dependency_probe passed && test \"$(redis-cli -h redis GET dependency_probe)\" = passed"]
|
||||
- name: dragonfly
|
||||
image: @@REDIS_IMAGE@@
|
||||
imagePullPolicy: Never
|
||||
command: [/bin/sh, -ec]
|
||||
args: ["redis-cli -h dragonfly SET wp02 passed && test \"$(redis-cli -h dragonfly GET wp02)\" = passed"]
|
||||
args: ["redis-cli -h dragonfly SET dependency_probe passed && test \"$(redis-cli -h dragonfly GET dependency_probe)\" = passed"]
|
||||
- name: vault-write
|
||||
image: @@VAULT_IMAGE@@
|
||||
imagePullPolicy: Never
|
||||
command: [vault]
|
||||
args: [kv, put, secret/wp02, value=passed]
|
||||
args: [kv, put, secret/dependency_probe, value=passed]
|
||||
env:
|
||||
- {name: VAULT_ADDR, value: "http://vault:8200"}
|
||||
- {name: VAULT_TOKEN, value: synthetic-vault-token}
|
||||
|
|
@ -64,7 +64,7 @@ spec:
|
|||
image: @@VAULT_IMAGE@@
|
||||
imagePullPolicy: Never
|
||||
command: [/bin/sh, -ec]
|
||||
args: ["test \"$(vault kv get -field=value secret/wp02)\" = passed && printf 'Vault write/read passed\\n'"]
|
||||
args: ["test \"$(vault kv get -field=value secret/dependency_probe)\" = passed && printf 'Vault write/read passed\\n'"]
|
||||
env:
|
||||
- {name: VAULT_ADDR, value: "http://vault:8200"}
|
||||
- {name: VAULT_TOKEN, value: synthetic-vault-token}
|
||||
|
|
|
|||
|
|
@ -175,11 +175,11 @@ write_helm_values() {
|
|||
fi
|
||||
cat > "$RUNTIME/deployment-values.yaml" <<EOF
|
||||
api:
|
||||
image: {repository: remora-api, tag: wp25, digest: "", pullPolicy: Never}
|
||||
image: {repository: remora-api, tag: local, digest: "", pullPolicy: Never}
|
||||
worker:
|
||||
image: {repository: remora-worker, tag: wp25, digest: "", pullPolicy: Never}
|
||||
image: {repository: remora-worker, tag: local, digest: "", pullPolicy: Never}
|
||||
web:
|
||||
image: {repository: remora-web, tag: wp25, digest: "", pullPolicy: Never}
|
||||
image: {repository: remora-web, tag: local, digest: "", pullPolicy: Never}
|
||||
publicOrigin: $public_origin
|
||||
apiUrl: /v1/
|
||||
oidcClientId: remora-web
|
||||
|
|
@ -432,17 +432,17 @@ validate_deployment_assets
|
|||
"$REMORA_REAL_NERDCTL" --namespace default build \
|
||||
--file "$ROOT/Dockerfile" \
|
||||
--target api \
|
||||
--tag remora-api:wp25 \
|
||||
--tag remora-api:local \
|
||||
"$ROOT"
|
||||
"$REMORA_REAL_NERDCTL" --namespace default build \
|
||||
--file "$ROOT/Dockerfile" \
|
||||
--target worker \
|
||||
--tag remora-worker:wp25 \
|
||||
--tag remora-worker:local \
|
||||
"$ROOT"
|
||||
"$REMORA_REAL_NERDCTL" --namespace default build \
|
||||
--file "$ROOT/Dockerfile" \
|
||||
--target web \
|
||||
--tag remora-web:wp25 \
|
||||
--tag remora-web:local \
|
||||
"$ROOT"
|
||||
"$REMORA_REAL_NERDCTL" --namespace default build \
|
||||
--file "$ROOT/Dockerfile.test" \
|
||||
|
|
@ -462,9 +462,9 @@ setup_fixture durable coordination oidc target secret
|
|||
if [[ "${REMORA_SYSTEM_QUALIFICATION:-0}" = 1 ]]; then
|
||||
install_qualification_ingress
|
||||
fi
|
||||
load_local_image remora-api:wp25
|
||||
load_local_image remora-worker:wp25
|
||||
load_local_image remora-web:wp25
|
||||
load_local_image remora-api:local
|
||||
load_local_image remora-worker:local
|
||||
load_local_image remora-web:local
|
||||
load_local_image remora-kind-deployment:local
|
||||
if [[ "${REMORA_SYSTEM_QUALIFICATION:-0}" = 1 ]]; then
|
||||
load_local_image remora-kind-web-system:local
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ cleanup() {
|
|||
status=1
|
||||
fi
|
||||
if [[ "$status" = 0 ]] && [[ "$SUCCEEDED" = true ]]; then
|
||||
printf 'WP-02 hermetic dependency testbed passed\n'
|
||||
printf 'hermetic dependency testbed passed\n'
|
||||
fi
|
||||
exit "$status"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue