Skip to content

Commit 1e5d549

Browse files
Josh Carpjmcarp
authored andcommitted
misc: run acceptance tests from github actions.
1 parent e1f520e commit 1e5d549

File tree

5 files changed

+131
-7
lines changed

5 files changed

+131
-7
lines changed

.github/workflows/build-test.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,53 @@ jobs:
2929
run: make test
3030
- name: lint
3131
run: make lint
32+
acceptance:
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v5
36+
- uses: hashicorp/setup-terraform@v3
37+
- uses: actions/setup-go@v5
38+
with:
39+
go-version-file: 'go.mod'
40+
- uses: docker/setup-compose-action@v1
41+
- uses: astral-sh/setup-uv@v6
42+
- name: install oxide cli
43+
run: |
44+
mkdir -p bin
45+
wget https://github.com/oxidecomputer/oxide.rs/releases/download/v0.13.0+20250730.0.0/oxide-cli-x86_64-unknown-linux-gnu.tar.xz
46+
tar xvf oxide-cli-x86_64-unknown-linux-gnu.tar.xz
47+
mv oxide-cli-x86_64-unknown-linux-gnu/oxide bin
48+
echo "$(pwd)/bin" >> $GITHUB_PATH
49+
# Run simulated omicron in the background with docker compose.
50+
# TODO(jmcarp): support tests against multiple omicron versions.
51+
# TODO(jmcarp): publish this image for faster builds.
52+
- name: omicron-dev
53+
working-directory: acctest
54+
run: |
55+
docker compose build
56+
docker compose up --wait --wait-timeout 900
57+
# We can't use `oxide auth login` here, since it requires a browser to
58+
# complete the oauth device flow. Instead, fetch an auth token using a
59+
# script that simulates the browser flow.
60+
- id: auth-token
61+
working-directory: acctest
62+
run: |
63+
echo "OXIDE_TOKEN=$(uv run auth.py)" >> $GITHUB_OUTPUT
64+
- name: oxide-dependencies
65+
run: |
66+
sudo apt-get update && sudo apt-get install -y qemu-utils
67+
wget https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.1-x86_64-bios-tiny-r0.qcow2
68+
qemu-img convert -f qcow2 -O raw generic_alpine-3.22.1-x86_64-bios-tiny-r0.qcow2 alpine.raw
69+
./scripts/acc-test-setup.sh
70+
env:
71+
OXIDE_HOST: http://localhost:12220
72+
OXIDE_TOKEN: ${{ steps.auth-token.outputs.OXIDE_TOKEN }}
73+
- name: test
74+
shell: bash
75+
run: |
76+
make testacc
77+
env:
78+
OXIDE_HOST: http://localhost:12220
79+
OXIDE_TOKEN: ${{ steps.auth-token.outputs.OXIDE_TOKEN }}
80+
OXIDE_TEST_IP_POOL_NAME: default
81+
OXIDE_SILO_DNS_NAME: "*.sys.oxide-dev.test"

acctest/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM rust
2+
3+
SHELL ["/bin/bash", "-c"]
4+
5+
RUN \
6+
git clone https://github.com/oxidecomputer/omicron.git --depth 1 --branch jmcarp/prereqs-omit-sudo && \
7+
cd omicron && \
8+
source env.sh && \
9+
./tools/install_builder_prerequisites.sh -y -s
10+
11+
WORKDIR omicron

acctest/auth.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# /// script
2+
# dependencies = [
3+
# "httpx",
4+
# ]
5+
# ///
6+
7+
import argparse
8+
import uuid
9+
10+
import httpx
11+
12+
13+
def fetch_token(args):
14+
# Get auth cookie via password login.
15+
client = httpx.Client()
16+
client.post(
17+
f"{args.host}/v1/login/{args.silo}/local",
18+
json={"username": args.username, "password": args.password},
19+
).raise_for_status()
20+
21+
# Start the device auth flow.
22+
u = uuid.uuid4()
23+
device_resp = httpx.post(f"{args.host}/device/auth", data={"client_id": str(u)})
24+
device_resp.raise_for_status()
25+
device_details = device_resp.json()
26+
27+
# Confirm the device via the authenticated session.
28+
client.post(
29+
f"{args.host}/device/confirm", json={"user_code": device_details["user_code"]}
30+
).raise_for_status()
31+
32+
# Fetch the token.
33+
token_resp = httpx.post(
34+
f"{args.host}/device/token",
35+
data={
36+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
37+
"device_code": device_details["device_code"],
38+
"client_id": str(u),
39+
},
40+
)
41+
token_resp.raise_for_status()
42+
return token_resp.json()["access_token"]
43+
44+
45+
if __name__ == "__main__":
46+
parser = argparse.ArgumentParser()
47+
parser.add_argument("--host", default="http://localhost:12220")
48+
parser.add_argument("--silo", default="test-suite-silo")
49+
parser.add_argument("--username", default="test-privileged")
50+
parser.add_argument("--password", default="oxide")
51+
args = parser.parse_args()
52+
53+
print(fetch_token(args))

acctest/docker-compose.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
omicron-dev:
3+
build: .
4+
command: /bin/bash -c 'source env.sh && cargo xtask omicron-dev run-all'
5+
healthcheck:
6+
test: ["CMD", "curl", "-f", "http://localhost:12220"]
7+
interval: 5s
8+
retries: 180
9+
ports:
10+
- "12220:12220"

scripts/acc-test-setup.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ SILO_NAME=${OXIDE_SILO:-test-suite-silo}
1717
# qemu-img convert -f qcow2 -O raw generic_alpine-3.22.1-x86_64-bios-tiny-r0.qcow2 alpine.raw
1818
IMAGE_PATH=${OXIDE_IMAGE_PATH:-alpine.raw}
1919

20-
# oxide project create --name $PROJECT_NAME --description $PROJECT_NAME
20+
oxide project create --name $PROJECT_NAME --description $PROJECT_NAME
2121

22-
# # We need to create disks, images, etc., so override the default empty quota.
23-
# oxide silo quotas update --silo $SILO_NAME --cpus 100 --memory $((2 ** 40)) --storage $((2 ** 40))
22+
# We need to create disks, images, etc., so override the default empty quota.
23+
oxide silo quotas update --silo $SILO_NAME --cpus 100 --memory $((2 ** 40)) --storage $((2 ** 40))
2424

25-
# # Set up the default IP pool, and add a range.
26-
# oxide ip-pool create --name default --description default
27-
# oxide ip-pool silo link --pool default --silo $SILO_NAME --is-default true
28-
# oxide ip-pool range add --first 10.0.1.0 --last 10.0.1.255 --pool default
25+
# Set up the default IP pool, and add a range.
26+
oxide ip-pool create --name default --description default
27+
oxide ip-pool silo link --pool default --silo $SILO_NAME --is-default true
28+
oxide ip-pool range add --first 10.0.1.0 --last 10.0.1.255 --pool default
2929

3030
# The acceptance tests expect both at least a single project-scoped image and a
3131
# silo-scoped image. Import the same image twice, then promote one copy to the

0 commit comments

Comments
 (0)