test: use RustFS for S3 service fixtures

This commit is contained in:
vorotamoroz
2026-09-15 13:32:55 +00:00
parent 6f0892a825
commit d082b409c0
13 changed files with 157 additions and 133 deletions
+1 -1
View File
@@ -199,7 +199,7 @@ jobs:
if: ${{ steps.integration_tests.outputs.present == 'true' }}
run: npm run test:docker-couchdb:start
- name: Start MinIO container
- name: Start RustFS container
if: ${{ steps.integration_tests.outputs.present == 'true' }}
run: npm run test:docker-s3:start
+2 -2
View File
@@ -87,9 +87,9 @@ Regression tests remain in the suite owned by the implementation under test. Plu
- **CLI E2E** (`src/apps/cli/testdeno/`): Host-independent consumer workflows. The canonical Compose P2P suite covers ordinary two-peer synchronisation, replacement of the current Replicator followed by transfer with the same peer, and explicit relay disconnection followed by paused and resumed reconnection. Its lifecycle entry point is included only in the Docker test build and does not add a public CLI command. Run `npm run test:e2e:cli` for the ordinary suite or `npm run test:e2e:cli:p2p` for P2P validation.
- **Self-hosted setup tools** (`utils/couchdb/`, `utils/setup/`, and `utils/flyio/`): Deno contract tests consume the exact locked Commonlib registry package, verify current CouchDB, Object Storage, and random-room P2P Setup URI defaults and remote profiles, and keep CouchDB administration separate from package-owned LiveSync database-version negotiation. `unit-ci` also provisions a real temporary CouchDB database and verifies its version document against the installed Commonlib package. Run `npm run test:setup-tools` for the local contract gate.
- **Real Obsidian E2E** (`test/e2e-obsidian/`): Local-first scripts that launch real Obsidian with temporary vaults and the built Self-hosted LiveSync plug-in. Use these for boot-up sequence, vault reflection, RedFlag flows, Fast Setup (Simple Fetch), settings dialogues, restart-sensitive workflows, Object Storage regressions, and other behaviour that depends on Obsidian itself. Run focused scripts such as `npm run test:e2e:obsidian:two-vault-sync`, or use `npm run test:e2e:obsidian:local-suite:services` to run the broader local suite with CouchDB and MinIO fixtures managed by the wrapper.
- **Real Obsidian E2E** (`test/e2e-obsidian/`): Local-first scripts that launch real Obsidian with temporary vaults and the built Self-hosted LiveSync plug-in. Use these for boot-up sequence, vault reflection, RedFlag flows, Fast Setup (Simple Fetch), settings dialogues, restart-sensitive workflows, Object Storage regressions, and other behaviour that depends on Obsidian itself. Run focused scripts such as `npm run test:e2e:obsidian:two-vault-sync`, or use `npm run test:e2e:obsidian:local-suite:services` to run the broader local suite with CouchDB and RustFS fixtures managed by the wrapper.
- **Docker Services**: Service-backed tests use CouchDB and MinIO (S3). Canonical P2P validation owns its relay through the CLI Compose runner:
- **Docker Services**: Service-backed tests use CouchDB and RustFS (S3). Canonical P2P validation owns its relay through the CLI Compose runner:
```bash
npm run test:docker-all:start # Start all test services
+27 -10
View File
@@ -307,10 +307,19 @@ cli_test_wait_for_minio_bucket() {
local delay_sec=2
local i
for ((i = 1; i <= retries; i++)); do
if docker run --rm --network host --entrypoint=/bin/sh minio/mc -c "mc alias set myminio $minio_endpoint $minio_access_key $minio_secret_key >/dev/null 2>&1 && mc ls myminio/$minio_bucket >/dev/null 2>&1"; then
if docker run --rm --network host --entrypoint=/bin/sh \
rustfs/rc:v0.1.35@sha256:adb45b56539006120f1d790bcc17ee5f9b4d93c1d7e71ed0a24f10267f9d6914 \
-c 'set -e
rc alias set myminio "$1" "$2" "$3" >/dev/null 2>&1
rc ls "myminio/$4" >/dev/null 2>&1
' sh "$minio_endpoint" "$minio_access_key" "$minio_secret_key" "$minio_bucket"; then
return 0
fi
bucketName="$minio_bucket" bash "$CLI_DIR/util/minio-init.sh" >/dev/null 2>&1 || true
minioEndpoint="$minio_endpoint" \
accessKey="$minio_access_key" \
secretKey="$minio_secret_key" \
bucketName="$minio_bucket" \
bash "$CLI_DIR/util/minio-init.sh" >/dev/null 2>&1 || true
sleep "$delay_sec"
done
return 1
@@ -323,26 +332,34 @@ cli_test_start_minio() {
local minio_bucket="$4"
local minio_init_ok=0
echo "[INFO] stopping leftover MinIO container if present"
echo "[INFO] stopping leftover RustFS container if present"
cli_test_stop_minio
echo "[INFO] starting MinIO test container"
bucketName="$minio_bucket" bash "$CLI_DIR/util/minio-start.sh"
echo "[INFO] starting RustFS test container"
minioEndpoint="$minio_endpoint" \
accessKey="$minio_access_key" \
secretKey="$minio_secret_key" \
bucketName="$minio_bucket" \
bash "$CLI_DIR/util/minio-start.sh"
echo "[INFO] initialising MinIO test bucket: $minio_bucket"
echo "[INFO] initialising RustFS test bucket: $minio_bucket"
for _ in 1 2 3 4 5; do
if bucketName="$minio_bucket" bash "$CLI_DIR/util/minio-init.sh"; then
if minioEndpoint="$minio_endpoint" \
accessKey="$minio_access_key" \
secretKey="$minio_secret_key" \
bucketName="$minio_bucket" \
bash "$CLI_DIR/util/minio-init.sh"; then
minio_init_ok=1
break
fi
sleep 2
done
if [[ "$minio_init_ok" != "1" ]]; then
echo "[FAIL] could not initialise MinIO bucket after retries: $minio_bucket" >&2
echo "[FAIL] could not initialise RustFS bucket after retries: $minio_bucket" >&2
exit 1
fi
if ! cli_test_wait_for_minio_bucket "$minio_endpoint" "$minio_access_key" "$minio_secret_key" "$minio_bucket"; then
echo "[FAIL] MinIO bucket not ready: $minio_bucket" >&2
echo "[FAIL] RustFS bucket not ready: $minio_bucket" >&2
exit 1
fi
}
@@ -359,4 +376,4 @@ display_test_info(){
if [[ "${LIVESYNC_TEST_DOCKER:-0}" == "1" ]]; then
# shellcheck source=/dev/null
source "$(dirname "${BASH_SOURCE[0]}")/test-helpers-docker.sh"
fi
fi
+37 -23
View File
@@ -190,7 +190,7 @@ async function dockerOrFail(...args: string[]): Promise<string> {
async function stopAndRemoveContainer(container: string): Promise<void> {
await docker("stop", container).catch(() => {});
await docker("rm", container).catch(() => {});
await docker("rm", "-v", container).catch(() => {});
}
async function cleanupTrackedContainers(reason: string): Promise<void> {
@@ -327,8 +327,22 @@ const COUCHDB_CONTAINER = "couchdb-test";
const COUCHDB_IMAGE = "couchdb:3.5.0";
const MINIO_CONTAINER = "minio-test";
const MINIO_IMAGE = "minio/minio";
const MINIO_MC_IMAGE = "minio/mc";
// RustFS provides the S3 backend for the existing MINIO test mode.
const S3_IMAGE = "rustfs/rustfs:1.0.0-rc.6@sha256:97171b3d72cd47dc81000f92ea84de25608bfc35a94c965501afaeb5d99f6035";
const S3_CLIENT_IMAGE = "rustfs/rc:v0.1.35@sha256:adb45b56539006120f1d790bcc17ee5f9b4d93c1d7e71ed0a24f10267f9d6914";
const S3_BUCKET_CORS = `<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<AllowedHeader>authorization</AllowedHeader>
<ExposeHeader>ETag</ExposeHeader>
</CORSRule>
</CORSConfiguration>`;
export async function stopCouchdb(): Promise<void> {
await stopAndRemoveContainer(COUCHDB_CONTAINER);
@@ -454,7 +468,7 @@ export async function updateCouchdbDoc(
}
// ---------------------------------------------------------------------------
// MinIO
// S3 (RustFS)
// ---------------------------------------------------------------------------
function shQuote(value: string): string {
@@ -473,9 +487,10 @@ async function initMinioBucket(
bucket: string
): Promise<boolean> {
const cmd =
`mc alias set myminio ${shQuote(minioEndpoint)} ${shQuote(accessKey)} ${shQuote(secretKey)} >/dev/null 2>&1 && ` +
`mc mb --ignore-existing myminio/${shQuote(bucket)} >/dev/null 2>&1`;
const r = await docker("run", "--rm", "--network", "host", "--entrypoint", "/bin/sh", MINIO_MC_IMAGE, "-c", cmd);
`rc alias set myminio ${shQuote(minioEndpoint)} ${shQuote(accessKey)} ${shQuote(secretKey)} >/dev/null 2>&1 && ` +
`rc mb --ignore-existing myminio/${shQuote(bucket)} >/dev/null 2>&1 && ` +
`printf %s ${shQuote(S3_BUCKET_CORS)} | rc cors set myminio/${shQuote(bucket)} - >/dev/null 2>&1`;
const r = await docker("run", "--rm", "--network", "host", "--entrypoint", "/bin/sh", S3_CLIENT_IMAGE, "-c", cmd);
return r.code === 0;
}
@@ -487,8 +502,8 @@ async function waitForMinioBucket(
): Promise<void> {
for (let i = 0; i < 30; i++) {
const checkCmd =
`mc alias set myminio ${shQuote(minioEndpoint)} ${shQuote(accessKey)} ${shQuote(secretKey)} >/dev/null 2>&1 && ` +
`mc ls myminio/${shQuote(bucket)} >/dev/null 2>&1`;
`rc alias set myminio ${shQuote(minioEndpoint)} ${shQuote(accessKey)} ${shQuote(secretKey)} >/dev/null 2>&1 && ` +
`rc ls myminio/${shQuote(bucket)} >/dev/null 2>&1`;
const check = await docker(
"run",
"--rm",
@@ -498,7 +513,7 @@ async function waitForMinioBucket(
"host",
"--entrypoint",
"/bin/sh",
MINIO_MC_IMAGE,
S3_CLIENT_IMAGE,
"-c",
checkCmd
);
@@ -508,7 +523,7 @@ async function waitForMinioBucket(
await initMinioBucket(minioEndpoint, accessKey, secretKey, bucket);
await sleep(2000);
}
throw new Error(`MinIO bucket not ready: ${bucket}`);
throw new Error(`S3 bucket not ready: ${bucket}`);
}
export async function startMinio(
@@ -517,10 +532,10 @@ export async function startMinio(
secretKey: string,
bucket: string
): Promise<void> {
console.log("[INFO] stopping leftover MinIO container if present");
console.log("[INFO] stopping leftover S3 test container if present");
await stopMinio().catch(() => {});
console.log("[INFO] starting MinIO test container");
console.log("[INFO] starting RustFS test container");
await dockerOrFail(
"run",
"-d",
@@ -532,20 +547,19 @@ export async function startMinio(
"-p",
"9001:9001",
"-e",
`MINIO_ROOT_USER=${accessKey}`,
`RUSTFS_ACCESS_KEY=${accessKey}`,
"-e",
`MINIO_ROOT_PASSWORD=${secretKey}`,
`RUSTFS_SECRET_KEY=${secretKey}`,
"-e",
`MINIO_SERVER_URL=${minioEndpoint}`,
MINIO_IMAGE,
"server",
"/data",
"--console-address",
":9001"
"RUSTFS_CONSOLE_ENABLE=true",
"-e",
"RUSTFS_CORS_ALLOWED_ORIGINS=*",
S3_IMAGE,
"/data"
);
trackContainer(MINIO_CONTAINER);
console.log(`[INFO] initialising MinIO test bucket: ${bucket}`);
console.log(`[INFO] initialising S3 test bucket: ${bucket}`);
let initialised = false;
for (let i = 0; i < 5; i++) {
if (await initMinioBucket(minioEndpoint, accessKey, secretKey, bucket)) {
@@ -555,7 +569,7 @@ export async function startMinio(
await sleep(2000);
}
if (!initialised) {
throw new Error(`Could not initialise MinIO bucket after retries: ${bucket}`);
throw new Error(`Could not initialise S3 bucket after retries: ${bucket}`);
}
await waitForMinioBucket(minioEndpoint, accessKey, secretKey, bucket);
@@ -60,6 +60,32 @@ export async function runScenario(remoteType: RemoteType, encrypt: boolean): Pro
}
try {
if (remoteType === "MINIO") {
// The shared S3 fixture also serves the browser and real Obsidian tests.
const origin = "app://obsidian.md";
const requestedHeaders = ["authorization", "content-type", "x-amz-date", "x-amz-content-sha256"];
const preflight = await fetch(`${minioEndpoint}/${minioBucket}`, {
method: "OPTIONS",
headers: {
Origin: origin,
"Access-Control-Request-Method": "PUT",
"Access-Control-Request-Headers": requestedHeaders.join(","),
},
});
await preflight.body?.cancel();
assert(preflight.ok, "The S3 fixture must accept browser preflight requests");
const allowedOrigin = preflight.headers.get("access-control-allow-origin");
assert(allowedOrigin === "*" || allowedOrigin === origin, "The S3 fixture must allow the Obsidian origin");
const allowedHeaders = (preflight.headers.get("access-control-allow-headers") ?? "")
.toLowerCase()
.split(",")
.map((header) => header.trim());
assert(allowedHeaders.includes("authorization"), "S3 CORS must explicitly allow the Authorization header");
assert(
preflight.headers.get("access-control-allow-methods")?.split(/,\s*/).includes("PUT"),
"S3 CORS must allow browser uploads"
);
}
await initSettingsFile(settingsA);
await initSettingsFile(settingsB);
await applyRemoteSyncSettings(settingsA, {
+4 -3
View File
@@ -99,11 +99,12 @@ This file corresponds to settings helpers in `test-helpers.sh`.
### `helpers/docker.ts`
- Starts, stops, and initialises CouchDB directly from Deno.
- Starts, stops, and initialises CouchDB and RustFS directly from Deno.
- Configures CouchDB via `fetch + retry`.
- Initialises S3 buckets using the RustFS `rc` client, including CORS for signed browser requests.
- Starts and stops the P2P relay through the same Docker runner.
Both CouchDB and P2P relay flows are bash-independent.
These flows do not require Bash on the host. The S3 matrix tasks, environment variables, and container name retain their existing `minio` names for compatibility; RustFS provides the test backend. The RustFS server and `rc` client images are pinned by version and digest.
### `helpers/backgroundCli.ts`
@@ -328,7 +329,7 @@ The GitHub Actions workflow `.github/workflows/cli-deno-tests.yml` runs automati
## Current limitations
- MinIO startup and matrix coverage are ported. Current limits are elsewhere, not setup URI generation.
- S3 startup and matrix coverage use RustFS. Current limits are elsewhere, not setup URI generation.
---
+21 -44
View File
@@ -1,47 +1,24 @@
#!/bin/bash
set -e
cat >/tmp/mybucket-rw.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetBucketLocation","s3:ListBucket"],
"Resource": ["arn:aws:s3:::$bucketName"]
},
{
"Effect": "Allow",
"Action": ["s3:GetObject","s3:PutObject","s3:DeleteObject"],
"Resource": ["arn:aws:s3:::$bucketName/*"]
}
]
}
EOF
# echo "<CORSConfiguration>
# <CORSRule>
# <AllowedOrigin>http://localhost:63315</AllowedOrigin>
# <AllowedOrigin>http://localhost:63316</AllowedOrigin>
# <AllowedOrigin>http://localhost</AllowedOrigin>
# <AllowedMethod>GET</AllowedMethod>
# <AllowedMethod>PUT</AllowedMethod>
# <AllowedMethod>POST</AllowedMethod>
# <AllowedMethod>DELETE</AllowedMethod>
# <AllowedMethod>HEAD</AllowedMethod>
# <AllowedHeader>*</AllowedHeader>
# </CORSRule>
# </CORSConfiguration>" > /tmp/cors.xml
# docker run --rm --network host -v /tmp/mybucket-rw.json:/tmp/mybucket-rw.json --entrypoint=/bin/sh minio/mc -c "
# mc alias set myminio $minioEndpoint $username $password
# mc mb --ignore-existing myminio/$bucketName
# mc admin policy create myminio my-custom-policy /tmp/mybucket-rw.json
# echo 'Creating service account for user $username with access key $accessKey'
# mc admin user svcacct add --access-key '$accessKey' --secret-key '$secretKey' myminio '$username'
# mc admin policy attach myminio my-custom-policy --user '$accessKey'
# echo 'Verifying policy and user creation:'
# mc admin user svcacct info myminio '$accessKey'
# "
docker run --rm --network host -v /tmp/mybucket-rw.json:/tmp/mybucket-rw.json --entrypoint=/bin/sh minio/mc -c "
mc alias set myminio $minioEndpoint $accessKey $secretKey
mc mb --ignore-existing myminio/$bucketName
"
docker run --rm --network host --entrypoint=/bin/sh \
rustfs/rc:v0.1.35@sha256:adb45b56539006120f1d790bcc17ee5f9b4d93c1d7e71ed0a24f10267f9d6914 \
-c 'set -e
rc alias set myminio "$1" "$2" "$3"
rc mb --ignore-existing "myminio/$4"
rc cors set "myminio/$4" - <<CORS
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<AllowedHeader>authorization</AllowedHeader>
<ExposeHeader>ETag</ExposeHeader>
</CORSRule>
</CORSConfiguration>
CORS
' sh "$minioEndpoint" "$accessKey" "$secretKey" "$bucketName"
+7 -1
View File
@@ -1,2 +1,8 @@
#!/bin/bash
docker run -d --name minio-test -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=$accessKey -e MINIO_ROOT_PASSWORD=$secretKey -e MINIO_SERVER_URL=$minioEndpoint minio/minio server /data --console-address ':9001'
docker run -d --name minio-test \
-p 9000:9000 -p 9001:9001 \
-e "RUSTFS_ACCESS_KEY=$accessKey" \
-e "RUSTFS_SECRET_KEY=$secretKey" \
-e "RUSTFS_CONSOLE_ENABLE=true" \
-e 'RUSTFS_CORS_ALLOWED_ORIGINS=*' \
rustfs/rustfs:1.0.0-rc.6@sha256:97171b3d72cd47dc81000f92ea84de25608bfc35a94c965501afaeb5d99f6035 /data
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/bash
docker stop minio-test
docker rm minio-test
docker rm -v minio-test
+2 -2
View File
@@ -125,7 +125,7 @@ The mobile pass uses Obsidian's `app.emulateMobile(true)`, a 390 by 844 CSS-pixe
`test:e2e:obsidian:p2p-pane` starts one configured CouchDB-only session with no P2P profile and separate configured P2P sessions for desktop and mobile. It proves that the command remains registered while the retired command, automatic pane, and ribbon entry without a P2P configuration are absent. For the configured P2P profiles, it verifies that the desktop ribbon is available, the current status command reaches the pane without it opening at start-up, checks its connection control and horizontal layout, and captures unobstructed desktop and mobile screenshots. The mobile session uses a fresh Vault, profile, and Obsidian process, enters `app.emulateMobile(true)` through `lifecycle.beforePluginStart`, and requires the P2P view to belong to the right drawer rather than inheriting desktop workspace state. It deliberately uses no relay or peer: replacement of the active replicator is covered by focused unit tests, the Deno and Compose CLI P2P lifecycle suite covers the headless transport, and `p2p-setup-uri-workflow` owns the visible transfer path between two real Obsidian sessions.
`test:e2e:obsidian:local-suite` builds the plug-in and, unless `LIVESYNC_CLI_COMMAND` selects an external CLI, the local LiveSync CLI. It then runs discovery, smoke, the onboarding invitation, Svelte dialogue mounting, revision repair, settings UI, the Review Harness, the P2P status pane, Vault reflection, CouchDB upload and manual setup, CLI-to-Obsidian synchronisation, Object Storage upload and Setup URI round-trip, P2P Setup URI round-trip, startup scan, provisioned CouchDB Setup URI, two-vault synchronisation, Hidden File Sync, Customisation Sync, and setting Markdown export in sequence. Start the local CouchDB, MinIO, and P2P relay fixtures before running it, or use `test:e2e:obsidian:local-suite:services` to let the wrapper stop leftover fixtures, start fresh fixtures, and stop them again after the run.
`test:e2e:obsidian:local-suite` builds the plug-in and, unless `LIVESYNC_CLI_COMMAND` selects an external CLI, the local LiveSync CLI. It then runs discovery, smoke, the onboarding invitation, Svelte dialogue mounting, revision repair, settings UI, the Review Harness, the P2P status pane, Vault reflection, CouchDB upload and manual setup, CLI-to-Obsidian synchronisation, Object Storage upload and Setup URI round-trip, P2P Setup URI round-trip, startup scan, provisioned CouchDB Setup URI, two-vault synchronisation, Hidden File Sync, Customisation Sync, and setting Markdown export in sequence. Start the local CouchDB, RustFS, and P2P relay fixtures before running it, or use `test:e2e:obsidian:local-suite:services` to let the wrapper stop leftover fixtures, start fresh fixtures, and stop them again after the run.
`test:e2e:obsidian:couchdb-upload` reuses the CouchDB variables from `.test.env` or the process environment. It expects a reachable CouchDB service, creates a unique database, starts from configured plug-in data without the device-local compatibility marker, and verifies the copied-or-restored Vault explanation in the actual compatibility dialogue. It captures the summary and details, resumes explicitly, confirms that the marker was recorded, creates a note in real Obsidian, commits the note into the local database, runs one-shot synchronisation, and verifies that the remote database contains both the metadata document and its chunk documents.
@@ -160,7 +160,7 @@ LIVESYNC_CLI_COMMAND="docker run --rm --network host --user $(id -u):$(id -g) --
`test:e2e:obsidian:minio-upload` reuses the Object Storage variables from `.test.env` or the process environment. It expects a reachable S3-compatible service and starts with isolated Object Storage settings and the device-local compatibility acknowledgement already in place, keeping the scenario focused on upload rather than unconfigured start-up or setup. It confirms those settings through `obsidian-cli eval`, creates a note in real Obsidian, runs one-shot Journal Sync, and verifies through the AWS SDK that objects were written under a unique bucket prefix. Adapter tests separately observe an in-progress SDK command, while this real-runtime workflow verifies the resulting request counters advance and rebalance.
`test:e2e:obsidian:object-storage-setup-uri-workflow` uses the public Commonlib-backed tool to generate the initial Setup URI for a unique MinIO prefix, completes visible initialisation on the first device, and then asks that working real Obsidian device to create a new Setup URI through the registered command. A second real Obsidian device imports only the device-generated URI. The workflow verifies the A-to-B note through explicit replication, then verifies that the B-to-A note arrives through `syncOnStart` after restarting the first device, without requesting manual replication. It captures the documented onboarding choices, and removes the Object Storage prefix only after both sessions have stopped.
`test:e2e:obsidian:object-storage-setup-uri-workflow` uses the public Commonlib-backed tool to generate the initial Setup URI for a unique Object Storage prefix, completes visible initialisation on the first device, and then asks that working real Obsidian device to create a new Setup URI through the registered command. A second real Obsidian device imports only the device-generated URI. The workflow verifies the A-to-B note through explicit replication, then verifies that the B-to-A note arrives through `syncOnStart` after restarting the first device, without requesting manual replication. It captures the documented onboarding choices, and removes the Object Storage prefix only after both sessions have stopped.
`test:e2e:obsidian:p2p-setup-uri-workflow` runs two concurrent isolated real Obsidian sessions against the local Compose Nostr relay fixture. The first device imports a generated initial Setup URI and completes its signalling test with zero peers, creates a Setup URI for the second device through the registered command, and remains online while the second device imports it. The second device must select the expected online source before Fetch can rebuild its local database. The workflow accepts each connection request visibly on the receiving device, verifies the initial A-to-B fetch, checks that the menu for the three persistent per-peer actions remains within the viewport, reconnects both P2P sessions in join order, and verifies the B-to-A return journey. Every started session remains tracked until teardown completes.
+21 -44
View File
@@ -1,47 +1,24 @@
#!/bin/bash
set -e
cat >/tmp/mybucket-rw.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetBucketLocation","s3:ListBucket"],
"Resource": ["arn:aws:s3:::$bucketName"]
},
{
"Effect": "Allow",
"Action": ["s3:GetObject","s3:PutObject","s3:DeleteObject"],
"Resource": ["arn:aws:s3:::$bucketName/*"]
}
]
}
EOF
# echo "<CORSConfiguration>
# <CORSRule>
# <AllowedOrigin>http://localhost:63315</AllowedOrigin>
# <AllowedOrigin>http://localhost:63316</AllowedOrigin>
# <AllowedOrigin>http://localhost</AllowedOrigin>
# <AllowedMethod>GET</AllowedMethod>
# <AllowedMethod>PUT</AllowedMethod>
# <AllowedMethod>POST</AllowedMethod>
# <AllowedMethod>DELETE</AllowedMethod>
# <AllowedMethod>HEAD</AllowedMethod>
# <AllowedHeader>*</AllowedHeader>
# </CORSRule>
# </CORSConfiguration>" > /tmp/cors.xml
# docker run --rm --network host -v /tmp/mybucket-rw.json:/tmp/mybucket-rw.json --entrypoint=/bin/sh minio/mc -c "
# mc alias set myminio $minioEndpoint $username $password
# mc mb --ignore-existing myminio/$bucketName
# mc admin policy create myminio my-custom-policy /tmp/mybucket-rw.json
# echo 'Creating service account for user $username with access key $accessKey'
# mc admin user svcacct add --access-key '$accessKey' --secret-key '$secretKey' myminio '$username'
# mc admin policy attach myminio my-custom-policy --user '$accessKey'
# echo 'Verifying policy and user creation:'
# mc admin user svcacct info myminio '$accessKey'
# "
docker run --rm --network host -v /tmp/mybucket-rw.json:/tmp/mybucket-rw.json --entrypoint=/bin/sh minio/mc -c "
mc alias set myminio $minioEndpoint $accessKey $secretKey
mc mb --ignore-existing myminio/$bucketName
"
docker run --rm --network host --entrypoint=/bin/sh \
rustfs/rc:v0.1.35@sha256:adb45b56539006120f1d790bcc17ee5f9b4d93c1d7e71ed0a24f10267f9d6914 \
-c 'set -e
rc alias set myminio "$1" "$2" "$3"
rc mb --ignore-existing "myminio/$4"
rc cors set "myminio/$4" - <<CORS
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<AllowedHeader>authorization</AllowedHeader>
<ExposeHeader>ETag</ExposeHeader>
</CORSRule>
</CORSConfiguration>
CORS
' sh "$minioEndpoint" "$accessKey" "$secretKey" "$bucketName"
+7 -1
View File
@@ -1,2 +1,8 @@
#!/bin/bash
docker run -d --name minio-test -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=$accessKey -e MINIO_ROOT_PASSWORD=$secretKey -e MINIO_SERVER_URL=$minioEndpoint minio/minio server /data --console-address ':9001'
docker run -d --name minio-test \
-p 9000:9000 -p 9001:9001 \
-e "RUSTFS_ACCESS_KEY=$accessKey" \
-e "RUSTFS_SECRET_KEY=$secretKey" \
-e "RUSTFS_CONSOLE_ENABLE=true" \
-e 'RUSTFS_CORS_ALLOWED_ORIGINS=*' \
rustfs/rustfs:1.0.0-rc.6@sha256:97171b3d72cd47dc81000f92ea84de25608bfc35a94c965501afaeb5d99f6035 /data
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/bash
docker stop minio-test
docker rm minio-test
docker rm -v minio-test