Files
s3-csi/cmd/s3-mount/main.go
T
e8b89e78c3 chore: no seaweed, no weed — it is s3 (#4)
* fix(docker): clone the fork that exists, at a commit that exists

The s3-mount image has never built. A global rename turned the upstream
seaweedfs reference into `github.com/s3/s3`, which is not a repository, so the
build died on `git clone ... exit code 128` before compiling anything.

Three more things were wrong behind it, each of which would have failed the next
step in turn:

  clone   github.com/s3/s3        -> github.com/hanzoai/s3
  path    /go/src/github.com/s3/s3 -> /go/src/github.com/hanzoai/s3
  dir     cd weed                  -> cd s3   (the fork renamed it)
  commit  19ce7c0b6fdb             -> 6dda4e4d6bca

That commit is the real one. 19ce7c0b6fdb is an UPSTREAM seaweedfs hash and does
not exist in our fork — the API 422s on it — so the checkout could never have
succeeded even with the URL fixed. The ARG stays so a build can still pin.

SEAWEEDFS_COMMIT is renamed S3_COMMIT while we are here; nothing consumed it yet.

* chore: no seaweed, no weed — it is s3

369 occurrences across 33 files, plus nine files whose names carried it. All of
it gone: manifests, helm chart, nomad jobs, workflows, docs and code.

Two of these were not cosmetic.

The driver spawned a binary called "weed":

    DefaultWeedBinary = "weed"

Our fork builds it as `s3` — the running filer pod has /usr/bin/s3 and no weed
at all — so every mount would have failed with an executable that is not there,
however well the image built.

And the crash-recovery integration test killed processes matching `pgrep -x
weed`. Nothing is named that any more, so it would have found no pids, killed
nothing, and passed while testing exactly nothing. It now matches `s3`. The test
already had a guard that fails when there is nothing to kill, which is the only
reason this would have been noticed at all.

The rest follows the same rename the Dockerfile got: SEAWEEDFS_COMMIT is
S3_COMMIT, and the release/sync workflows that patch that ARG were updated with
it or they would silently stop pinning anything.

No upstream import paths were touched — go.mod depends on github.com/hanzoai/s3,
not on anything upstream, so nothing here was load-bearing for the build.
Verified: go build clean, all three test packages pass.

---------

Co-authored-by: hanzo-dev <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 18:26:50 -07:00

119 lines
3.0 KiB
Go

package main
import (
"context"
"encoding/json"
"errors"
"flag"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/hanzoai/s3-csi/pkg/mountmanager"
"github.com/hanzoai/s3/s3/glog"
)
var (
endpoint = flag.String("endpoint", "unix:///tmp/s3-mount.sock", "endpoint the mount service listens on")
s3Binary = flag.String("s3Binary", mountmanager.DefaultS3Binary, "path to the s3 binary")
)
func main() {
flag.Parse()
scheme, address, err := mountmanager.ParseEndpoint(*endpoint)
if err != nil {
glog.Fatalf("invalid endpoint: %v", err)
}
if scheme != "unix" {
glog.Fatalf("unsupported endpoint scheme: %s", scheme)
}
if err := os.Remove(address); err != nil && !errors.Is(err, os.ErrNotExist) {
glog.Fatalf("removing existing socket: %v", err)
}
listener, err := net.Listen("unix", address)
if err != nil {
glog.Fatalf("failed to listen on %s: %v", address, err)
}
defer func() {
_ = listener.Close()
_ = os.Remove(address)
}()
manager := mountmanager.NewManager(mountmanager.Config{S3Binary: *s3Binary})
mux := http.NewServeMux()
mux.HandleFunc("/mount", makePostHandler(manager.Mount))
mux.HandleFunc("/unmount", makePostHandler(manager.Unmount))
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
})
server := &http.Server{Handler: mux}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
go func() {
if err := server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
glog.Fatalf("server error: %v", err)
}
}()
glog.Infof("mount service listening on %s", *endpoint)
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(shutdownCtx); err != nil {
glog.Errorf("server shutdown error: %v", err)
}
glog.Infof("mount service stopped")
}
func writeJSON(w http.ResponseWriter, status int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if err := json.NewEncoder(w).Encode(data); err != nil {
glog.Errorf("writing response failed: %v", err)
}
}
func writeError(w http.ResponseWriter, status int, message string) {
writeJSON(w, status, mountmanager.ErrorResponse{Error: message})
}
// makePostHandler creates a generic HTTP POST handler that decodes JSON request,
// calls the manager function, and encodes the JSON response.
func makePostHandler[Req any, Resp any](managerFunc func(*Req) (*Resp, error)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
var req Req
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid request: "+err.Error())
return
}
resp, err := managerFunc(&req)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, http.StatusOK, resp)
}
}