初始化蓝鸟文件快递柜源码与部署文档

This commit is contained in:
lhc committed 2026-10-05 23:41:07 +08:00
commit 5643d22242
70 files changed
+18669

No files matched your search

+109
View File
@@ -0,0 +1,109 @@
"""Verify the native release in an isolated directory on the workspace filesystem."""
import http.cookiejar
import json
import os
from pathlib import Path
import secrets
import shutil
import socket
import sqlite3
import subprocess
import tarfile
import tempfile
import time
import urllib.request
project = Path(__file__).resolve().parent.parent
stage = Path(tempfile.mkdtemp(prefix=".bluebird-smoke-", dir=project))
server = None
try:
with tarfile.open(project / "build/bluebird-linux-amd64.tar.gz") as archive:
archive.extractall(stage, filter="data")
with socket.socket() as sock:
sock.bind(("127.0.0.1", 0))
port = sock.getsockname()[1]
base = f"http://127.0.0.1:{port}"
config = stage / "config.toml"
source = (config.read_text().replace("127.0.0.1:8080", f"127.0.0.1:{port}")
.replace("http://localhost:8080", base)
.replace("min_free_bytes = 1073741824", "min_free_bytes = 0")
.replace("encryption = false", "encryption = true"))
config.write_text(source)
binary = str(stage / "bluebird")
password = secrets.token_urlsafe(24)
env = os.environ.copy()
env["BLUEBIRD_ADMIN_PASSWORD"] = password
subprocess.run([binary, "init", "--config", str(config)], env=env, check=True,
capture_output=True, timeout=15)
server = subprocess.Popen([binary, "serve", "--config", str(config)],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
opener = urllib.request.build_opener(
urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
def call(method, path, body=None, raw=False):
headers = {}
if body is not None:
if not raw:
body = json.dumps(body).encode()
headers = {"Origin": base, "Content-Type":
"application/octet-stream" if raw else "application/json"}
request = urllib.request.Request(base + "/api/v1" + path, data=body,
headers=headers, method=method)
with opener.open(request, timeout=10) as response:
return json.loads(response.read())
for _ in range(50):
try:
assert call("GET", "/health")["ready"]
break
except (OSError, AssertionError):
time.sleep(.1)
else:
raise AssertionError("Release server did not start")
with opener.open(base + "/", timeout=10) as response:
assert b'<div id="app">' in response.read()
call("GET", "/policy")
payload = b"bluebird-release-smoke\n" * 4096
parcel = call("POST", "/uploads", {
"files": [{"name": "first.dat", "size": len(payload)},
{"name": "same.dat", "size": len(payload)}],
"days": 7, "downloads": 2, "renew": True, "password": ""})
for file in parcel["files"]:
call("PUT", f"/uploads/{parcel['id']}/files/{file['id']}", payload, True)
share = call("POST", f"/uploads/{parcel['id']}/publish", {})
call("POST", "/pickup/resolve", {"code": share["code"]})
request = urllib.request.Request(
base + f"/api/v1/pickup/files/{parcel['files'][0]['id']}/download")
with opener.open(request, timeout=10) as response:
assert response.read() == payload
call("POST", "/admin/login", {"username": "admin", "password": password})
stats = call("GET", "/admin/stats")
assert stats["objects"] == 1 and stats["files"] == 2
server.terminate()
server.wait(timeout=10)
server = None
subprocess.run([binary, "check", "--config", str(config)], check=True,
capture_output=True, timeout=15)
backup = stage / "backup.tar.gz"
subprocess.run([binary, "backup", "--config", str(config), "--output", str(backup)],
check=True, capture_output=True, timeout=15)
restored = stage / "restore.toml"
restored.write_text(source.replace('data_dir = "var"', 'data_dir = "restored-var"'))
subprocess.run([binary, "restore", "--config", str(restored), "--input", str(backup)],
check=True, capture_output=True, timeout=15)
subprocess.run([binary, "check", "--config", str(restored)], check=True,
capture_output=True, timeout=15)
with sqlite3.connect(stage / "restored-var/db/bluebird.db") as db:
assert db.execute("SELECT state,code_hash FROM parcels").fetchone() == ("restored", None)
assert db.execute("SELECT count(*) FROM grants").fetchone()[0] == 0
assert db.execute("SELECT count(*) FROM objects").fetchone()[0] == 1
print("发布包验证通过:初始化、内嵌前端、匿名去重、加密下载、管理、检查、备份恢复。")
finally:
if server is not None:
server.terminate()
try:
server.wait(timeout=10)
except subprocess.TimeoutExpired:
server.kill()
server.wait()
shutil.rmtree(stage)