mirror of
https://github.com/hanzoai/s3.git
synced 2026-11-03 03:07:41 +00:00
hanzoai/s3 was an AGPL-3.0 MinIO fork whose network-copyleft blocks embedding
and reselling as a managed service. Replace it wholesale with a fork of
SeaweedFS (github.com/seaweedfs/seaweedfs, Apache-2.0, Go) which ships a
built-in S3 gateway + Filer.
- License: AGPL-3.0 -> Apache-2.0 (upstream LICENSE kept verbatim, incl.
"Copyright 2025 Chris Lu"); NOTICE added crediting SeaweedFS. No AGPL/BUSL/
SSPL/GPL or enterprise ("ee") files remain.
- Module: go.mod path set to github.com/hanzoai/s3 with a self-replace
(replace github.com/seaweedfs/seaweedfs => ./) so the ~1800 internal Go files
keep their upstream import paths with zero churn. Internal identifiers and
import paths are intentionally NOT renamed.
- CLI rebrand: the binary is built as `s3` (was `weed`); root usage, per-command
help/usage/flag strings, shell autocomplete program name, and the product name
in CLI output now read "Hanzo S3" / `s3`. Users never see `weed`.
(e.g. `s3 server`, `s3 filer`, `s3 master`, `s3 volume`, `s3 s3`, `s3 mount`.)
- Build: `make` (or `go build -o s3 ./weed`) builds the `s3` binary green;
`cmd/weed-db` and `cmd/weed-sql` also build; `go vet ./weed/command/` clean.
- README/LLM.md rewritten for Hanzo S3; AGENTS.md/CLAUDE.md symlinks preserved.
- Dropped a 33MB prebuilt Mach-O `stress` binary upstream had committed; `.gitignore`
updated to ignore the `s3` build output.
117 lines
5.1 KiB
Go
117 lines
5.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/gorilla/sessions"
|
|
"github.com/seaweedfs/seaweedfs/weed/admin/dash"
|
|
)
|
|
|
|
func TestSetupRoutes_RegistersPluginSchedulerStatesAPI_NoAuth(t *testing.T) {
|
|
router := mux.NewRouter()
|
|
|
|
newRouteTestAdminHandlers().SetupRoutes(router, false, "", "", "", "", true)
|
|
|
|
if !hasRoute(router, http.MethodGet, "/api/plugin/scheduler-states") {
|
|
t.Fatalf("expected GET /api/plugin/scheduler-states to be registered in no-auth mode")
|
|
}
|
|
if !hasRoute(router, http.MethodGet, "/api/plugin/jobs/example/detail") {
|
|
t.Fatalf("expected GET /api/plugin/jobs/:jobId/detail to be registered in no-auth mode")
|
|
}
|
|
if !hasRoute(router, http.MethodPost, "/api/plugin/jobs/example/expire") {
|
|
t.Fatalf("expected POST /api/plugin/jobs/:jobId/expire to be registered in no-auth mode")
|
|
}
|
|
}
|
|
|
|
func TestSetupRoutes_RegistersPluginSchedulerStatesAPI_WithAuth(t *testing.T) {
|
|
router := mux.NewRouter()
|
|
|
|
newRouteTestAdminHandlers().SetupRoutes(router, true, "admin", "password", "", "", true)
|
|
|
|
if !hasRoute(router, http.MethodGet, "/api/plugin/scheduler-states") {
|
|
t.Fatalf("expected GET /api/plugin/scheduler-states to be registered in auth mode")
|
|
}
|
|
if !hasRoute(router, http.MethodGet, "/api/plugin/jobs/example/detail") {
|
|
t.Fatalf("expected GET /api/plugin/jobs/:jobId/detail to be registered in auth mode")
|
|
}
|
|
if !hasRoute(router, http.MethodPost, "/api/plugin/jobs/example/expire") {
|
|
t.Fatalf("expected POST /api/plugin/jobs/:jobId/expire to be registered in auth mode")
|
|
}
|
|
}
|
|
|
|
func TestSetupRoutes_RegistersPluginPages_NoAuth(t *testing.T) {
|
|
router := mux.NewRouter()
|
|
|
|
newRouteTestAdminHandlers().SetupRoutes(router, false, "", "", "", "", true)
|
|
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/configuration")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/queue")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/detection")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/execution")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/monitoring")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default/configuration")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default/queue")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default/detection")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default/execution")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default/monitoring")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/default/workers")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/lifecycle")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/lifecycle/configuration")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/lifecycle/workers")
|
|
}
|
|
|
|
func TestSetupRoutes_RegistersPluginPages_WithAuth(t *testing.T) {
|
|
router := mux.NewRouter()
|
|
|
|
newRouteTestAdminHandlers().SetupRoutes(router, true, "admin", "password", "", "", true)
|
|
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/configuration")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/queue")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/detection")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/execution")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/monitoring")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg/configuration")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg/queue")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg/detection")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg/execution")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg/monitoring")
|
|
assertHasRoute(t, router, http.MethodGet, "/plugin/lanes/iceberg/workers")
|
|
}
|
|
|
|
func newRouteTestAdminHandlers() *AdminHandlers {
|
|
adminServer := &dash.AdminServer{}
|
|
store := sessions.NewCookieStore([]byte("test-session-key"))
|
|
return &AdminHandlers{
|
|
adminServer: adminServer,
|
|
sessionStore: store,
|
|
authHandlers: &AuthHandlers{adminServer: adminServer, sessionStore: store},
|
|
clusterHandlers: &ClusterHandlers{adminServer: adminServer},
|
|
fileBrowserHandlers: &FileBrowserHandlers{adminServer: adminServer},
|
|
userHandlers: &UserHandlers{adminServer: adminServer},
|
|
policyHandlers: &PolicyHandlers{adminServer: adminServer},
|
|
pluginHandlers: &PluginHandlers{adminServer: adminServer},
|
|
mqHandlers: &MessageQueueHandlers{adminServer: adminServer},
|
|
serviceAccountHandlers: &ServiceAccountHandlers{adminServer: adminServer},
|
|
}
|
|
}
|
|
|
|
func hasRoute(router *mux.Router, method string, path string) bool {
|
|
req := httptest.NewRequest(method, path, nil)
|
|
var match mux.RouteMatch
|
|
return router.Match(req, &match)
|
|
}
|
|
|
|
func assertHasRoute(t *testing.T, router *mux.Router, method string, path string) {
|
|
t.Helper()
|
|
if !hasRoute(router, method, path) {
|
|
t.Fatalf("expected %s %s to be registered", method, path)
|
|
}
|
|
}
|