mirror of
https://github.com/tuna/tunasync.git
synced 2025-06-13 04:17:00 +00:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
528b799bc4 | ||
|
436386fb73 | ||
|
0933b65144 | ||
|
833027a6a0 | ||
|
a5b72b8c55 | ||
|
033aa60540 | ||
|
d2b3e731bf | ||
|
c01de06ac3 | ||
|
ece3e3d9e3 | ||
|
0a00097301 | ||
|
245a8bfc3f | ||
|
a64557b86d | ||
|
27e4307375 |
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@ -18,13 +18,14 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.22'
|
||||
go-version: '^1.23'
|
||||
id: go
|
||||
- name: Build
|
||||
run: |
|
||||
TAG=$(git describe --tags)
|
||||
for i in linux-amd64 linux-arm64 linux-riscv64 linux-loong64; do
|
||||
make ARCH=$i all
|
||||
tar -cz --numeric-owner --owner root --group root -f tunasync-$i-bin.tar.gz -C build-$i tunasync tunasynctl
|
||||
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
|
||||
|
2
.github/workflows/tunasync.yml
vendored
2
.github/workflows/tunasync.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.22'
|
||||
go-version: '^1.23'
|
||||
id: go
|
||||
|
||||
- name: Get dependencies
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/moby/moby/pkg/reexec"
|
||||
"github.com/moby/sys/reexec"
|
||||
"github.com/pkg/profile"
|
||||
"github.com/urfave/cli"
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
|
39
go.mod
39
go.mod
@ -1,8 +1,8 @@
|
||||
module github.com/tuna/tunasync
|
||||
|
||||
go 1.22.0
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.22.9
|
||||
toolchain go1.23.5
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
@ -17,15 +17,16 @@ require (
|
||||
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/moby/moby v27.4.1+incompatible
|
||||
github.com/opencontainers/runtime-spec v1.2.0
|
||||
github.com/moby/moby v28.0.1+incompatible
|
||||
github.com/moby/sys/reexec v0.1.0
|
||||
github.com/opencontainers/runtime-spec v1.2.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/profile v1.7.0
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46
|
||||
github.com/smartystreets/goconvey v1.6.4
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/urfave/cli v1.22.16
|
||||
golang.org/x/sys v0.29.0
|
||||
golang.org/x/sys v0.30.0
|
||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
||||
)
|
||||
|
||||
@ -33,12 +34,12 @@ 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.7 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.2 // 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/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cilium/ebpf v0.17.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cilium/ebpf v0.17.3 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // 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
|
||||
@ -53,18 +54,18 @@ require (
|
||||
github.com/gin-contrib/sse v1.0.0 // 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.23.0 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // 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-20241210010833-40e02aabc2ad // indirect
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
@ -78,11 +79,11 @@ require (
|
||||
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
|
||||
golang.org/x/arch v0.13.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
google.golang.org/protobuf v1.36.2 // indirect
|
||||
golang.org/x/arch v0.14.0 // indirect
|
||||
golang.org/x/crypto v0.35.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/text v0.22.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
|
||||
)
|
||||
|
37
go.sum
37
go.sum
@ -14,9 +14,13 @@ github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
|
||||
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
|
||||
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.2 h1:jxAJuN9fOot/cyz5Q6dUuMJF5OqQ6+5GfA8FjjQ0R4o=
|
||||
github.com/bytedance/sonic/loader v0.2.2/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
@ -32,8 +36,12 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cilium/ebpf v0.17.1 h1:G8mzU81R2JA1nE5/8SRubzqvBMmAmri2VL8BIZPWvV0=
|
||||
github.com/cilium/ebpf v0.17.1/go.mod h1:vay2FaYSmIlv3r8dNACd4mW/OCaZLJKJOo+IHBvCIO8=
|
||||
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.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
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/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=
|
||||
@ -95,6 +103,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
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=
|
||||
@ -104,6 +114,8 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
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=
|
||||
@ -124,6 +136,8 @@ github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8I
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
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=
|
||||
@ -145,9 +159,13 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
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.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
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=
|
||||
@ -172,6 +190,10 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/moby v27.4.1+incompatible h1:z6detzbcLRt7U+w4ovHV+8oYpJfpHKTmUbFWPG6cudA=
|
||||
github.com/moby/moby v27.4.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||
github.com/moby/moby v28.0.1+incompatible h1:10ejBTwFhM3/9p6pSaKrLyXnx7QzzCmCYHAedOp67cQ=
|
||||
github.com/moby/moby v28.0.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||
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=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -190,6 +212,8 @@ 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.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
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/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=
|
||||
@ -258,18 +282,25 @@ 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.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA=
|
||||
golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
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.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
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.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
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=
|
||||
@ -281,12 +312,18 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
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=
|
||||
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=
|
||||
|
@ -1,4 +1,4 @@
|
||||
package internal
|
||||
|
||||
// Version of the program
|
||||
const Version string = "0.9.1"
|
||||
const Version string = "0.9.3"
|
||||
|
@ -19,9 +19,10 @@ type baseProvider struct {
|
||||
timeout time.Duration
|
||||
isMaster bool
|
||||
|
||||
cmd *cmdJob
|
||||
logFileFd *os.File
|
||||
isRunning atomic.Value
|
||||
cmd *cmdJob
|
||||
logFileFd *os.File
|
||||
isRunning atomic.Value
|
||||
successExitCodes []int
|
||||
|
||||
cgroup *cgroupHook
|
||||
zfs *zfsHook
|
||||
@ -186,3 +187,18 @@ func (p *baseProvider) Terminate() error {
|
||||
func (p *baseProvider) DataSize() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *baseProvider) SetSuccessExitCodes(codes []int) {
|
||||
if codes == nil {
|
||||
p.successExitCodes = []int{}
|
||||
} else {
|
||||
p.successExitCodes = codes
|
||||
}
|
||||
}
|
||||
|
||||
func (p *baseProvider) GetSuccessExitCodes() []int {
|
||||
if p.successExitCodes == nil {
|
||||
return []int{}
|
||||
}
|
||||
return p.successExitCodes
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
cgroups "github.com/containerd/cgroups/v3"
|
||||
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||
cgv2 "github.com/containerd/cgroups/v3/cgroup2"
|
||||
"github.com/moby/moby/pkg/reexec"
|
||||
"github.com/moby/sys/reexec"
|
||||
contspecs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||
cgv2 "github.com/containerd/cgroups/v3/cgroup2"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/moby/moby/pkg/reexec"
|
||||
"github.com/moby/sys/reexec"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
@ -250,7 +250,7 @@ sleep 30
|
||||
if cgcf.Group == "" {
|
||||
wkrg, err := cgv2.NestedGroupPath("")
|
||||
So(err, ShouldBeNil)
|
||||
wkrMgr, err := cgv2.Load(wkrg)
|
||||
wkrMgr, _ := cgv2.Load(wkrg)
|
||||
allCtrls, err := wkrMgr.Controllers()
|
||||
So(err, ShouldBeNil)
|
||||
err = wkrMgr.ToggleControllers(allCtrls, cgv2.Disable)
|
||||
|
@ -58,8 +58,14 @@ type globalConfig struct {
|
||||
Retry int `toml:"retry"`
|
||||
Timeout int `toml:"timeout"`
|
||||
|
||||
// appended to the options generated by rsync_provider, but before mirror-specific options
|
||||
RsyncOptions []string `toml:"rsync_options"`
|
||||
|
||||
ExecOnSuccess []string `toml:"exec_on_success"`
|
||||
ExecOnFailure []string `toml:"exec_on_failure"`
|
||||
|
||||
// merged with mirror-specific options. make sure you know what you are doing!
|
||||
SuccessExitCodes []int `toml:"dangerous_global_success_exit_codes"`
|
||||
}
|
||||
|
||||
type managerConfig struct {
|
||||
@ -162,23 +168,27 @@ type mirrorConfig struct {
|
||||
ExecOnSuccess []string `toml:"exec_on_success"`
|
||||
ExecOnFailure []string `toml:"exec_on_failure"`
|
||||
|
||||
// These two options the global options
|
||||
// These two options are appended to the global options
|
||||
ExecOnSuccessExtra []string `toml:"exec_on_success_extra"`
|
||||
ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
|
||||
|
||||
Command string `toml:"command"`
|
||||
FailOnMatch string `toml:"fail_on_match"`
|
||||
SizePattern string `toml:"size_pattern"`
|
||||
UseIPv6 bool `toml:"use_ipv6"`
|
||||
UseIPv4 bool `toml:"use_ipv4"`
|
||||
ExcludeFile string `toml:"exclude_file"`
|
||||
Username string `toml:"username"`
|
||||
Password string `toml:"password"`
|
||||
RsyncNoTimeo bool `toml:"rsync_no_timeout"`
|
||||
RsyncTimeout int `toml:"rsync_timeout"`
|
||||
RsyncOptions []string `toml:"rsync_options"`
|
||||
RsyncOverride []string `toml:"rsync_override"`
|
||||
Stage1Profile string `toml:"stage1_profile"`
|
||||
// will be merged with global option
|
||||
SuccessExitCodes []int `toml:"success_exit_codes"`
|
||||
|
||||
Command string `toml:"command"`
|
||||
FailOnMatch string `toml:"fail_on_match"`
|
||||
SizePattern string `toml:"size_pattern"`
|
||||
UseIPv6 bool `toml:"use_ipv6"`
|
||||
UseIPv4 bool `toml:"use_ipv4"`
|
||||
ExcludeFile string `toml:"exclude_file"`
|
||||
Username string `toml:"username"`
|
||||
Password string `toml:"password"`
|
||||
RsyncNoTimeo bool `toml:"rsync_no_timeout"`
|
||||
RsyncTimeout int `toml:"rsync_timeout"`
|
||||
RsyncOptions []string `toml:"rsync_options"`
|
||||
RsyncOverride []string `toml:"rsync_override"`
|
||||
RsyncOverrideOnly bool `toml:"rsync_override_only"` // only use provided overridden options if true
|
||||
Stage1Profile string `toml:"stage1_profile"`
|
||||
|
||||
MemoryLimit MemBytes `toml:"memory_limit"`
|
||||
|
||||
|
@ -10,12 +10,12 @@ import (
|
||||
func TestConfigDiff(t *testing.T) {
|
||||
Convey("When old and new configs are equal", t, func() {
|
||||
oldList := []mirrorConfig{
|
||||
mirrorConfig{Name: "debian"},
|
||||
mirrorConfig{Name: "debian-security"},
|
||||
mirrorConfig{Name: "fedora"},
|
||||
mirrorConfig{Name: "archlinux"},
|
||||
mirrorConfig{Name: "AOSP"},
|
||||
mirrorConfig{Name: "ubuntu"},
|
||||
{Name: "debian"},
|
||||
{Name: "debian-security"},
|
||||
{Name: "fedora"},
|
||||
{Name: "archlinux"},
|
||||
{Name: "AOSP"},
|
||||
{Name: "ubuntu"},
|
||||
}
|
||||
newList := make([]mirrorConfig, len(oldList))
|
||||
copy(newList, oldList)
|
||||
@ -25,12 +25,12 @@ func TestConfigDiff(t *testing.T) {
|
||||
})
|
||||
Convey("When old config is empty", t, func() {
|
||||
newList := []mirrorConfig{
|
||||
mirrorConfig{Name: "debian"},
|
||||
mirrorConfig{Name: "debian-security"},
|
||||
mirrorConfig{Name: "fedora"},
|
||||
mirrorConfig{Name: "archlinux"},
|
||||
mirrorConfig{Name: "AOSP"},
|
||||
mirrorConfig{Name: "ubuntu"},
|
||||
{Name: "debian"},
|
||||
{Name: "debian-security"},
|
||||
{Name: "fedora"},
|
||||
{Name: "archlinux"},
|
||||
{Name: "AOSP"},
|
||||
{Name: "ubuntu"},
|
||||
}
|
||||
oldList := make([]mirrorConfig, 0)
|
||||
|
||||
@ -39,12 +39,12 @@ func TestConfigDiff(t *testing.T) {
|
||||
})
|
||||
Convey("When new config is empty", t, func() {
|
||||
oldList := []mirrorConfig{
|
||||
mirrorConfig{Name: "debian"},
|
||||
mirrorConfig{Name: "debian-security"},
|
||||
mirrorConfig{Name: "fedora"},
|
||||
mirrorConfig{Name: "archlinux"},
|
||||
mirrorConfig{Name: "AOSP"},
|
||||
mirrorConfig{Name: "ubuntu"},
|
||||
{Name: "debian"},
|
||||
{Name: "debian-security"},
|
||||
{Name: "fedora"},
|
||||
{Name: "archlinux"},
|
||||
{Name: "AOSP"},
|
||||
{Name: "ubuntu"},
|
||||
}
|
||||
newList := make([]mirrorConfig, 0)
|
||||
|
||||
@ -53,19 +53,19 @@ func TestConfigDiff(t *testing.T) {
|
||||
})
|
||||
Convey("When giving two config lists with different names", t, func() {
|
||||
oldList := []mirrorConfig{
|
||||
mirrorConfig{Name: "debian"},
|
||||
mirrorConfig{Name: "debian-security"},
|
||||
mirrorConfig{Name: "fedora"},
|
||||
mirrorConfig{Name: "archlinux"},
|
||||
mirrorConfig{Name: "AOSP", Env: map[string]string{"REPO": "/usr/bin/repo"}},
|
||||
mirrorConfig{Name: "ubuntu"},
|
||||
{Name: "debian"},
|
||||
{Name: "debian-security"},
|
||||
{Name: "fedora"},
|
||||
{Name: "archlinux"},
|
||||
{Name: "AOSP", Env: map[string]string{"REPO": "/usr/bin/repo"}},
|
||||
{Name: "ubuntu"},
|
||||
}
|
||||
newList := []mirrorConfig{
|
||||
mirrorConfig{Name: "debian"},
|
||||
mirrorConfig{Name: "debian-cd"},
|
||||
mirrorConfig{Name: "archlinuxcn"},
|
||||
mirrorConfig{Name: "AOSP", Env: map[string]string{"REPO": "/usr/local/bin/aosp-repo"}},
|
||||
mirrorConfig{Name: "ubuntu-ports"},
|
||||
{Name: "debian"},
|
||||
{Name: "debian-cd"},
|
||||
{Name: "archlinuxcn"},
|
||||
{Name: "AOSP", Env: map[string]string{"REPO": "/usr/local/bin/aosp-repo"}},
|
||||
{Name: "ubuntu-ports"},
|
||||
}
|
||||
|
||||
difference := diffMirrorConfig(oldList, newList)
|
||||
|
@ -403,4 +403,178 @@ use_ipv6 = true
|
||||
So(rp.WorkingDir(), ShouldEqual, "/data/mirrors/debian-cd")
|
||||
So(p.Timeout(), ShouldEqual, 86400*time.Second)
|
||||
})
|
||||
|
||||
Convey("rsync_override_only should work", t, func() {
|
||||
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||
So(err, ShouldEqual, nil)
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
cfgBlob1 := `
|
||||
[global]
|
||||
name = "test_worker"
|
||||
log_dir = "/var/log/tunasync/{{.Name}}"
|
||||
mirror_dir = "/data/mirrors"
|
||||
concurrent = 10
|
||||
interval = 240
|
||||
retry = 3
|
||||
timeout = 86400
|
||||
|
||||
[manager]
|
||||
api_base = "https://127.0.0.1:5000"
|
||||
token = "some_token"
|
||||
|
||||
[server]
|
||||
hostname = "worker1.example.com"
|
||||
listen_addr = "127.0.0.1"
|
||||
listen_port = 6000
|
||||
ssl_cert = "/etc/tunasync.d/worker1.cert"
|
||||
ssl_key = "/etc/tunasync.d/worker1.key"
|
||||
|
||||
[[mirrors]]
|
||||
name = "foo"
|
||||
provider = "rsync"
|
||||
upstream = "rsync://foo.bar/"
|
||||
interval = 720
|
||||
retry = 2
|
||||
timeout = 3600
|
||||
mirror_dir = "/data/foo"
|
||||
rsync_override = ["--bar", "baz"]
|
||||
rsync_override_only = true
|
||||
`
|
||||
|
||||
err = os.WriteFile(tmpfile.Name(), []byte(cfgBlob1), 0644)
|
||||
So(err, ShouldEqual, nil)
|
||||
defer tmpfile.Close()
|
||||
|
||||
cfg, err := LoadConfig(tmpfile.Name())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
providers := map[string]mirrorProvider{}
|
||||
for _, m := range cfg.Mirrors {
|
||||
p := newMirrorProvider(m, cfg)
|
||||
providers[p.Name()] = p
|
||||
}
|
||||
|
||||
p, ok := providers["foo"].(*rsyncProvider)
|
||||
So(ok, ShouldBeTrue)
|
||||
So(p.options, ShouldResemble, []string{"--bar", "baz"})
|
||||
})
|
||||
|
||||
Convey("rsync global options should work", t, func() {
|
||||
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||
So(err, ShouldEqual, nil)
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
cfgBlob1 := `
|
||||
[global]
|
||||
name = "test_worker"
|
||||
log_dir = "/var/log/tunasync/{{.Name}}"
|
||||
mirror_dir = "/data/mirrors"
|
||||
concurrent = 10
|
||||
interval = 240
|
||||
retry = 3
|
||||
timeout = 86400
|
||||
rsync_options = ["--global"]
|
||||
|
||||
[manager]
|
||||
api_base = "https://127.0.0.1:5000"
|
||||
token = "some_token"
|
||||
|
||||
[server]
|
||||
hostname = "worker1.example.com"
|
||||
listen_addr = "127.0.0.1"
|
||||
listen_port = 6000
|
||||
ssl_cert = "/etc/tunasync.d/worker1.cert"
|
||||
ssl_key = "/etc/tunasync.d/worker1.key"
|
||||
|
||||
[[mirrors]]
|
||||
name = "foo"
|
||||
provider = "rsync"
|
||||
upstream = "rsync://foo.bar/"
|
||||
interval = 720
|
||||
retry = 2
|
||||
timeout = 3600
|
||||
mirror_dir = "/data/foo"
|
||||
rsync_override = ["--override"]
|
||||
rsync_options = ["--local"]
|
||||
`
|
||||
|
||||
err = os.WriteFile(tmpfile.Name(), []byte(cfgBlob1), 0644)
|
||||
So(err, ShouldEqual, nil)
|
||||
defer tmpfile.Close()
|
||||
|
||||
cfg, err := LoadConfig(tmpfile.Name())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
providers := map[string]mirrorProvider{}
|
||||
for _, m := range cfg.Mirrors {
|
||||
p := newMirrorProvider(m, cfg)
|
||||
providers[p.Name()] = p
|
||||
}
|
||||
|
||||
p, ok := providers["foo"].(*rsyncProvider)
|
||||
So(ok, ShouldBeTrue)
|
||||
So(p.options, ShouldResemble, []string{
|
||||
"--override", // from mirror.rsync_override
|
||||
"--timeout=120", // generated by newRsyncProvider
|
||||
"--global", // from global.rsync_options
|
||||
"--local", // from mirror.rsync_options
|
||||
})
|
||||
})
|
||||
|
||||
Convey("success_exit_codes should work globally and per mirror", t, func() {
|
||||
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||
So(err, ShouldEqual, nil)
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
cfgBlob1 := `
|
||||
[global]
|
||||
name = "test_worker"
|
||||
log_dir = "/var/log/tunasync/{{.Name}}"
|
||||
mirror_dir = "/data/mirrors"
|
||||
concurrent = 10
|
||||
interval = 240
|
||||
retry = 3
|
||||
timeout = 86400
|
||||
dangerous_global_success_exit_codes = [10, 20]
|
||||
|
||||
[manager]
|
||||
api_base = "https://127.0.0.1:5000"
|
||||
token = "some_token"
|
||||
|
||||
[server]
|
||||
hostname = "worker1.example.com"
|
||||
listen_addr = "127.0.0.1"
|
||||
listen_port = 6000
|
||||
ssl_cert = "/etc/tunasync.d/worker1.cert"
|
||||
ssl_key = "/etc/tunasync.d/worker1.key"
|
||||
|
||||
[[mirrors]]
|
||||
name = "foo"
|
||||
provider = "rsync"
|
||||
upstream = "rsync://foo.bar/"
|
||||
interval = 720
|
||||
retry = 2
|
||||
timeout = 3600
|
||||
mirror_dir = "/data/foo"
|
||||
success_exit_codes = [30, 40]
|
||||
`
|
||||
|
||||
err = os.WriteFile(tmpfile.Name(), []byte(cfgBlob1), 0644)
|
||||
So(err, ShouldEqual, nil)
|
||||
defer tmpfile.Close()
|
||||
|
||||
cfg, err := LoadConfig(tmpfile.Name())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
providers := map[string]mirrorProvider{}
|
||||
for _, m := range cfg.Mirrors {
|
||||
p := newMirrorProvider(m, cfg)
|
||||
providers[p.Name()] = p
|
||||
}
|
||||
|
||||
p, ok := providers["foo"].(*rsyncProvider)
|
||||
So(ok, ShouldBeTrue)
|
||||
So(p.successExitCodes, ShouldResemble, []int{10, 20, 30, 40})
|
||||
})
|
||||
}
|
||||
|
@ -60,6 +60,10 @@ type mirrorProvider interface {
|
||||
ExitContext() *Context
|
||||
// return context
|
||||
Context() *Context
|
||||
|
||||
// set in newMirrorProvider, used by cmdJob.Wait
|
||||
SetSuccessExitCodes(codes []int)
|
||||
GetSuccessExitCodes() []int
|
||||
}
|
||||
|
||||
// newProvider creates a mirrorProvider instance
|
||||
@ -142,7 +146,9 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider {
|
||||
extraOptions: mirror.RsyncOptions,
|
||||
rsyncNeverTimeout: mirror.RsyncNoTimeo,
|
||||
rsyncTimeoutValue: mirror.RsyncTimeout,
|
||||
globalOptions: cfg.Global.RsyncOptions,
|
||||
overriddenOptions: mirror.RsyncOverride,
|
||||
useOverrideOnly: mirror.RsyncOverrideOnly,
|
||||
rsyncEnv: mirror.Env,
|
||||
workingDir: mirrorDir,
|
||||
logDir: logDir,
|
||||
@ -247,5 +253,17 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider {
|
||||
}
|
||||
addHookFromCmdList(mirror.ExecOnFailureExtra, execOnFailure)
|
||||
|
||||
successExitCodes := []int{}
|
||||
if cfg.Global.SuccessExitCodes != nil {
|
||||
successExitCodes = append(successExitCodes, cfg.Global.SuccessExitCodes...)
|
||||
}
|
||||
if mirror.SuccessExitCodes != nil {
|
||||
successExitCodes = append(successExitCodes, mirror.SuccessExitCodes...)
|
||||
}
|
||||
if len(successExitCodes) > 0 {
|
||||
logger.Infof("Non-zero success exit codes set for mirror %s: %v", mirror.Name, successExitCodes)
|
||||
provider.SetSuccessExitCodes(successExitCodes)
|
||||
}
|
||||
|
||||
return provider
|
||||
}
|
||||
|
@ -552,6 +552,59 @@ sleep 10
|
||||
So(provider.DataSize(), ShouldBeEmpty)
|
||||
})
|
||||
})
|
||||
Convey("Command Provider with successExitCodes should work", t, func(ctx C) {
|
||||
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
So(err, ShouldBeNil)
|
||||
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
||||
tmpFile := filepath.Join(tmpDir, "log_file")
|
||||
|
||||
c := cmdConfig{
|
||||
name: "tuna-cmd",
|
||||
upstreamURL: "http://mirrors.tuna.moe/",
|
||||
command: "bash " + scriptFile,
|
||||
workingDir: tmpDir,
|
||||
logDir: tmpDir,
|
||||
logFile: tmpFile,
|
||||
interval: 600 * time.Second,
|
||||
}
|
||||
|
||||
provider, err := newCmdProvider(c)
|
||||
provider.SetSuccessExitCodes([]int{199, 200})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(provider.Type(), ShouldEqual, provCommand)
|
||||
So(provider.Name(), ShouldEqual, c.name)
|
||||
So(provider.WorkingDir(), ShouldEqual, c.workingDir)
|
||||
So(provider.LogDir(), ShouldEqual, c.logDir)
|
||||
So(provider.LogFile(), ShouldEqual, c.logFile)
|
||||
So(provider.Interval(), ShouldEqual, c.interval)
|
||||
So(provider.GetSuccessExitCodes(), ShouldResemble, []int{199, 200})
|
||||
|
||||
Convey("Command exits with configured successExitCodes", func() {
|
||||
scriptContent := `exit 199`
|
||||
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||
So(err, ShouldBeNil)
|
||||
readedScriptContent, err := os.ReadFile(scriptFile)
|
||||
So(err, ShouldBeNil)
|
||||
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
||||
|
||||
err = provider.Run(make(chan empty, 1))
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Command exits with unknown exit code", func() {
|
||||
scriptContent := `exit 201`
|
||||
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||
So(err, ShouldBeNil)
|
||||
readedScriptContent, err := os.ReadFile(scriptFile)
|
||||
So(err, ShouldBeNil)
|
||||
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
||||
|
||||
err = provider.Run(make(chan empty, 1))
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestTwoStageRsyncProvider(t *testing.T) {
|
||||
|
@ -14,7 +14,9 @@ type rsyncConfig struct {
|
||||
rsyncCmd string
|
||||
upstreamURL, username, password, excludeFile string
|
||||
extraOptions []string
|
||||
globalOptions []string
|
||||
overriddenOptions []string
|
||||
useOverrideOnly bool
|
||||
rsyncNeverTimeout bool
|
||||
rsyncTimeoutValue int
|
||||
rsyncEnv map[string]string
|
||||
@ -75,25 +77,36 @@ func newRsyncProvider(c rsyncConfig) (*rsyncProvider, error) {
|
||||
options = c.overriddenOptions
|
||||
}
|
||||
|
||||
if !c.rsyncNeverTimeout {
|
||||
timeo := 120
|
||||
if c.rsyncTimeoutValue > 0 {
|
||||
timeo = c.rsyncTimeoutValue
|
||||
if c.useOverrideOnly {
|
||||
if c.overriddenOptions == nil {
|
||||
return nil, errors.New("rsync_override_only is set but no rsync_override provided")
|
||||
}
|
||||
// use overridden options only
|
||||
} else {
|
||||
if !c.rsyncNeverTimeout {
|
||||
timeo := 120
|
||||
if c.rsyncTimeoutValue > 0 {
|
||||
timeo = c.rsyncTimeoutValue
|
||||
}
|
||||
options = append(options, fmt.Sprintf("--timeout=%d", timeo))
|
||||
}
|
||||
options = append(options, fmt.Sprintf("--timeout=%d", timeo))
|
||||
}
|
||||
|
||||
if c.useIPv6 {
|
||||
options = append(options, "-6")
|
||||
} else if c.useIPv4 {
|
||||
options = append(options, "-4")
|
||||
}
|
||||
if c.useIPv6 {
|
||||
options = append(options, "-6")
|
||||
} else if c.useIPv4 {
|
||||
options = append(options, "-4")
|
||||
}
|
||||
|
||||
if c.excludeFile != "" {
|
||||
options = append(options, "--exclude-from", c.excludeFile)
|
||||
}
|
||||
if c.extraOptions != nil {
|
||||
options = append(options, c.extraOptions...)
|
||||
if c.excludeFile != "" {
|
||||
options = append(options, "--exclude-from", c.excludeFile)
|
||||
}
|
||||
|
||||
if c.globalOptions != nil {
|
||||
options = append(options, c.globalOptions...)
|
||||
}
|
||||
if c.extraOptions != nil {
|
||||
options = append(options, c.extraOptions...)
|
||||
}
|
||||
}
|
||||
provider.options = options
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@ -12,7 +13,7 @@ import (
|
||||
|
||||
"github.com/codeskyblue/go-sh"
|
||||
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||
"github.com/moby/moby/pkg/reexec"
|
||||
"github.com/moby/sys/reexec"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -171,9 +172,18 @@ func (c *cmdJob) Wait() error {
|
||||
return c.retErr
|
||||
default:
|
||||
err := c.cmd.Wait()
|
||||
c.retErr = err
|
||||
close(c.finished)
|
||||
return err
|
||||
if err != nil {
|
||||
code := err.(*exec.ExitError).ExitCode()
|
||||
allowedCodes := c.provider.GetSuccessExitCodes()
|
||||
if slices.Contains(allowedCodes, code) {
|
||||
// process exited with non-success status
|
||||
logger.Infof("Command %s exited with code %d: treated as success (allowed: %v)", c.cmd.Args, code, allowedCodes)
|
||||
} else {
|
||||
c.retErr = err
|
||||
}
|
||||
}
|
||||
return c.retErr
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ func TestWorker(t *testing.T) {
|
||||
})
|
||||
Convey("with one job", func(ctx C) {
|
||||
workerCfg.Mirrors = []mirrorConfig{
|
||||
mirrorConfig{
|
||||
{
|
||||
Name: "job-ls",
|
||||
Provider: provCommand,
|
||||
Command: "ls",
|
||||
@ -194,17 +194,17 @@ func TestWorker(t *testing.T) {
|
||||
})
|
||||
Convey("with several jobs", func(ctx C) {
|
||||
workerCfg.Mirrors = []mirrorConfig{
|
||||
mirrorConfig{
|
||||
{
|
||||
Name: "job-ls-1",
|
||||
Provider: provCommand,
|
||||
Command: "ls",
|
||||
},
|
||||
mirrorConfig{
|
||||
{
|
||||
Name: "job-fail",
|
||||
Provider: provCommand,
|
||||
Command: "non-existent-command-xxxx",
|
||||
},
|
||||
mirrorConfig{
|
||||
{
|
||||
Name: "job-ls-2",
|
||||
Provider: provCommand,
|
||||
Command: "ls",
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
func TestZFSHook(t *testing.T) {
|
||||
|
||||
Convey("ZFS Hook should work", t, func(ctx C) {
|
||||
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||
tmpDir, _ := os.MkdirTemp("", "tunasync")
|
||||
tmpFile := filepath.Join(tmpDir, "log_file")
|
||||
|
||||
c := cmdConfig{
|
||||
|
Loading…
x
Reference in New Issue
Block a user