test: automate SMB integration
This commit is contained in:
parent
c793785e30
commit
ce23bded90
8 changed files with 112 additions and 49 deletions
|
|
@ -11,7 +11,6 @@ ARTIFACTS_DIR="$SCRIPT_DIR/artifacts/$TARGET_HOST"
|
|||
KNOWN_HOSTS_PATH="$ARTIFACTS_DIR/known_hosts"
|
||||
CONFIG_PATH="$ARTIFACTS_DIR/config.generated.json"
|
||||
|
||||
SMB_PASSWORD_FILE="$ARTIFACTS_DIR/smb-password.txt"
|
||||
SFTP_PASSWORD_FILE="$ARTIFACTS_DIR/sftp-password.txt"
|
||||
|
||||
read_or_create_secret() {
|
||||
|
|
@ -29,16 +28,14 @@ read_or_create_secret() {
|
|||
mkdir -p "$ARTIFACTS_DIR"
|
||||
chmod 700 "$ARTIFACTS_DIR"
|
||||
|
||||
SMB_PASSWORD="$(read_or_create_secret "$SMB_PASSWORD_FILE")"
|
||||
SFTP_PASSWORD="$(read_or_create_secret "$SFTP_PASSWORD_FILE")"
|
||||
|
||||
ssh "$TARGET" bash -s -- "$FIXTURE_UID" "$FIXTURE_GID" "$SMB_PASSWORD" "$SFTP_PASSWORD" <<'REMOTE'
|
||||
ssh "$TARGET" bash -s -- "$FIXTURE_UID" "$FIXTURE_GID" "$SFTP_PASSWORD" <<'REMOTE'
|
||||
set -euo pipefail
|
||||
|
||||
fixture_uid="$1"
|
||||
fixture_gid="$2"
|
||||
smb_password="$3"
|
||||
sftp_password="$4"
|
||||
sftp_password="$3"
|
||||
legacy_sshd_dir="/etc/ssh/zerobyte-backend-integration-legacy"
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
|
@ -49,10 +46,9 @@ write_file() {
|
|||
}
|
||||
|
||||
apt-get update
|
||||
apt-get install -y nfs-kernel-server openssh-server rpcbind samba
|
||||
apt-get install -y nfs-kernel-server openssh-server rpcbind
|
||||
|
||||
id -u zerobyte-sftp >/dev/null 2>&1 || useradd --create-home --home-dir /home/zerobyte-sftp --shell /bin/bash zerobyte-sftp
|
||||
id -u zerobyte-smb >/dev/null 2>&1 || useradd --create-home --home-dir /home/zerobyte-smb --shell /bin/bash zerobyte-smb
|
||||
|
||||
install -d -m 0755 /srv/zerobyte-backend-integration/fixtures/case-a/docs
|
||||
printf 'hello from zerobyte integration\n' >/srv/zerobyte-backend-integration/fixtures/case-a/hello.txt
|
||||
|
|
@ -61,8 +57,6 @@ chown -R "$fixture_uid:$fixture_gid" /srv/zerobyte-backend-integration/fixtures
|
|||
find /srv/zerobyte-backend-integration/fixtures -type d -exec chmod 0755 {} +
|
||||
find /srv/zerobyte-backend-integration/fixtures -type f -exec chmod 0644 {} +
|
||||
|
||||
printf '%s\n%s\n' "$smb_password" "$smb_password" | smbpasswd -a -s zerobyte-smb >/dev/null
|
||||
smbpasswd -e zerobyte-smb >/dev/null
|
||||
printf 'zerobyte-sftp:%s\n' "$sftp_password" | chpasswd
|
||||
passwd -u zerobyte-sftp >/dev/null 2>&1 || true
|
||||
|
||||
|
|
@ -76,15 +70,6 @@ systemctl start rpcbind
|
|||
systemctl start proc-fs-nfsd.mount
|
||||
systemctl restart nfs-kernel-server
|
||||
|
||||
write_file /etc/samba/smb.conf <<'EOF'
|
||||
[zerobyte-backend-integration]
|
||||
path = /srv/zerobyte-backend-integration/fixtures
|
||||
browseable = yes
|
||||
read only = yes
|
||||
guest ok = no
|
||||
valid users = zerobyte-smb
|
||||
EOF
|
||||
|
||||
install -d -m 0700 "$legacy_sshd_dir"
|
||||
if [[ ! -f "$legacy_sshd_dir/ssh_host_rsa_key" ]]; then
|
||||
ssh-keygen -q -t rsa -b 2048 -N "" -f "$legacy_sshd_dir/ssh_host_rsa_key"
|
||||
|
|
@ -139,7 +124,6 @@ EOF
|
|||
systemctl daemon-reload
|
||||
systemctl enable --now zerobyte-backend-integration-legacy-sshd.service
|
||||
|
||||
systemctl restart smbd
|
||||
systemctl restart ssh
|
||||
systemctl restart zerobyte-backend-integration-legacy-sshd.service
|
||||
systemctl is-active --quiet zerobyte-backend-integration-legacy-sshd.service
|
||||
|
|
@ -158,10 +142,9 @@ if ! ssh-keyscan -T 5 -p 2222 "$TARGET_HOST" >>"$KNOWN_HOSTS_PATH" 2>/dev/null;
|
|||
exit 1
|
||||
fi
|
||||
|
||||
INTEGRATION_HOST="$TARGET_HOST" \
|
||||
INTEGRATION_HOST="$TARGET_HOST" \
|
||||
FIXTURE_UID="$FIXTURE_UID" \
|
||||
FIXTURE_GID="$FIXTURE_GID" \
|
||||
SMB_PASSWORD="$SMB_PASSWORD" \
|
||||
SFTP_PASSWORD="$SFTP_PASSWORD" \
|
||||
KNOWN_HOSTS_PATH="$KNOWN_HOSTS_PATH" \
|
||||
CONFIG_PATH="$CONFIG_PATH" \
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ function getRequiredNumberEnv(name: string) {
|
|||
const host = getRequiredEnv("INTEGRATION_HOST");
|
||||
const fixtureUid = getRequiredNumberEnv("FIXTURE_UID");
|
||||
const fixtureGid = getRequiredNumberEnv("FIXTURE_GID");
|
||||
const smbPassword = getRequiredEnv("SMB_PASSWORD");
|
||||
const sftpPassword = getRequiredEnv("SFTP_PASSWORD");
|
||||
const knownHosts = fs.readFileSync(getRequiredEnv("KNOWN_HOSTS_PATH"), "utf8");
|
||||
const configPath = getRequiredEnv("CONFIG_PATH");
|
||||
|
|
@ -25,12 +24,6 @@ const nfsEntries = [
|
|||
{ path: "docs/readme.md", type: "file", uid: fixtureUid, gid: fixtureGid, mode: "0644", text: readmeText },
|
||||
];
|
||||
|
||||
const smbEntries = [
|
||||
{ path: "hello.txt", type: "file", uid: fixtureUid, gid: fixtureGid, mode: "0644", text: fileText },
|
||||
{ path: "docs", type: "directory", uid: fixtureUid, gid: fixtureGid, mode: "1755" },
|
||||
{ path: "docs/readme.md", type: "file", uid: fixtureUid, gid: fixtureGid, mode: "0644", text: readmeText },
|
||||
];
|
||||
|
||||
const contentOnlyEntries = [
|
||||
{ path: "hello.txt", type: "file", text: fileText },
|
||||
{ path: "docs", type: "directory" },
|
||||
|
|
@ -54,23 +47,6 @@ const config = {
|
|||
fixtureRoot: "case-a",
|
||||
expectedEntries: nfsEntries,
|
||||
},
|
||||
{
|
||||
id: "smb-local-repo",
|
||||
volume: {
|
||||
backend: "smb",
|
||||
server: host,
|
||||
share: "zerobyte-backend-integration",
|
||||
username: "zerobyte-smb",
|
||||
password: smbPassword,
|
||||
mapToContainerUidGid: false,
|
||||
vers: "3.0",
|
||||
port: 445,
|
||||
readOnly: true,
|
||||
},
|
||||
repository: { backend: "local", path: "repo-smb" },
|
||||
fixtureRoot: "case-a",
|
||||
expectedEntries: smbEntries,
|
||||
},
|
||||
{
|
||||
id: "sftp-legacy-rsa-hostkey-local-repo",
|
||||
volume: {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,28 @@ services:
|
|||
timeout: 5s
|
||||
retries: 30
|
||||
|
||||
smb:
|
||||
build:
|
||||
context: ./smb
|
||||
environment:
|
||||
SMB_USER: "zerobyte-smb"
|
||||
SMB_PASSWORD: "zerobyte-smb-password"
|
||||
SMB_SHARE: "zerobyte-integration"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"smbclient",
|
||||
"//localhost/zerobyte-integration",
|
||||
"-U",
|
||||
"zerobyte-smb%zerobyte-smb-password",
|
||||
"-c",
|
||||
"get case-a/hello.txt /tmp/zerobyte-smb-healthcheck.txt",
|
||||
]
|
||||
interval: 1s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
|
||||
integration:
|
||||
build:
|
||||
context: ../../../..
|
||||
|
|
@ -72,6 +94,8 @@ services:
|
|||
condition: service_healthy
|
||||
webdav:
|
||||
condition: service_healthy
|
||||
smb:
|
||||
condition: service_healthy
|
||||
cap_add:
|
||||
- SYS_ADMIN
|
||||
devices:
|
||||
|
|
|
|||
10
app/test/integration/infra/smb/Dockerfile
Normal file
10
app/test/integration/infra/smb/Dockerfile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
FROM alpine:3.21
|
||||
|
||||
RUN apk add --no-cache samba samba-common-tools samba-client
|
||||
|
||||
COPY entrypoint.sh /usr/local/bin/zerobyte-smb-entrypoint
|
||||
RUN chmod +x /usr/local/bin/zerobyte-smb-entrypoint
|
||||
|
||||
EXPOSE 445
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/zerobyte-smb-entrypoint"]
|
||||
44
app/test/integration/infra/smb/entrypoint.sh
Normal file
44
app/test/integration/infra/smb/entrypoint.sh
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
SMB_USER="${SMB_USER:-zerobyte-smb}"
|
||||
SMB_PASSWORD="${SMB_PASSWORD:-zerobyte-smb-password}"
|
||||
SMB_SHARE="${SMB_SHARE:-zerobyte-integration}"
|
||||
FIXTURE_ROOT="/srv/zerobyte-integration/fixtures"
|
||||
|
||||
adduser -D -H -s /sbin/nologin "$SMB_USER" 2>/dev/null || true
|
||||
|
||||
install -d -m 0755 "$FIXTURE_ROOT/case-a/docs"
|
||||
printf 'hello from zerobyte integration\n' >"$FIXTURE_ROOT/case-a/hello.txt"
|
||||
printf 'fixture documentation\n' >"$FIXTURE_ROOT/case-a/docs/readme.md"
|
||||
chown -R "$SMB_USER:$SMB_USER" "$FIXTURE_ROOT"
|
||||
find "$FIXTURE_ROOT" -type d -exec chmod 0755 {} +
|
||||
find "$FIXTURE_ROOT" -type f -exec chmod 0644 {} +
|
||||
|
||||
printf '%s\n%s\n' "$SMB_PASSWORD" "$SMB_PASSWORD" | smbpasswd -a -s "$SMB_USER" >/dev/null
|
||||
smbpasswd -e "$SMB_USER" >/dev/null
|
||||
|
||||
cat >/etc/samba/smb.conf <<EOF
|
||||
[global]
|
||||
server role = standalone server
|
||||
server string = Zerobyte Integration SMB
|
||||
map to guest = Never
|
||||
log file = /dev/stdout
|
||||
max log size = 0
|
||||
load printers = no
|
||||
printing = bsd
|
||||
disable spoolss = yes
|
||||
bind interfaces only = yes
|
||||
interfaces = lo eth0
|
||||
smb ports = 445
|
||||
|
||||
[$SMB_SHARE]
|
||||
path = $FIXTURE_ROOT
|
||||
browseable = yes
|
||||
read only = yes
|
||||
guest ok = no
|
||||
valid users = $SMB_USER
|
||||
EOF
|
||||
|
||||
testparm -s >/dev/null
|
||||
exec smbd --foreground --no-process-group --debug-stdout
|
||||
|
|
@ -29,18 +29,18 @@ chmod 644 "$sftp_artifacts_dir/id_ed25519.pub"
|
|||
docker build --progress quiet --target runtime-tools -t "$base_image" "$repo_root" >"$docker_output_log" 2>&1
|
||||
|
||||
exit_code=0
|
||||
"${compose[@]}" up --build --quiet-build --no-color --detach rustfs >>"$docker_output_log" 2>&1 || exit_code=$?
|
||||
"${compose[@]}" up --build --no-color --detach rustfs >>"$docker_output_log" 2>&1 || exit_code=$?
|
||||
|
||||
if [[ "$exit_code" -eq 0 ]]; then
|
||||
"${compose[@]}" up --build --quiet-build --no-color --abort-on-container-exit --exit-code-from rustfs-setup rustfs-setup >>"$docker_output_log" 2>&1 || exit_code=$?
|
||||
"${compose[@]}" up --build --no-color --abort-on-container-exit --exit-code-from rustfs-setup rustfs-setup >>"$docker_output_log" 2>&1 || exit_code=$?
|
||||
fi
|
||||
|
||||
if [[ "$exit_code" -eq 0 ]]; then
|
||||
"${compose[@]}" up --build --quiet-build --no-color --detach --wait sftp webdav >>"$docker_output_log" 2>&1 || exit_code=$?
|
||||
"${compose[@]}" up --build --no-color --detach --wait sftp webdav smb >>"$docker_output_log" 2>&1 || exit_code=$?
|
||||
fi
|
||||
|
||||
if [[ "$exit_code" -eq 0 ]]; then
|
||||
"${compose[@]}" run --rm --no-deps --build --quiet-build integration 2>>"$docker_output_log" || exit_code=$?
|
||||
"${compose[@]}" run --rm --no-deps --build integration 2>>"$docker_output_log" || exit_code=$?
|
||||
fi
|
||||
|
||||
if [[ "$exit_code" -ne 0 ]]; then
|
||||
|
|
|
|||
19
app/test/integration/src/helpers/smb.ts
Normal file
19
app/test/integration/src/helpers/smb.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import type { BackendConfig } from "@zerobyte/contracts/volumes";
|
||||
|
||||
export const SMB_HOST = "smb";
|
||||
export const SMB_PORT = 445;
|
||||
export const SMB_SHARE = "zerobyte-integration";
|
||||
export const SMB_USERNAME = "zerobyte-smb";
|
||||
export const SMB_PASSWORD = "zerobyte-smb-password";
|
||||
|
||||
export const buildSmbVolumeConfig = (): BackendConfig => ({
|
||||
backend: "smb",
|
||||
server: SMB_HOST,
|
||||
share: SMB_SHARE,
|
||||
username: SMB_USERNAME,
|
||||
password: SMB_PASSWORD,
|
||||
mapToContainerUidGid: false,
|
||||
vers: "3.0",
|
||||
port: SMB_PORT,
|
||||
readOnly: true,
|
||||
});
|
||||
|
|
@ -4,6 +4,7 @@ import path from "node:path";
|
|||
import type { RepositoryConfig } from "@zerobyte/core/restic";
|
||||
import { Effect } from "effect";
|
||||
import { expect, test } from "vitest";
|
||||
import { makeSmbBackend } from "../../../../apps/agent/src/volume-host/backends/smb";
|
||||
import { makeSftpBackend } from "../../../../apps/agent/src/volume-host/backends/sftp";
|
||||
import { makeWebdavBackend } from "../../../../apps/agent/src/volume-host/backends/webdav";
|
||||
import type { VolumeBackend } from "../../../../apps/agent/src/volume-host/types";
|
||||
|
|
@ -17,6 +18,7 @@ import {
|
|||
readSftpPrivateKey,
|
||||
scanSftpKnownHosts,
|
||||
} from "./helpers/sftp";
|
||||
import { buildSmbVolumeConfig } from "./helpers/smb";
|
||||
import { buildWebdavVolumeConfig } from "./helpers/webdav";
|
||||
|
||||
type VolumeScenario = {
|
||||
|
|
@ -50,6 +52,11 @@ const scenarios: VolumeScenario[] = [
|
|||
name: "WebDAV volume with local repository",
|
||||
createBackend: async (mountPath) => makeWebdavBackend(buildWebdavVolumeConfig(), mountPath),
|
||||
},
|
||||
{
|
||||
id: "smb-local-repo",
|
||||
name: "SMB volume with local repository",
|
||||
createBackend: async (mountPath) => makeSmbBackend(buildSmbVolumeConfig(), mountPath),
|
||||
},
|
||||
];
|
||||
|
||||
const makeDirectoriesWritable = async (root: string): Promise<void> => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue