mirror of
https://github.com/tuna/tunasync.git
synced 2026-07-03 12:28:07 +08:00
Merge pull request #221 from tuna/go-1.25
Bump toolchain, CI and dependencies
This commit is contained in:
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -14,11 +14,11 @@ jobs:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '^1.23'
|
||||
go-version-file: go.mod
|
||||
id: go
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
tar -cz --numeric-owner --owner root --group root -f tunasync-${TAG}-$i-bin.tar.gz -C build-$i tunasync tunasynctl
|
||||
done
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
|
||||
26
.github/workflows/tunasync.yml
vendored
26
.github/workflows/tunasync.yml
vendored
@@ -15,12 +15,12 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '^1.23'
|
||||
go-version-file: go.mod
|
||||
id: go
|
||||
|
||||
- name: Get dependencies
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
make tunasynctl
|
||||
|
||||
- name: Keep artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: tunasync-bin
|
||||
path: build-linux-amd64/
|
||||
@@ -53,15 +53,15 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cgroup-tools
|
||||
docker pull alpine:3.8
|
||||
docker pull alpine:3.23
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '^1.22'
|
||||
go-version-file: go.mod
|
||||
id: go
|
||||
|
||||
- name: Run Unit tests.
|
||||
@@ -88,17 +88,17 @@ jobs:
|
||||
(TESTREEXEC="$case" TERM=xterm-256color exec -a "$argv0" ./worker.test -test.v=true -test.coverprofile "profile5_$case.gcov" -test.run TestReexec -- "$@")
|
||||
}
|
||||
run_test_reexec 1 tunasync-exec __dummy__
|
||||
run_test_reexec 2 tunasync-exec /tmp/dummy_exec
|
||||
run_test_reexec 2 tunasync-exec /tmp/dummy_exec 3< /dev/null
|
||||
run_test_reexec 3 tunasync-exec /tmp/dummy_exec 3< <(echo -n "abrt")
|
||||
run_test_reexec 4 tunasync-exec /tmp/dummy_exec 3< <(echo -n "cont")
|
||||
run_test_reexec 5 tunasync-exec2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
with:
|
||||
driver-opts: network=host
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
if: github.event_name == 'push'
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
@@ -125,7 +125,7 @@ jobs:
|
||||
mkdir -p /tmp/.buildx-cache
|
||||
|
||||
- name: Build Docker image for uml rootfs
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .umlrootfs
|
||||
file: .umlrootfs/Dockerfile
|
||||
|
||||
3
Makefile
3
Makefile
@@ -17,7 +17,8 @@ $(BUILDBIN:%=build-$(ARCH)/%) : build-$(ARCH)/% : cmd/%
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 go build -o $@ -ldflags ${LDFLAGS} github.com/tuna/tunasync/$<
|
||||
|
||||
test:
|
||||
go test -v -covermode=count -coverprofile=profile.gcov ./...
|
||||
# see: https://stackoverflow.com/questions/79780882/go-no-such-tool-covdata-in-go-1-25
|
||||
GOTOOLCHAIN=go1.26.2+auto go test -v -covermode=count -coverprofile=profile.gcov ./...
|
||||
|
||||
build-test-worker:
|
||||
CGO_ENABLED=0 go test -c -covermode=count github.com/tuna/tunasync/worker
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/moby/sys/reexec"
|
||||
"github.com/pkg/profile"
|
||||
"github.com/urfave/cli"
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
tunasync "github.com/tuna/tunasync/internal"
|
||||
"github.com/tuna/tunasync/manager"
|
||||
@@ -24,7 +23,7 @@ var (
|
||||
githash = "No githash provided"
|
||||
)
|
||||
|
||||
var logger = logging.MustGetLogger("tunasync")
|
||||
var logger = tunasync.MustGetLogger("tunasync")
|
||||
|
||||
func startManager(c *cli.Context) error {
|
||||
tunasync.InitLogger(c.Bool("verbose"), c.Bool("debug"), c.Bool("with-systemd"))
|
||||
@@ -140,54 +139,56 @@ func main() {
|
||||
app.Usage = "tunasync mirror job management tool"
|
||||
app.EnableBashCompletion = true
|
||||
app.Version = tunasync.Version
|
||||
app.Commands = []cli.Command{
|
||||
app.Commands = []*cli.Command{
|
||||
{
|
||||
Name: "manager",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "start the tunasync manager",
|
||||
Action: startManager,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Usage: "Load manager configurations from `FILE`",
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Load manager configurations from `FILE`",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "addr",
|
||||
Usage: "The manager will listen on `ADDR`",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "The manager will bind to `PORT`",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "cert",
|
||||
Usage: "Use SSL certificate from `FILE`",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "key",
|
||||
Usage: "Use SSL key from `FILE`",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "db-file",
|
||||
Usage: "Use `FILE` as the database file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "db-type",
|
||||
Usage: "Use database type `TYPE`",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "verbose, v",
|
||||
Usage: "Enable verbose logging",
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Enable verbose logging",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Run manager in debug mode",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "with-systemd",
|
||||
Usage: "Enable systemd-compatible logging",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "pidfile",
|
||||
Value: "/run/tunasync/tunasync.manager.pid",
|
||||
Usage: "The pid file of the manager process",
|
||||
@@ -200,28 +201,30 @@ func main() {
|
||||
Usage: "start the tunasync worker",
|
||||
Action: startWorker,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Usage: "Load worker configurations from `FILE`",
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Load worker configurations from `FILE`",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "verbose, v",
|
||||
Usage: "Enable verbose logging",
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Enable verbose logging",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Run worker in debug mode",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "with-systemd",
|
||||
Usage: "Enable systemd-compatible logging",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "pidfile",
|
||||
Value: "/run/tunasync/tunasync.worker.pid",
|
||||
Usage: "The pid file of the worker process",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "prof-path",
|
||||
Value: "",
|
||||
Usage: "Go profiling file path",
|
||||
|
||||
@@ -12,8 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/urfave/cli"
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
tunasync "github.com/tuna/tunasync/internal"
|
||||
)
|
||||
@@ -33,7 +32,7 @@ const (
|
||||
userCfgFile = "$HOME/.config/tunasync/ctl.conf" // user-specific conf
|
||||
)
|
||||
|
||||
var logger = logging.MustGetLogger("tunasynctl")
|
||||
var logger = tunasync.MustGetLogger("tunasynctl")
|
||||
|
||||
var baseURL string
|
||||
var client *http.Client
|
||||
@@ -42,7 +41,7 @@ func initializeWrapper(handler cli.ActionFunc) cli.ActionFunc {
|
||||
return func(c *cli.Context) error {
|
||||
err := initialize(c)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err.Error(), 1)
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
return handler(c)
|
||||
}
|
||||
@@ -83,7 +82,7 @@ func initialize(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
logger.Debug("user config file: %s", os.ExpandEnv(userCfgFile))
|
||||
logger.Debugf("user config file: %s", os.ExpandEnv(userCfgFile))
|
||||
if _, err := os.Stat(os.ExpandEnv(userCfgFile)); err == nil {
|
||||
err = loadConfig(os.ExpandEnv(userCfgFile), cfg)
|
||||
if err != nil {
|
||||
@@ -134,14 +133,14 @@ func listWorkers(c *cli.Context) error {
|
||||
var workers []tunasync.WorkerStatus
|
||||
_, err := tunasync.GetJSON(baseURL+listWorkersPath, &workers, client)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Filed to correctly get informations from"+
|
||||
"manager server: %s", err.Error()), 1)
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(workers, "", " ")
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Error printing out informations: %s",
|
||||
err.Error()),
|
||||
1)
|
||||
@@ -156,7 +155,7 @@ func listJobs(c *cli.Context) error {
|
||||
var jobs []tunasync.WebMirrorStatus
|
||||
_, err := tunasync.GetJSON(baseURL+listJobsPath, &jobs, client)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to correctly get information "+
|
||||
"of all jobs from manager server: %s", err.Error()),
|
||||
1)
|
||||
@@ -168,7 +167,7 @@ func listJobs(c *cli.Context) error {
|
||||
var status tunasync.SyncStatus
|
||||
err = status.UnmarshalJSON([]byte("\"" + strings.TrimSpace(s) + "\""))
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Error parsing status: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
@@ -188,9 +187,9 @@ func listJobs(c *cli.Context) error {
|
||||
}
|
||||
} else {
|
||||
var jobs []tunasync.MirrorStatus
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Usage Error: jobs command need at"+
|
||||
" least one arguments or \"--all\" flag."), 1)
|
||||
}
|
||||
@@ -210,7 +209,7 @@ func listJobs(c *cli.Context) error {
|
||||
for range args {
|
||||
job := <-ans
|
||||
if job == nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to correctly get information "+
|
||||
"of jobs from at least one manager"),
|
||||
1)
|
||||
@@ -224,7 +223,7 @@ func listJobs(c *cli.Context) error {
|
||||
tpl := template.New("")
|
||||
_, err := tpl.Parse(format)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Error parsing format template: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
@@ -233,7 +232,7 @@ func listJobs(c *cli.Context) error {
|
||||
for _, job := range jobs {
|
||||
err = tpl.Execute(os.Stdout, job)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Error printing out information: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
@@ -243,7 +242,7 @@ func listJobs(c *cli.Context) error {
|
||||
for _, job := range jobs {
|
||||
err = tpl.Execute(os.Stdout, job)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Error printing out information: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
@@ -253,7 +252,7 @@ func listJobs(c *cli.Context) error {
|
||||
} else {
|
||||
b, err := json.MarshalIndent(genericJobs, "", " ")
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Error printing out information: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
@@ -264,13 +263,13 @@ func listJobs(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func updateMirrorSize(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) != 2 {
|
||||
return cli.NewExitError("Usage: tunasynctl set-size -w <worker-id> <mirror> <size>", 1)
|
||||
return cli.Exit("Usage: tunasynctl set-size -w <worker-id> <mirror> <size>", 1)
|
||||
}
|
||||
workerID := c.String("worker")
|
||||
mirrorID := args.Get(0)
|
||||
mirrorSize := args.Get(1)
|
||||
mirrorID := args[0]
|
||||
mirrorSize := args[1]
|
||||
|
||||
msg := struct {
|
||||
Name string `json:"name"`
|
||||
@@ -286,7 +285,7 @@ func updateMirrorSize(c *cli.Context) error {
|
||||
|
||||
resp, err := tunasync.PostJSON(url, msg, client)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to send request to manager: %s",
|
||||
err.Error()),
|
||||
1)
|
||||
@@ -294,7 +293,7 @@ func updateMirrorSize(c *cli.Context) error {
|
||||
defer resp.Body.Close()
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Manager failed to update mirror size: %s", body), 1,
|
||||
)
|
||||
}
|
||||
@@ -302,7 +301,7 @@ func updateMirrorSize(c *cli.Context) error {
|
||||
var status tunasync.MirrorStatus
|
||||
json.Unmarshal(body, &status)
|
||||
if status.Size != mirrorSize {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf(
|
||||
"Mirror size error, expecting %s, manager returned %s",
|
||||
mirrorSize, status.Size,
|
||||
@@ -315,13 +314,13 @@ func updateMirrorSize(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func removeWorker(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) != 0 {
|
||||
return cli.NewExitError("Usage: tunasynctl -w <worker-id>", 1)
|
||||
return cli.Exit("Usage: tunasynctl -w <worker-id>", 1)
|
||||
}
|
||||
workerID := c.String("worker")
|
||||
if len(workerID) == 0 {
|
||||
return cli.NewExitError("Please specify the <worker-id>", 1)
|
||||
return cli.Exit("Please specify the <worker-id>", 1)
|
||||
}
|
||||
url := fmt.Sprintf("%s/workers/%s", baseURL, workerID)
|
||||
|
||||
@@ -332,7 +331,7 @@ func removeWorker(c *cli.Context) error {
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to send request to manager: %s", err.Error()), 1)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
@@ -340,12 +339,12 @@ func removeWorker(c *cli.Context) error {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
|
||||
return cli.NewExitError(fmt.Sprintf("Failed to correctly send"+
|
||||
return cli.Exit(fmt.Sprintf("Failed to correctly send"+
|
||||
" command: HTTP status code is not 200: %s", body),
|
||||
1)
|
||||
}
|
||||
@@ -355,7 +354,7 @@ func removeWorker(c *cli.Context) error {
|
||||
if res["message"] == "deleted" {
|
||||
fmt.Println("Successfully removed the worker")
|
||||
} else {
|
||||
return cli.NewExitError("Failed to remove the worker", 1)
|
||||
return cli.Exit("Failed to remove the worker", 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -368,7 +367,7 @@ func flushDisabledJobs(c *cli.Context) error {
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to send request to manager: %s",
|
||||
err.Error()),
|
||||
1)
|
||||
@@ -378,12 +377,12 @@ func flushDisabledJobs(c *cli.Context) error {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
|
||||
return cli.NewExitError(fmt.Sprintf("Failed to correctly send"+
|
||||
return cli.Exit(fmt.Sprintf("Failed to correctly send"+
|
||||
" command: HTTP status code is not 200: %s", body),
|
||||
1)
|
||||
}
|
||||
@@ -396,15 +395,16 @@ func cmdJob(cmd tunasync.CmdVerb) cli.ActionFunc {
|
||||
return func(c *cli.Context) error {
|
||||
var mirrorID string
|
||||
var argsList []string
|
||||
if len(c.Args()) == 1 {
|
||||
mirrorID = c.Args()[0]
|
||||
} else if len(c.Args()) == 2 {
|
||||
mirrorID = c.Args()[0]
|
||||
for _, arg := range strings.Split(c.Args()[1], ",") {
|
||||
args := c.Args().Slice()
|
||||
if len(args) == 1 {
|
||||
mirrorID = args[0]
|
||||
} else if len(args) == 2 {
|
||||
mirrorID = args[0]
|
||||
for _, arg := range strings.Split(args[1], ",") {
|
||||
argsList = append(argsList, strings.TrimSpace(arg))
|
||||
}
|
||||
} else {
|
||||
return cli.NewExitError("Usage Error: cmd command receive just "+
|
||||
return cli.Exit("Usage Error: cmd command receive just "+
|
||||
"1 required positional argument MIRROR and 1 optional "+
|
||||
"argument WORKER", 1)
|
||||
}
|
||||
@@ -422,7 +422,7 @@ func cmdJob(cmd tunasync.CmdVerb) cli.ActionFunc {
|
||||
}
|
||||
resp, err := tunasync.PostJSON(baseURL+cmdPath, cmd, client)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to correctly send command: %s",
|
||||
err.Error()),
|
||||
1)
|
||||
@@ -432,12 +432,12 @@ func cmdJob(cmd tunasync.CmdVerb) cli.ActionFunc {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
|
||||
return cli.NewExitError(fmt.Sprintf("Failed to correctly send"+
|
||||
return cli.Exit(fmt.Sprintf("Failed to correctly send"+
|
||||
" command: HTTP status code is not 200: %s", body),
|
||||
1)
|
||||
}
|
||||
@@ -451,7 +451,7 @@ func cmdWorker(cmd tunasync.CmdVerb) cli.ActionFunc {
|
||||
return func(c *cli.Context) error {
|
||||
|
||||
if c.String("worker") == "" {
|
||||
return cli.NewExitError("Please specify the worker with -w <worker-id>", 1)
|
||||
return cli.Exit("Please specify the worker with -w <worker-id>", 1)
|
||||
}
|
||||
|
||||
cmd := tunasync.ClientCmd{
|
||||
@@ -460,7 +460,7 @@ func cmdWorker(cmd tunasync.CmdVerb) cli.ActionFunc {
|
||||
}
|
||||
resp, err := tunasync.PostJSON(baseURL+cmdPath, cmd, client)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to correctly send command: %s",
|
||||
err.Error()),
|
||||
1)
|
||||
@@ -470,12 +470,12 @@ func cmdWorker(cmd tunasync.CmdVerb) cli.ActionFunc {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return cli.NewExitError(
|
||||
return cli.Exit(
|
||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||
1)
|
||||
}
|
||||
|
||||
return cli.NewExitError(fmt.Sprintf("Failed to correctly send"+
|
||||
return cli.Exit(fmt.Sprintf("Failed to correctly send"+
|
||||
" command: HTTP status code is not 200: %s", body),
|
||||
1)
|
||||
}
|
||||
@@ -514,62 +514,71 @@ func main() {
|
||||
app.Usage = "control client for tunasync manager"
|
||||
|
||||
commonFlags := []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Read configuration from `FILE` rather than" +
|
||||
" ~/.config/tunasync/ctl.conf and /etc/tunasync/ctl.conf",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "manager, m",
|
||||
Usage: "The manager server address",
|
||||
&cli.StringFlag{
|
||||
Name: "manager",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "The manager server address",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "port, p",
|
||||
Usage: "The manager server port",
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "The manager server port",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "ca-cert",
|
||||
Usage: "Trust root CA cert file `CERT`",
|
||||
},
|
||||
|
||||
cli.BoolFlag{
|
||||
Name: "verbose, v",
|
||||
Usage: "Enable verbosely logging",
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Enable verbosely logging",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Enable debugging logging",
|
||||
},
|
||||
}
|
||||
cmdFlags := []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "worker, w",
|
||||
Usage: "Send the command to `WORKER`",
|
||||
&cli.StringFlag{
|
||||
Name: "worker",
|
||||
Aliases: []string{"w"},
|
||||
Usage: "Send the command to `WORKER`",
|
||||
},
|
||||
}
|
||||
|
||||
forceStartFlag := cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Override the concurrent limit",
|
||||
forceStartFlag := &cli.BoolFlag{
|
||||
Name: "force",
|
||||
Aliases: []string{"f"},
|
||||
Usage: "Override the concurrent limit",
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
app.Commands = []*cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "List jobs of workers",
|
||||
Flags: append(commonFlags,
|
||||
[]cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "List all jobs of all workers",
|
||||
&cli.BoolFlag{
|
||||
Name: "all",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "List all jobs of all workers",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "status, s",
|
||||
Usage: "Filter output based on status provided",
|
||||
&cli.StringFlag{
|
||||
Name: "status",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Filter output based on status provided",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "Pretty-print containers using a Go template",
|
||||
&cli.StringFlag{
|
||||
Name: "format",
|
||||
Aliases: []string{"f"},
|
||||
Usage: "Pretty-print containers using a Go template",
|
||||
},
|
||||
}...),
|
||||
Action: initializeWrapper(listJobs),
|
||||
@@ -591,9 +600,10 @@ func main() {
|
||||
Usage: "Remove a worker",
|
||||
Flags: append(
|
||||
commonFlags,
|
||||
cli.StringFlag{
|
||||
Name: "worker, w",
|
||||
Usage: "worker-id of the worker to be removed",
|
||||
&cli.StringFlag{
|
||||
Name: "worker",
|
||||
Aliases: []string{"w"},
|
||||
Usage: "worker-id of the worker to be removed",
|
||||
},
|
||||
),
|
||||
Action: initializeWrapper(removeWorker),
|
||||
@@ -603,9 +613,10 @@ func main() {
|
||||
Usage: "Set mirror size",
|
||||
Flags: append(
|
||||
commonFlags,
|
||||
cli.StringFlag{
|
||||
Name: "worker, w",
|
||||
Usage: "specify worker-id of the mirror job",
|
||||
&cli.StringFlag{
|
||||
Name: "worker",
|
||||
Aliases: []string{"w"},
|
||||
Usage: "specify worker-id of the mirror job",
|
||||
},
|
||||
),
|
||||
Action: initializeWrapper(updateMirrorSize),
|
||||
|
||||
116
go.mod
116
go.mod
@@ -1,89 +1,89 @@
|
||||
module github.com/tuna/tunasync
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.5
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible
|
||||
dario.cat/mergo v1.0.2
|
||||
github.com/BurntSushi/toml v1.6.0
|
||||
github.com/alicebob/miniredis/v2 v2.37.0
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe
|
||||
github.com/containerd/cgroups/v3 v3.0.5
|
||||
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4
|
||||
github.com/codeskyblue/go-sh v0.0.0-20250509230738-c29da582b0f5
|
||||
github.com/containerd/cgroups/v3 v3.1.3
|
||||
github.com/dennwc/btrfs v0.0.0-20260222081608-edfb8b9e4f55
|
||||
github.com/dgraph-io/badger/v4 v4.9.1
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/imdario/mergo v0.3.16
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/moby/sys/reexec v0.1.0
|
||||
github.com/opencontainers/runtime-spec v1.2.1
|
||||
github.com/opencontainers/runtime-spec v1.3.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/profile v1.7.0
|
||||
github.com/redis/go-redis/v9 v9.18.0
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46
|
||||
github.com/smartystreets/goconvey v1.6.4
|
||||
github.com/smartystreets/goconvey v1.8.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/urfave/cli v1.22.16
|
||||
golang.org/x/sys v0.31.0
|
||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
||||
github.com/urfave/cli/v2 v2.27.7
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
golang.org/x/sys v0.43.0
|
||||
)
|
||||
|
||||
replace github.com/boltdb/bolt v1.3.1 => go.etcd.io/bbolt v1.3.11
|
||||
|
||||
require (
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
|
||||
github.com/bytedance/sonic v1.12.9 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/bytedance/gopkg v0.1.4 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cilium/ebpf v0.17.3 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/cilium/ebpf v0.21.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/dennwc/ioctl v1.0.0 // indirect
|
||||
github.com/dgraph-io/ristretto v0.2.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/dennwc/ioctl v1.0.1 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/felixge/fgprof v0.9.5 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
|
||||
github.com/gin-contrib/sse v1.1.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.25.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gomodule/redigo v1.8.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.2 // indirect
|
||||
github.com/goccy/go-json v0.10.6 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/godbus/dbus/v5 v5.2.2 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/google/flatbuffers v25.12.19+incompatible // indirect
|
||||
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect
|
||||
github.com/gopherjs/gopherjs v1.20.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/klauspost/compress v1.18.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-isatty v0.0.21 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.3.0 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
github.com/smarty/assertions v1.16.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect
|
||||
go.etcd.io/bbolt v1.4.0 // indirect
|
||||
golang.org/x/arch v0.14.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
|
||||
github.com/yuin/gopher-lua v1.1.2 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
golang.org/x/arch v0.26.0 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
|
||||
331
go.sum
331
go.sum
@@ -1,22 +1,21 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI=
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/alicebob/miniredis/v2 v2.37.0 h1:RheObYW32G1aiJIj81XVt78ZHJpHonHLHW7OLIshq68=
|
||||
github.com/alicebob/miniredis/v2 v2.37.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/bytedance/sonic v1.12.9 h1:Od1BvK55NnewtGaJsTDeAOSnLVO2BTSLOe0+ooKokmQ=
|
||||
github.com/bytedance/sonic v1.12.9/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
|
||||
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM=
|
||||
github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI=
|
||||
github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
@@ -28,108 +27,96 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg=
|
||||
github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cilium/ebpf v0.21.0 h1:4dpx1J/B/1apeTmWBH5BkVLayHTkFrMovVPnHEk+l3k=
|
||||
github.com/cilium/ebpf v0.21.0/go.mod h1:1kHKv6Kvh5a6TePP5vvvoMa1bclRyzUXELSs272fmIQ=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe h1:69JI97HlzP+PH5Mi1thcGlDoBr6PS2Oe+l3mNmAkbs4=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20250509230738-c29da582b0f5 h1:2Q4bAJrPn4r2w2vw5jNg3RyaNkI+r35TDS8l21WlyUI=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20250509230738-c29da582b0f5/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ=
|
||||
github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6 h1:fV+JlCY0cCJh3l0jfE7iB3ZmrdfJSgfcjdrCQhPokGg=
|
||||
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6/go.mod h1:MYsOV9Dgsec3FFSOjywi0QK5r6TeBbdWxdrMGtiYXHA=
|
||||
github.com/dennwc/ioctl v1.0.0 h1:DsWAAjIxRqNcLn9x6mwfuf2pet3iB7aK90K4tF16rLg=
|
||||
github.com/dennwc/ioctl v1.0.0/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk=
|
||||
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
|
||||
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dennwc/btrfs v0.0.0-20260222081608-edfb8b9e4f55 h1:VAnGuI8RNnP8vHqCn8X1O63TexAv+QjMqffBdkLbYKU=
|
||||
github.com/dennwc/btrfs v0.0.0-20260222081608-edfb8b9e4f55/go.mod h1:Kn6RQo4OP1ZEoLB3uldDJabFcf72VgDRInxEqLEo8OE=
|
||||
github.com/dennwc/ioctl v1.0.1-0.20181021180353-017804252068/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
|
||||
github.com/dennwc/ioctl v1.0.1 h1:9iI6o0gbknFAz3GvR/NY1qy0glki6EtU6W3ZtJlpbMc=
|
||||
github.com/dennwc/ioctl v1.0.1/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
|
||||
github.com/dgraph-io/badger/v4 v4.9.1 h1:DocZXZkg5JJHJPtUErA0ibyHxOVUDVoXLSCV6t8NC8w=
|
||||
github.com/dgraph-io/badger/v4 v4.9.1/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0=
|
||||
github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU=
|
||||
github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E=
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38=
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
|
||||
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko=
|
||||
github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s=
|
||||
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
|
||||
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ=
|
||||
github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc=
|
||||
github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s=
|
||||
github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU=
|
||||
github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
|
||||
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
|
||||
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs=
|
||||
github.com/google/flatbuffers v25.12.19+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg=
|
||||
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
|
||||
github.com/gopherjs/gopherjs v1.20.1 h1:22uLWFvVcxhJ+j3dJ99NNfwGyHynxCmjhYsrcwqbY60=
|
||||
github.com/gopherjs/gopherjs v1.20.1/go.mod h1:h+FTmmLgbXMmmtuZFp9bUqXciN429Wx0sJEJuMnpyfM=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
@@ -139,34 +126,24 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
|
||||
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
|
||||
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
github.com/moby/sys/reexec v0.1.0 h1:RrBi8e0EBTLEgfruBOFcxtElzRGTEUkeIFaVXgU7wok=
|
||||
github.com/moby/sys/reexec v0.1.0/go.mod h1:EqjBg8F3X7iZe5pU6nRZnYCMUTXoxsjiIfHup5wYIN8=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
@@ -176,130 +153,112 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
|
||||
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg=
|
||||
github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
|
||||
github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
|
||||
github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/smarty/assertions v1.16.0 h1:EvHNkdRA4QHMrn75NZSoUQ/mAUXAYWfatfB01yTCzfY=
|
||||
github.com/smarty/assertions v1.16.0/go.mod h1:duaaFdCS0K9dnoM50iyek/eYINOZ64gbh1Xlf6LG7AI=
|
||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
|
||||
github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0=
|
||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
|
||||
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yuin/gopher-lua v1.1.2 h1:yF/FjE3hD65tBbt0VXLE13HWS9h34fdzJmrWRXwobGA=
|
||||
github.com/yuin/gopher-lua v1.1.2/go.mod h1:7aRmXIWl37SqRf0koeyylBEzJ+aPt8A+mmkQ4f1ntR8=
|
||||
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
|
||||
golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4=
|
||||
golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE=
|
||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
|
||||
@@ -1,35 +1,281 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// InitLogger initilizes logging format and level
|
||||
func InitLogger(verbose, debug, withSystemd bool) {
|
||||
var fmtString string
|
||||
if withSystemd {
|
||||
fmtString = "[%{level:.6s}] %{message}"
|
||||
} else {
|
||||
if debug {
|
||||
fmtString = "%{color}[%{time:06-01-02 15:04:05}][%{level:.6s}][%{shortfile}]%{color:reset} %{message}"
|
||||
} else {
|
||||
fmtString = "%{color}[%{time:06-01-02 15:04:05}][%{level:.6s}]%{color:reset} %{message}"
|
||||
}
|
||||
}
|
||||
format := logging.MustStringFormatter(fmtString)
|
||||
logging.SetFormatter(format)
|
||||
logging.SetBackend(logging.NewLogBackend(os.Stdout, "", 0))
|
||||
const LevelNotice = slog.Level(2)
|
||||
|
||||
type Logger struct {
|
||||
name string
|
||||
}
|
||||
|
||||
type lineHandler struct {
|
||||
w io.Writer
|
||||
level slog.Leveler
|
||||
addSource bool
|
||||
withSystemd bool
|
||||
attrs []slog.Attr
|
||||
groups []string
|
||||
mu *sync.Mutex
|
||||
}
|
||||
|
||||
var defaultHandler atomic.Value
|
||||
|
||||
func init() {
|
||||
InitLogger(false, false, false)
|
||||
}
|
||||
|
||||
func MustGetLogger(name string) *Logger {
|
||||
return &Logger{name: name}
|
||||
}
|
||||
|
||||
// InitLogger initializes logging format and level.
|
||||
func InitLogger(verbose, debug, withSystemd bool) {
|
||||
level := LevelNotice
|
||||
if debug {
|
||||
logging.SetLevel(logging.DEBUG, "tunasync")
|
||||
logging.SetLevel(logging.DEBUG, "tunasynctl")
|
||||
level = slog.LevelDebug
|
||||
} else if verbose {
|
||||
logging.SetLevel(logging.INFO, "tunasync")
|
||||
logging.SetLevel(logging.INFO, "tunasynctl")
|
||||
} else {
|
||||
logging.SetLevel(logging.NOTICE, "tunasync")
|
||||
logging.SetLevel(logging.NOTICE, "tunasynctl")
|
||||
level = slog.LevelInfo
|
||||
}
|
||||
defaultHandler.Store(slog.Handler(newLineHandler(os.Stdout, level, debug, withSystemd)))
|
||||
}
|
||||
|
||||
func (l *Logger) Debug(args ...any) {
|
||||
l.log(slog.LevelDebug, normalizeArgs(args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Debugf(format string, args ...any) {
|
||||
l.log(slog.LevelDebug, formatMessage(format, args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Info(args ...any) {
|
||||
l.log(slog.LevelInfo, normalizeArgs(args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Infof(format string, args ...any) {
|
||||
l.log(slog.LevelInfo, formatMessage(format, args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Notice(args ...any) {
|
||||
l.log(LevelNotice, normalizeArgs(args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Noticef(format string, args ...any) {
|
||||
l.log(LevelNotice, formatMessage(format, args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Warning(args ...any) {
|
||||
l.log(slog.LevelWarn, normalizeArgs(args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Warningf(format string, args ...any) {
|
||||
l.log(slog.LevelWarn, formatMessage(format, args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Error(args ...any) {
|
||||
l.log(slog.LevelError, normalizeArgs(args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Errorf(format string, args ...any) {
|
||||
l.log(slog.LevelError, formatMessage(format, args...))
|
||||
}
|
||||
|
||||
func (l *Logger) Panic(args ...any) {
|
||||
msg := normalizeArgs(args...)
|
||||
l.log(slog.LevelError, msg)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
func (l *Logger) Panicf(format string, args ...any) {
|
||||
msg := formatMessage(format, args...)
|
||||
l.log(slog.LevelError, msg)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
func (l *Logger) log(level slog.Level, msg string) {
|
||||
handler := currentHandler()
|
||||
ctx := context.Background()
|
||||
if !handler.Enabled(ctx, level) {
|
||||
return
|
||||
}
|
||||
|
||||
var pcs [1]uintptr
|
||||
runtime.Callers(3, pcs[:])
|
||||
|
||||
record := slog.NewRecord(time.Now(), level, msg, pcs[0])
|
||||
_ = handler.Handle(ctx, record)
|
||||
}
|
||||
|
||||
func currentHandler() slog.Handler {
|
||||
if h, ok := defaultHandler.Load().(slog.Handler); ok {
|
||||
return h
|
||||
}
|
||||
return newLineHandler(os.Stdout, LevelNotice, false, false)
|
||||
}
|
||||
|
||||
func newLineHandler(w io.Writer, level slog.Leveler, addSource, withSystemd bool) *lineHandler {
|
||||
return &lineHandler{
|
||||
w: w,
|
||||
level: level,
|
||||
addSource: addSource,
|
||||
withSystemd: withSystemd,
|
||||
mu: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (h *lineHandler) Enabled(_ context.Context, level slog.Level) bool {
|
||||
return level >= h.level.Level()
|
||||
}
|
||||
|
||||
func (h *lineHandler) Handle(_ context.Context, record slog.Record) error {
|
||||
var b strings.Builder
|
||||
|
||||
if h.withSystemd {
|
||||
b.WriteString("[")
|
||||
b.WriteString(levelLabel(record.Level))
|
||||
b.WriteString("] ")
|
||||
} else {
|
||||
b.WriteString("[")
|
||||
b.WriteString(record.Time.Format("06-01-02 15:04:05"))
|
||||
b.WriteString("][")
|
||||
b.WriteString(levelLabel(record.Level))
|
||||
b.WriteString("]")
|
||||
if h.addSource {
|
||||
if src := shortSource(record.PC); src != "" {
|
||||
b.WriteString("[")
|
||||
b.WriteString(src)
|
||||
b.WriteString("]")
|
||||
}
|
||||
}
|
||||
b.WriteString(" ")
|
||||
}
|
||||
|
||||
b.WriteString(record.Message)
|
||||
|
||||
attrs := append([]slog.Attr{}, h.attrs...)
|
||||
record.Attrs(func(attr slog.Attr) bool {
|
||||
attrs = append(attrs, attr)
|
||||
return true
|
||||
})
|
||||
appendAttrs(&b, h.groups, attrs)
|
||||
|
||||
b.WriteByte('\n')
|
||||
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
_, err := io.WriteString(h.w, b.String())
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *lineHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
cloned := *h
|
||||
cloned.attrs = append(append([]slog.Attr{}, h.attrs...), attrs...)
|
||||
return &cloned
|
||||
}
|
||||
|
||||
func (h *lineHandler) WithGroup(name string) slog.Handler {
|
||||
cloned := *h
|
||||
cloned.groups = append(append([]string{}, h.groups...), name)
|
||||
return &cloned
|
||||
}
|
||||
|
||||
func appendAttrs(b *strings.Builder, groups []string, attrs []slog.Attr) {
|
||||
for _, attr := range attrs {
|
||||
attr.Value = attr.Value.Resolve()
|
||||
if attr.Equal(slog.Attr{}) {
|
||||
continue
|
||||
}
|
||||
key := attr.Key
|
||||
if len(groups) > 0 {
|
||||
key = strings.Join(append(append([]string{}, groups...), key), ".")
|
||||
}
|
||||
b.WriteByte(' ')
|
||||
b.WriteString(key)
|
||||
b.WriteByte('=')
|
||||
b.WriteString(attrValue(attr.Value))
|
||||
}
|
||||
}
|
||||
|
||||
func attrValue(v slog.Value) string {
|
||||
switch v.Kind() {
|
||||
case slog.KindString:
|
||||
return strconv.Quote(v.String())
|
||||
case slog.KindBool:
|
||||
return strconv.FormatBool(v.Bool())
|
||||
case slog.KindInt64:
|
||||
return strconv.FormatInt(v.Int64(), 10)
|
||||
case slog.KindUint64:
|
||||
return strconv.FormatUint(v.Uint64(), 10)
|
||||
case slog.KindFloat64:
|
||||
return strconv.FormatFloat(v.Float64(), 'f', -1, 64)
|
||||
case slog.KindDuration:
|
||||
return v.Duration().String()
|
||||
case slog.KindTime:
|
||||
return v.Time().Format(time.RFC3339Nano)
|
||||
case slog.KindAny:
|
||||
return fmt.Sprintf("%v", v.Any())
|
||||
default:
|
||||
return v.String()
|
||||
}
|
||||
}
|
||||
|
||||
func levelLabel(level slog.Level) string {
|
||||
switch {
|
||||
case level <= slog.LevelDebug:
|
||||
return "DEBUG"
|
||||
case level < LevelNotice:
|
||||
return "INFO"
|
||||
case level < slog.LevelWarn:
|
||||
return "NOTICE"
|
||||
case level < slog.LevelError:
|
||||
return "WARN"
|
||||
default:
|
||||
return "ERROR"
|
||||
}
|
||||
}
|
||||
|
||||
func shortSource(pc uintptr) string {
|
||||
if pc == 0 {
|
||||
return ""
|
||||
}
|
||||
frame, _ := runtime.CallersFrames([]uintptr{pc}).Next()
|
||||
if frame.File == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", filepath.Base(frame.File), frame.Line)
|
||||
}
|
||||
|
||||
func normalizeArgs(args ...any) string {
|
||||
if len(args) == 0 {
|
||||
return ""
|
||||
}
|
||||
if format, ok := args[0].(string); ok && len(args) > 1 && strings.Contains(format, "%") {
|
||||
return fmt.Sprintf(format, args[1:]...)
|
||||
}
|
||||
return fmt.Sprint(args...)
|
||||
}
|
||||
|
||||
func formatMessage(format string, args ...any) string {
|
||||
if len(args) == 0 {
|
||||
return format
|
||||
}
|
||||
if strings.Contains(format, "%") {
|
||||
return fmt.Sprintf(format, args...)
|
||||
}
|
||||
items := make([]any, 0, len(args)+1)
|
||||
items = append(items, format)
|
||||
items = append(items, args...)
|
||||
return fmt.Sprint(items...)
|
||||
}
|
||||
|
||||
325
internal/logger_test.go
Normal file
325
internal/logger_test.go
Normal file
@@ -0,0 +1,325 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log/slog"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type lazyString string
|
||||
|
||||
func (l lazyString) LogValue() slog.Value {
|
||||
return slog.StringValue(string(l))
|
||||
}
|
||||
|
||||
func withDefaultHandler(t *testing.T, handler slog.Handler) {
|
||||
t.Helper()
|
||||
|
||||
prev := currentHandler()
|
||||
defaultHandler.Store(handler)
|
||||
t.Cleanup(func() {
|
||||
defaultHandler.Store(prev)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInitLoggerConfiguresHandler(t *testing.T) {
|
||||
prev := currentHandler()
|
||||
t.Cleanup(func() {
|
||||
defaultHandler.Store(prev)
|
||||
})
|
||||
|
||||
InitLogger(false, false, true)
|
||||
h, ok := currentHandler().(*lineHandler)
|
||||
if !ok {
|
||||
t.Fatalf("expected *lineHandler, got %T", currentHandler())
|
||||
}
|
||||
if got := h.level.Level(); got != LevelNotice {
|
||||
t.Fatalf("notice level = %v, want %v", got, LevelNotice)
|
||||
}
|
||||
if !h.withSystemd {
|
||||
t.Fatalf("withSystemd = false, want true")
|
||||
}
|
||||
if h.addSource {
|
||||
t.Fatalf("addSource = true, want false")
|
||||
}
|
||||
|
||||
InitLogger(true, false, false)
|
||||
h = currentHandler().(*lineHandler)
|
||||
if got := h.level.Level(); got != slog.LevelInfo {
|
||||
t.Fatalf("info level = %v, want %v", got, slog.LevelInfo)
|
||||
}
|
||||
if h.withSystemd {
|
||||
t.Fatalf("withSystemd = true, want false")
|
||||
}
|
||||
if h.addSource {
|
||||
t.Fatalf("addSource = true, want false")
|
||||
}
|
||||
|
||||
InitLogger(false, true, false)
|
||||
h = currentHandler().(*lineHandler)
|
||||
if got := h.level.Level(); got != slog.LevelDebug {
|
||||
t.Fatalf("debug level = %v, want %v", got, slog.LevelDebug)
|
||||
}
|
||||
if !h.addSource {
|
||||
t.Fatalf("addSource = false, want true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoggerMethodsWriteExpectedLevels(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
withDefaultHandler(t, newLineHandler(&buf, slog.LevelDebug, false, false))
|
||||
|
||||
logger := MustGetLogger("unit")
|
||||
if logger.name != "unit" {
|
||||
t.Fatalf("logger name = %q, want %q", logger.name, "unit")
|
||||
}
|
||||
|
||||
debugFormat := "debug %s"
|
||||
logger.Debug(debugFormat, "one")
|
||||
logger.Debugf("debugf %d", 2)
|
||||
logger.Info("info")
|
||||
logger.Infof("infof %d", 3)
|
||||
logger.Notice("notice")
|
||||
logger.Noticef("noticef %d", 4)
|
||||
logger.Warning("warning")
|
||||
logger.Warningf("warningf %d", 5)
|
||||
logger.Error("error")
|
||||
logger.Errorf("errorf %d", 6)
|
||||
|
||||
lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
|
||||
if len(lines) != 10 {
|
||||
t.Fatalf("line count = %d, want 10\n%s", len(lines), buf.String())
|
||||
}
|
||||
|
||||
wants := []string{
|
||||
"[DEBUG] debug one",
|
||||
"[DEBUG] debugf 2",
|
||||
"[INFO] info",
|
||||
"[INFO] infof 3",
|
||||
"[NOTICE] notice",
|
||||
"[NOTICE] noticef 4",
|
||||
"[WARN] warning",
|
||||
"[WARN] warningf 5",
|
||||
"[ERROR] error",
|
||||
"[ERROR] errorf 6",
|
||||
}
|
||||
for i, want := range wants {
|
||||
if !strings.Contains(lines[i], want) {
|
||||
t.Fatalf("line %d = %q, want substring %q", i, lines[i], want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoggerRespectsLevelFiltering(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
withDefaultHandler(t, newLineHandler(&buf, slog.LevelInfo, false, false))
|
||||
|
||||
logger := MustGetLogger("unit")
|
||||
logger.Debug("hidden")
|
||||
logger.Info("visible")
|
||||
|
||||
out := buf.String()
|
||||
if strings.Contains(out, "hidden") {
|
||||
t.Fatalf("unexpected debug output: %q", out)
|
||||
}
|
||||
if !strings.Contains(out, "[INFO] visible") {
|
||||
t.Fatalf("missing info output: %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoggerPanicMethods(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
withDefaultHandler(t, newLineHandler(&buf, slog.LevelDebug, false, false))
|
||||
|
||||
logger := MustGetLogger("panic")
|
||||
|
||||
assertPanic := func(name, want string, fn func()) {
|
||||
t.Helper()
|
||||
defer func() {
|
||||
got := recover()
|
||||
if got != want {
|
||||
t.Fatalf("%s panic = %v, want %q", name, got, want)
|
||||
}
|
||||
}()
|
||||
fn()
|
||||
}
|
||||
|
||||
assertPanic("Panic", "boom", func() {
|
||||
logger.Panic("boom")
|
||||
})
|
||||
if !strings.Contains(buf.String(), "[ERROR] boom") {
|
||||
t.Fatalf("panic output missing: %q", buf.String())
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
assertPanic("Panicf", "boom 2", func() {
|
||||
logger.Panicf("boom %d", 2)
|
||||
})
|
||||
if !strings.Contains(buf.String(), "[ERROR] boom 2") {
|
||||
t.Fatalf("panicf output missing: %q", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLineHandlerFormatsAttrsAndSource(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
handler := newLineHandler(&buf, slog.LevelDebug, true, false).
|
||||
WithGroup("grp").
|
||||
WithAttrs([]slog.Attr{
|
||||
slog.String("prefix", "yes"),
|
||||
{},
|
||||
})
|
||||
|
||||
pc, _, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
t.Fatal("runtime.Caller failed")
|
||||
}
|
||||
|
||||
record := slog.NewRecord(
|
||||
time.Date(2024, time.January, 2, 3, 4, 5, 0, time.UTC),
|
||||
LevelNotice,
|
||||
"hello",
|
||||
pc,
|
||||
)
|
||||
record.AddAttrs(
|
||||
slog.String("name", "value"),
|
||||
slog.Bool("ok", true),
|
||||
slog.Int64("n", -3),
|
||||
slog.Uint64("u", 4),
|
||||
slog.Float64("f", 1.5),
|
||||
slog.Duration("d", 2*time.Second),
|
||||
slog.Time("when", time.Date(2024, time.January, 2, 3, 4, 5, 0, time.UTC)),
|
||||
slog.Any("obj", struct{ X int }{X: 7}),
|
||||
slog.Any("lazy", lazyString("resolved")),
|
||||
)
|
||||
|
||||
if !handler.Enabled(context.Background(), LevelNotice) {
|
||||
t.Fatal("handler should be enabled for notice")
|
||||
}
|
||||
if err := handler.Handle(context.Background(), record); err != nil {
|
||||
t.Fatalf("Handle returned error: %v", err)
|
||||
}
|
||||
|
||||
out := buf.String()
|
||||
for _, want := range []string{
|
||||
"[24-01-02 03:04:05][NOTICE][logger_test.go:",
|
||||
" hello",
|
||||
"grp.prefix=\"yes\"",
|
||||
"grp.name=\"value\"",
|
||||
"grp.ok=true",
|
||||
"grp.n=-3",
|
||||
"grp.u=4",
|
||||
"grp.f=1.5",
|
||||
"grp.d=2s",
|
||||
"grp.when=2024-01-02T03:04:05Z",
|
||||
"grp.obj={7}",
|
||||
"grp.lazy=\"resolved\"",
|
||||
} {
|
||||
if !strings.Contains(out, want) {
|
||||
t.Fatalf("output = %q, want substring %q", out, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLineHandlerSystemdFormat(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
handler := newLineHandler(&buf, slog.LevelDebug, false, true)
|
||||
|
||||
record := slog.NewRecord(
|
||||
time.Date(2024, time.January, 2, 3, 4, 5, 0, time.UTC),
|
||||
slog.LevelWarn,
|
||||
"systemd",
|
||||
0,
|
||||
)
|
||||
if err := handler.Handle(context.Background(), record); err != nil {
|
||||
t.Fatalf("Handle returned error: %v", err)
|
||||
}
|
||||
|
||||
out := buf.String()
|
||||
if got, want := out, "[WARN] systemd\n"; got != want {
|
||||
t.Fatalf("systemd output = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoggerHelpers(t *testing.T) {
|
||||
if got := normalizeArgs(); got != "" {
|
||||
t.Fatalf("normalizeArgs() = %q, want empty", got)
|
||||
}
|
||||
format := "value=%d"
|
||||
if got := normalizeArgs(format, 4); got != "value=4" {
|
||||
t.Fatalf("normalizeArgs(format) = %q, want %q", got, "value=4")
|
||||
}
|
||||
if got := normalizeArgs("value", 4); got != "value4" {
|
||||
t.Fatalf("normalizeArgs(sprint) = %q, want %q", got, "value4")
|
||||
}
|
||||
|
||||
if got := formatMessage("plain"); got != "plain" {
|
||||
t.Fatalf("formatMessage(no args) = %q, want %q", got, "plain")
|
||||
}
|
||||
if got := formatMessage(format, 4); got != "value=4" {
|
||||
t.Fatalf("formatMessage(format) = %q, want %q", got, "value=4")
|
||||
}
|
||||
plain := "plain"
|
||||
if got := formatMessage(plain, 4); got != "plain4" {
|
||||
t.Fatalf("formatMessage(sprint) = %q, want %q", got, "plain4")
|
||||
}
|
||||
|
||||
if got := levelLabel(slog.LevelDebug); got != "DEBUG" {
|
||||
t.Fatalf("levelLabel(debug) = %q, want DEBUG", got)
|
||||
}
|
||||
if got := levelLabel(slog.LevelInfo); got != "INFO" {
|
||||
t.Fatalf("levelLabel(info) = %q, want INFO", got)
|
||||
}
|
||||
if got := levelLabel(LevelNotice); got != "NOTICE" {
|
||||
t.Fatalf("levelLabel(notice) = %q, want NOTICE", got)
|
||||
}
|
||||
if got := levelLabel(slog.LevelWarn); got != "WARN" {
|
||||
t.Fatalf("levelLabel(warn) = %q, want WARN", got)
|
||||
}
|
||||
if got := levelLabel(slog.LevelError); got != "ERROR" {
|
||||
t.Fatalf("levelLabel(error) = %q, want ERROR", got)
|
||||
}
|
||||
|
||||
if got := shortSource(0); got != "" {
|
||||
t.Fatalf("shortSource(0) = %q, want empty", got)
|
||||
}
|
||||
pc, _, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
t.Fatal("runtime.Caller failed")
|
||||
}
|
||||
if got := shortSource(pc); !strings.Contains(got, "logger_test.go:") {
|
||||
t.Fatalf("shortSource(pc) = %q, want logger_test.go:*", got)
|
||||
}
|
||||
|
||||
if got := attrValue(slog.StringValue("value")); got != "\"value\"" {
|
||||
t.Fatalf("attrValue(string) = %q, want %q", got, "\"value\"")
|
||||
}
|
||||
if got := attrValue(slog.BoolValue(true)); got != "true" {
|
||||
t.Fatalf("attrValue(bool) = %q, want true", got)
|
||||
}
|
||||
if got := attrValue(slog.Int64Value(-3)); got != "-3" {
|
||||
t.Fatalf("attrValue(int64) = %q, want -3", got)
|
||||
}
|
||||
if got := attrValue(slog.Uint64Value(4)); got != "4" {
|
||||
t.Fatalf("attrValue(uint64) = %q, want 4", got)
|
||||
}
|
||||
if got := attrValue(slog.Float64Value(1.5)); got != "1.5" {
|
||||
t.Fatalf("attrValue(float64) = %q, want 1.5", got)
|
||||
}
|
||||
if got := attrValue(slog.DurationValue(2 * time.Second)); got != "2s" {
|
||||
t.Fatalf("attrValue(duration) = %q, want 2s", got)
|
||||
}
|
||||
if got := attrValue(slog.TimeValue(time.Date(2024, time.January, 2, 3, 4, 5, 0, time.UTC))); got != "2024-01-02T03:04:05Z" {
|
||||
t.Fatalf("attrValue(time) = %q, want RFC3339", got)
|
||||
}
|
||||
if got := attrValue(slog.AnyValue(struct{ X int }{X: 7})); got != "{7}" {
|
||||
t.Fatalf("attrValue(any) = %q, want %q", got, "{7}")
|
||||
}
|
||||
if got := attrValue(slog.GroupValue(slog.Int("x", 1))); !strings.Contains(got, "x=1") {
|
||||
t.Fatalf("attrValue(group) = %q, want substring %q", got, "x=1")
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
tunasync "github.com/tuna/tunasync/internal"
|
||||
)
|
||||
|
||||
var logger = logging.MustGetLogger("tunasync")
|
||||
var logger = tunasync.MustGetLogger("tunasync")
|
||||
|
||||
@@ -2,7 +2,7 @@ package manager
|
||||
|
||||
import (
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// A Config is the top-level toml-serializaible config struct
|
||||
@@ -42,7 +42,7 @@ func LoadConfig(cfgFile string, c *cli.Context) (*Config, error) {
|
||||
|
||||
if cfgFile != "" {
|
||||
if _, err := toml.DecodeFile(cfgFile, cfg); err != nil {
|
||||
logger.Errorf(err.Error())
|
||||
logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func LoadConfig(cfgFile string, c *cli.Context) (*Config, error) {
|
||||
cfg.Files.DBFile = c.String("db-file")
|
||||
}
|
||||
if c.String("db-type") != "" {
|
||||
cfg.Files.DBFile = c.String("db-type")
|
||||
cfg.Files.DBType = c.String("db-type")
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
@@ -46,40 +46,43 @@ func TestConfig(t *testing.T) {
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "addr",
|
||||
},
|
||||
cli.IntFlag{
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "cert",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "key",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "status-file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "db-file",
|
||||
},
|
||||
}
|
||||
Convey("when giving no config options", func() {
|
||||
app.Action = func(c *cli.Context) {
|
||||
app.Action = func(c *cli.Context) error {
|
||||
cfgFile := c.String("config")
|
||||
cfg, err := LoadConfig(cfgFile, c)
|
||||
So(err, ShouldEqual, nil)
|
||||
So(cfg.Server.Addr, ShouldEqual, "127.0.0.1")
|
||||
return nil
|
||||
}
|
||||
args := strings.Split("cmd", " ")
|
||||
app.Run(args)
|
||||
err = app.Run(args)
|
||||
So(err, ShouldEqual, nil)
|
||||
})
|
||||
Convey("when giving config options", func() {
|
||||
app.Action = func(c *cli.Context) {
|
||||
app.Action = func(c *cli.Context) error {
|
||||
cfgFile := c.String("config")
|
||||
So(cfgFile, ShouldEqual, tmpfile.Name())
|
||||
conf, err := LoadConfig(cfgFile, c)
|
||||
@@ -88,14 +91,15 @@ func TestConfig(t *testing.T) {
|
||||
So(conf.Server.Port, ShouldEqual, 5000)
|
||||
So(conf.Files.StatusFile, ShouldEqual, "/tmp/tunasync.json")
|
||||
So(conf.Files.DBFile, ShouldEqual, "/var/lib/tunasync/tunasync.db")
|
||||
|
||||
return nil
|
||||
}
|
||||
cmd := fmt.Sprintf("cmd -c %s", tmpfile.Name())
|
||||
args := strings.Split(cmd, " ")
|
||||
app.Run(args)
|
||||
err = app.Run(args)
|
||||
So(err, ShouldEqual, nil)
|
||||
})
|
||||
Convey("when giving cli options", func() {
|
||||
app.Action = func(c *cli.Context) {
|
||||
app.Action = func(c *cli.Context) error {
|
||||
cfgFile := c.String("config")
|
||||
So(cfgFile, ShouldEqual, "")
|
||||
conf, err := LoadConfig(cfgFile, c)
|
||||
@@ -106,16 +110,17 @@ func TestConfig(t *testing.T) {
|
||||
So(conf.Server.SSLKey, ShouldEqual, "/ssl.key")
|
||||
So(conf.Files.StatusFile, ShouldEqual, "/tunasync.json")
|
||||
So(conf.Files.DBFile, ShouldEqual, "/tunasync.db")
|
||||
|
||||
return nil
|
||||
}
|
||||
args := strings.Split(
|
||||
"cmd --addr=0.0.0.0 --port=5001 --cert=/ssl.cert --key /ssl.key --status-file=/tunasync.json --db-file=/tunasync.db",
|
||||
" ",
|
||||
)
|
||||
app.Run(args)
|
||||
err = app.Run(args)
|
||||
So(err, ShouldEqual, nil)
|
||||
})
|
||||
Convey("when giving both config and cli options", func() {
|
||||
app.Action = func(c *cli.Context) {
|
||||
app.Action = func(c *cli.Context) error {
|
||||
cfgFile := c.String("config")
|
||||
So(cfgFile, ShouldEqual, tmpfile.Name())
|
||||
conf, err := LoadConfig(cfgFile, c)
|
||||
@@ -126,14 +131,15 @@ func TestConfig(t *testing.T) {
|
||||
So(conf.Server.SSLKey, ShouldEqual, "/ssl.key")
|
||||
So(conf.Files.StatusFile, ShouldEqual, "/tunasync.json")
|
||||
So(conf.Files.DBFile, ShouldEqual, "/tunasync.db")
|
||||
|
||||
return nil
|
||||
}
|
||||
cmd := fmt.Sprintf(
|
||||
"cmd -c %s --cert=/ssl.cert --key /ssl.key --status-file=/tunasync.json --db-file=/tunasync.db",
|
||||
tmpfile.Name(),
|
||||
)
|
||||
args := strings.Split(cmd, " ")
|
||||
app.Run(args)
|
||||
err = app.Run(args)
|
||||
So(err, ShouldEqual, nil)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
bolt "github.com/boltdb/bolt"
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
|
||||
. "github.com/tuna/tunasync/internal"
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
// implement kv interface backed by badger
|
||||
|
||||
@@ -3,7 +3,7 @@ package manager
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
bolt "github.com/boltdb/bolt"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// implement kv interface backed by boltdb
|
||||
|
||||
@@ -3,7 +3,7 @@ package manager
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// implement kv interface backed by redis
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis"
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
. "github.com/tuna/tunasync/internal"
|
||||
)
|
||||
|
||||
@@ -121,7 +121,7 @@ func initCgroup(cfg *cgroupConfig) error {
|
||||
for _, p := range procs {
|
||||
if err := wkrMgr.AddProc(p); err != nil {
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring")
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring", p)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -206,7 +206,7 @@ func initCgroup(cfg *cgroupConfig) error {
|
||||
for _, proc := range procs {
|
||||
if err := wkrMgr.Add(proc); err != nil {
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring")
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring", proc.Pid)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -53,8 +53,13 @@ func TestReexec(t *testing.T) {
|
||||
return errors.New("pipe is nil")
|
||||
} else {
|
||||
_, err := pipe.Stat()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
pipe.Close()
|
||||
_, err := pipe.Stat()
|
||||
return err
|
||||
})(), ShouldNotBeNil)
|
||||
So(func() {
|
||||
reexec.Init()
|
||||
@@ -172,7 +177,7 @@ sleep 30
|
||||
daemonPidBytes, err := os.ReadFile(bgPidfile)
|
||||
So(err, ShouldBeNil)
|
||||
daemonPid := strings.Trim(string(daemonPidBytes), " \n")
|
||||
logger.Debug("daemon pid: %s", daemonPid)
|
||||
logger.Debugf("daemon pid: %s", daemonPid)
|
||||
procDir := filepath.Join("/proc", daemonPid)
|
||||
_, err = os.Stat(procDir)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -266,7 +271,7 @@ sleep 30
|
||||
for _, p := range procs {
|
||||
if err := origMgr.AddProc(p); err != nil {
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring")
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring", p)
|
||||
} else {
|
||||
So(err, ShouldBeNil)
|
||||
}
|
||||
@@ -306,7 +311,7 @@ sleep 30
|
||||
for _, proc := range procs {
|
||||
if err := origMgr.Add(proc); err != nil {
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring")
|
||||
logger.Debugf("Write pid %d to sub group failed: process vanished, ignoring", proc.Pid)
|
||||
} else {
|
||||
So(err, ShouldBeNil)
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ func (p *cmdProvider) Run(started chan empty) error {
|
||||
return err
|
||||
}
|
||||
if len(matches) != 0 {
|
||||
logger.Debug("Fail-on-match: %r", matches)
|
||||
logger.Debugf("Fail-on-match: %v", matches)
|
||||
return fmt.Errorf("Fail-on-match regexp found %d matches", len(matches))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package worker
|
||||
// put global variables and types here
|
||||
|
||||
import (
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
tunasync "github.com/tuna/tunasync/internal"
|
||||
)
|
||||
|
||||
type empty struct{}
|
||||
|
||||
const defaultMaxRetry = 2
|
||||
|
||||
var logger = logging.MustGetLogger("tunasync")
|
||||
var logger = tunasync.MustGetLogger("tunasync")
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"dario.cat/mergo"
|
||||
"github.com/BurntSushi/toml"
|
||||
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||
cgv2 "github.com/containerd/cgroups/v3/cgroup2"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/imdario/mergo"
|
||||
)
|
||||
|
||||
type providerEnum uint8
|
||||
@@ -213,20 +213,20 @@ func LoadConfig(cfgFile string) (*Config, error) {
|
||||
|
||||
cfg := new(Config)
|
||||
if _, err := toml.DecodeFile(cfgFile, cfg); err != nil {
|
||||
logger.Errorf(err.Error())
|
||||
logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.Include.IncludeMirrors != "" {
|
||||
includedFiles, err := filepath.Glob(cfg.Include.IncludeMirrors)
|
||||
if err != nil {
|
||||
logger.Errorf(err.Error())
|
||||
logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
for _, f := range includedFiles {
|
||||
var incMirCfg includedMirrorConfig
|
||||
if _, err := toml.DecodeFile(f, &incMirCfg); err != nil {
|
||||
logger.Errorf(err.Error())
|
||||
logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
cfg.MirrorsConf = append(cfg.MirrorsConf, incMirCfg.Mirrors...)
|
||||
|
||||
@@ -22,7 +22,7 @@ func cmdRun(p string, args []string) {
|
||||
logger.Debugf("cmdRun failed %s", err)
|
||||
return
|
||||
}
|
||||
logger.Debugf("cmdRun: ", string(out))
|
||||
logger.Debugf("cmdRun: %s", string(out))
|
||||
}
|
||||
|
||||
func getDockerByName(name string) (string, error) {
|
||||
@@ -74,7 +74,7 @@ sleep 20
|
||||
emptyHook: emptyHook{
|
||||
provider: provider,
|
||||
},
|
||||
image: "alpine:3.8",
|
||||
image: "alpine:3.23",
|
||||
volumes: []string{
|
||||
fmt.Sprintf("%s:%s", cmdScript, "/bin/cmd.sh"),
|
||||
},
|
||||
|
||||
@@ -297,7 +297,7 @@ func TestRsyncProviderWithDocker(t *testing.T) {
|
||||
Upstream: "rsync://rsync.tuna.moe/tuna/",
|
||||
Command: "/bin/myrsync",
|
||||
ExcludeFile: excludeFile,
|
||||
DockerImage: "alpine:3.8",
|
||||
DockerImage: "alpine:3.23",
|
||||
LogDir: tmpDir,
|
||||
MirrorDir: tmpDir,
|
||||
UseIPv6: true,
|
||||
|
||||
@@ -139,7 +139,7 @@ func (p *rsyncProvider) Run(started chan empty) error {
|
||||
if err := p.Wait(); err != nil {
|
||||
code, msg := internal.TranslateRsyncErrorCode(err)
|
||||
if code != 0 {
|
||||
logger.Debug("Rsync exitcode %d (%s)", code, msg)
|
||||
logger.Debugf("Rsync exitcode %d (%s)", code, msg)
|
||||
if p.logFileFd != nil {
|
||||
p.logFileFd.WriteString(msg + "\n")
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ func (c *cmdJob) Start() error {
|
||||
if cg.cgCfg.isUnified {
|
||||
if err := cg.cgMgrV2.AddProc(uint64(pid)); err != nil {
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
logger.Infof("Write pid %d to cgroup failed: process vanished, ignoring")
|
||||
logger.Infof("Write pid %d to cgroup failed: process vanished, ignoring", pid)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -150,7 +150,7 @@ func (c *cmdJob) Start() error {
|
||||
} else {
|
||||
if err := cg.cgMgrV1.Add(cgv1.Process{Pid: pid}); err != nil {
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
logger.Infof("Write pid %d to cgroup failed: process vanished, ignoring")
|
||||
logger.Infof("Write pid %d to cgroup failed: process vanished, ignoring", pid)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func (q *scheduleQueue) Pop() *mirrorJob {
|
||||
job := first.Value().(*mirrorJob)
|
||||
q.list.Delete(first.Key())
|
||||
delete(q.jobs, job.Name())
|
||||
logger.Debug("Popped out job %s @%v", job.Name(), t)
|
||||
logger.Debugf("Popped out job %s @%v", job.Name(), t)
|
||||
return job
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -197,7 +197,7 @@ func (p *twoStageRsyncProvider) Run(started chan empty) error {
|
||||
if err != nil {
|
||||
code, msg := internal.TranslateRsyncErrorCode(err)
|
||||
if code != 0 {
|
||||
logger.Debug("Rsync exitcode %d (%s)", code, msg)
|
||||
logger.Debugf("Rsync exitcode %d (%s)", code, msg)
|
||||
if p.logFileFd != nil {
|
||||
p.logFileFd.WriteString(msg + "\n")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user