mirror of
https://github.com/tuna/tunasync.git
synced 2025-06-14 13:32:43 +00:00
Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
528b799bc4 | ||
|
436386fb73 | ||
|
0933b65144 | ||
|
833027a6a0 | ||
|
a5b72b8c55 | ||
|
033aa60540 | ||
|
d2b3e731bf | ||
|
c01de06ac3 | ||
|
ece3e3d9e3 | ||
|
0a00097301 | ||
|
245a8bfc3f | ||
|
a64557b86d | ||
|
27e4307375 | ||
|
ad97ef8421 | ||
|
748f276d49 | ||
|
0ebfc58126 | ||
|
ab8d1c2120 | ||
|
559f5705f6 | ||
|
f8d7ea1828 | ||
|
b4ca6f4c1e | ||
|
113df44f19 | ||
|
e903c644f2 | ||
|
181fddb87c | ||
|
a6a03decf0 | ||
|
5fb63e119c | ||
|
95c4d54ee2 | ||
|
ef32197fef | ||
|
99c7ab6b65 | ||
|
ab416f6545 | ||
|
15e87a5f48 | ||
|
3ad551f73d | ||
|
3562907af9 | ||
|
6d50645ddb | ||
|
95ba9586e0 | ||
|
c73becc0f1 | ||
|
6132446bc7 | ||
|
bfcbfe75bc | ||
|
fcb8dd5f3a | ||
|
938f67c7b4 | ||
|
dca04a3220 | ||
|
c45974c0bf | ||
|
755c87761d | ||
|
7bc3e8f193 | ||
|
8ddcc46255 | ||
|
37b15d157a | ||
|
f2b22d059c | ||
|
45099fc7d3 | ||
|
c3b742c2a8 | ||
|
68a3149e8d | ||
|
b372744640 | ||
|
4007bb2e4d | ||
|
bca49abd3c | ||
|
60f92ceebb |
46
.github/workflows/release.yml
vendored
46
.github/workflows/release.yml
vendored
@ -1,46 +1,38 @@
|
|||||||
name: release
|
name: release
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
# Sequence of patterns matched against refs/tags
|
|
||||||
tags:
|
tags:
|
||||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Set up Go 1.13
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.13
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '^1.23'
|
||||||
|
id: go
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
for i in linux-amd64 linux-arm64; do
|
TAG=$(git describe --tags)
|
||||||
|
for i in linux-amd64 linux-arm64 linux-riscv64 linux-loong64; do
|
||||||
make ARCH=$i all
|
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
|
done
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
uses: softprops/action-gh-release@v2
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ github.ref }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
release_name: Release ${{ github.ref }}
|
tag_name: ${{ github.ref_name }}
|
||||||
draft: false
|
name: Release ${{ github.ref_name }}
|
||||||
prerelease: false
|
prerelease: false
|
||||||
- name: Upload Release Assets
|
files: |
|
||||||
env:
|
tunasync-*.tar.gz
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
TAG_NAME: ${{ github.ref }}
|
|
||||||
run: |
|
|
||||||
hub release edit $(find . -type f -name "tunasync-*.tar.gz" -printf "-a %p ") -m "" "${TAG_NAME##*/}"
|
|
||||||
|
99
.github/workflows/tunasync.yml
vendored
99
.github/workflows/tunasync.yml
vendored
@ -1,6 +1,11 @@
|
|||||||
name: tunasync
|
name: tunasync
|
||||||
|
|
||||||
on: [push]
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
@ -9,14 +14,14 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Set up Go 1.16
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.16
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '^1.23'
|
||||||
|
id: go
|
||||||
|
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -29,7 +34,7 @@ jobs:
|
|||||||
make tunasynctl
|
make tunasynctl
|
||||||
|
|
||||||
- name: Keep artifacts
|
- name: Keep artifacts
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: tunasync-bin
|
name: tunasync-bin
|
||||||
path: build-linux-amd64/
|
path: build-linux-amd64/
|
||||||
@ -49,28 +54,30 @@ jobs:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y cgroup-tools
|
sudo apt-get install -y cgroup-tools
|
||||||
docker pull alpine:3.8
|
docker pull alpine:3.8
|
||||||
lssubsys -am
|
|
||||||
sudo cgcreate -a $USER -t $USER -g cpu:tunasync
|
|
||||||
sudo cgcreate -a $USER -t $USER -g memory:tunasync
|
|
||||||
|
|
||||||
- name: Set up Go 1.16
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.16
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '^1.22'
|
||||||
|
id: go
|
||||||
|
|
||||||
- name: Run Unit tests.
|
- name: Run Unit tests.
|
||||||
run: |
|
run: |
|
||||||
go install github.com/wadey/gocovmerge@latest
|
go install github.com/wadey/gocovmerge@latest
|
||||||
TERM=xterm-256color make test
|
sudo systemd-run --service-type=oneshot --uid="$(id --user)" --pipe --wait \
|
||||||
|
--property=Delegate=yes --setenv=USECURCGROUP=1 \
|
||||||
|
--setenv=TERM=xterm-256color --same-dir \
|
||||||
|
make test
|
||||||
|
|
||||||
- name: Run Additional Unit tests.
|
- name: Run Additional Unit tests.
|
||||||
run: |
|
run: |
|
||||||
make build-test-worker
|
make build-test-worker
|
||||||
sudo cgexec -g "*:/" bash -c "echo 0 > /sys/fs/cgroup/systemd/tasks; exec sudo -u $USER env USECURCGROUP=1 TERM=xterm-256color cgexec -g cpu,memory:tunasync ./worker.test -test.v=true -test.coverprofile profile2.cov -test.run TestCgroup"
|
sudo mkdir /sys/fs/cgroup/tunasync
|
||||||
|
sudo ./worker.test -test.v=true -test.coverprofile profile2.gcov -test.run TestCgroup
|
||||||
|
sudo rmdir /sys/fs/cgroup/tunasync
|
||||||
touch /tmp/dummy_exec
|
touch /tmp/dummy_exec
|
||||||
chmod +x /tmp/dummy_exec
|
chmod +x /tmp/dummy_exec
|
||||||
run_test_reexec (){
|
run_test_reexec (){
|
||||||
@ -78,7 +85,7 @@ jobs:
|
|||||||
shift
|
shift
|
||||||
argv0="$1"
|
argv0="$1"
|
||||||
shift
|
shift
|
||||||
(TESTREEXEC="$case" TERM=xterm-256color exec -a "$argv0" ./worker.test -test.v=true -test.coverprofile "profile5_$case.cov" -test.run TestReexec -- "$@")
|
(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 1 tunasync-exec __dummy__
|
||||||
run_test_reexec 2 tunasync-exec /tmp/dummy_exec
|
run_test_reexec 2 tunasync-exec /tmp/dummy_exec
|
||||||
@ -87,11 +94,11 @@ jobs:
|
|||||||
run_test_reexec 5 tunasync-exec2
|
run_test_reexec 5 tunasync-exec2
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
driver-opts: network=host
|
driver-opts: network=host
|
||||||
- name: Cache Docker layers
|
- name: Cache Docker layers
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
with:
|
with:
|
||||||
path: /tmp/.buildx-cache
|
path: /tmp/.buildx-cache
|
||||||
@ -99,7 +106,7 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-buildx-
|
${{ runner.os }}-buildx-
|
||||||
- name: Cache Docker layers
|
- name: Cache Docker layers
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
with:
|
with:
|
||||||
path: /tmp/.buildx-cache
|
path: /tmp/.buildx-cache
|
||||||
@ -118,7 +125,7 @@ jobs:
|
|||||||
mkdir -p /tmp/.buildx-cache
|
mkdir -p /tmp/.buildx-cache
|
||||||
|
|
||||||
- name: Build Docker image for uml rootfs
|
- name: Build Docker image for uml rootfs
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .umlrootfs
|
context: .umlrootfs
|
||||||
file: .umlrootfs/Dockerfile
|
file: .umlrootfs/Dockerfile
|
||||||
@ -132,10 +139,10 @@ jobs:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y debian-archive-keyring
|
sudo apt-get install -y debian-archive-keyring
|
||||||
sudo ln -sf /usr/share/keyrings/debian-archive-keyring.gpg /etc/apt/trusted.gpg.d/
|
sudo ln -sf /usr/share/keyrings/debian-archive-keyring.gpg /etc/apt/trusted.gpg.d/
|
||||||
echo "deb http://deb.debian.org/debian buster main" | sudo tee /etc/apt/sources.list.d/buster.list
|
echo "deb http://deb.debian.org/debian bullseye main" | sudo tee /etc/apt/sources.list.d/bullseye.list
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
apt-get download user-mode-linux/buster
|
apt-get download user-mode-linux/bullseye
|
||||||
sudo rm /etc/apt/sources.list.d/buster.list
|
sudo rm /etc/apt/sources.list.d/bullseye.list
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo mv user-mode-linux_*.deb /tmp/uml.deb
|
sudo mv user-mode-linux_*.deb /tmp/uml.deb
|
||||||
sudo apt-get install --no-install-recommends -y /tmp/uml.deb
|
sudo apt-get install --no-install-recommends -y /tmp/uml.deb
|
||||||
@ -157,7 +164,7 @@ jobs:
|
|||||||
- name: Start Uml
|
- name: Start Uml
|
||||||
run: |
|
run: |
|
||||||
start_uml () {
|
start_uml () {
|
||||||
sudo bash -c 'linux root=/dev/root rootflags=/ rw rootfstype=hostfs mem=2G eth0=tuntap,umltap hostfs="$PWD/umlrootfs" con1=pts systemd.unified_cgroup_hierarchy=1 & pid=$!; echo "UMLINUX_PID=$pid" >> '"$GITHUB_ENV"
|
sudo bash -c 'linux root=/dev/root rootflags=/ rw rootfstype=hostfs mem=2G eth0=tuntap,umltap hostfs="$PWD/umlrootfs" con1=pts systemd.unified_cgroup_hierarchy=0 & pid=$!; echo "UMLINUX_PID=$pid" >> '"$GITHUB_ENV"
|
||||||
}
|
}
|
||||||
( start_uml )
|
( start_uml )
|
||||||
started=0
|
started=0
|
||||||
@ -184,20 +191,18 @@ jobs:
|
|||||||
EOF
|
EOF
|
||||||
ln ./worker.test "umlrootfs/home/${CUSER}/worker.test"
|
ln ./worker.test "umlrootfs/home/${CUSER}/worker.test"
|
||||||
|
|
||||||
- name: Run Tests in Cgroupv2
|
- name: Run Tests in Cgroupv1
|
||||||
run: |
|
run: |
|
||||||
CUSER="$(id --user --name)"
|
CUSER="$(id --user --name)"
|
||||||
sudo rsh 254.255.255.2 bash --noprofile --norc -eo pipefail << EOF
|
sudo rsh 254.255.255.2 bash --noprofile --norc -eo pipefail << EOF
|
||||||
|
exec 2>&1
|
||||||
cd "/home/${CUSER}"
|
cd "/home/${CUSER}"
|
||||||
mkdir -p /sys/fs/cgroup/tunasync
|
lssubsys -am
|
||||||
|
cgcreate -a "$CUSER" -t "$CUSER" -g cpu:tunasync
|
||||||
|
cgcreate -a "$CUSER" -t "$CUSER" -g memory:tunasync
|
||||||
TERM=xterm-256color ./worker.test -test.v=true -test.coverprofile \
|
TERM=xterm-256color ./worker.test -test.v=true -test.coverprofile \
|
||||||
profile3.cov -test.run TestCgroup
|
profile3.gcov -test.run TestCgroup
|
||||||
rmdir /sys/fs/cgroup/tunasync
|
cgexec -g "*:/" bash -c "echo 0 > /sys/fs/cgroup/systemd/tasks; exec sudo -u $CUSER env USECURCGROUP=1 TERM=xterm-256color cgexec -g cpu,memory:tunasync ./worker.test -test.v=true -test.coverprofile profile4.gcov -test.run TestCgroup"
|
||||||
systemd-run --service-type=oneshot --uid="${CUSER}" --pipe --wait \
|
|
||||||
--property=Delegate=yes --setenv=USECURCGROUP=1 \
|
|
||||||
--setenv=TERM=xterm-256color --same-dir \
|
|
||||||
"\${PWD}/worker.test" -test.v=true -test.coverprofile \
|
|
||||||
profile4.cov -test.run TestCgroup
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
- name: Stop Uml
|
- name: Stop Uml
|
||||||
@ -222,19 +227,21 @@ jobs:
|
|||||||
- name: Combine coverage files
|
- name: Combine coverage files
|
||||||
run : |
|
run : |
|
||||||
CUSER="$(id --user --name)"
|
CUSER="$(id --user --name)"
|
||||||
"${HOME}/go/bin/gocovmerge" profile.cov profile2.cov \
|
"${HOME}/go/bin/gocovmerge" profile.gcov profile2.gcov \
|
||||||
"umlrootfs/home/${CUSER}/profile3.cov" \
|
"umlrootfs/home/${CUSER}/profile3.gcov" \
|
||||||
"umlrootfs/home/${CUSER}/profile4.cov" \
|
"umlrootfs/home/${CUSER}/profile4.gcov" \
|
||||||
profile5_*.cov > profile-all.cov
|
profile5_*.gcov > merged.gcov
|
||||||
|
# remove cmdline tools from coverage statistics
|
||||||
|
grep -v "cmd/.*\.go" merged.gcov > profile-all.gcov
|
||||||
|
|
||||||
- name: Convert coverage to lcov
|
- name: Convert coverage to lcov
|
||||||
uses: jandelgado/gcov2lcov-action@v1.0.0
|
uses: jandelgado/gcov2lcov-action@v1
|
||||||
with:
|
with:
|
||||||
infile: profile-all.cov
|
infile: profile-all.gcov
|
||||||
outfile: coverage.lcov
|
outfile: coverage.lcov
|
||||||
|
|
||||||
- name: Coveralls
|
- name: Coveralls
|
||||||
uses: coverallsapp/github-action@v1.0.1
|
uses: coverallsapp/github-action@v2
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.github_token }}
|
github-token: ${{ secrets.github_token }}
|
||||||
path-to-lcov: coverage.lcov
|
path-to-lcov: coverage.lcov
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
/build
|
/build
|
||||||
/build-*
|
/build-*
|
||||||
|
worker.test
|
||||||
|
profile*
|
@ -1,13 +1,8 @@
|
|||||||
FROM debian:buster
|
FROM debian:bullseye
|
||||||
RUN apt-get update && apt-get install -y systemd rsh-redone-server ifupdown sudo kmod
|
RUN apt-get update && apt-get install -y systemd rsh-redone-server ifupdown sudo kmod cgroup-tools systemd-sysv
|
||||||
RUN echo "host" > /root/.rhosts && \
|
RUN echo "host" > /root/.rhosts && \
|
||||||
chmod 600 /root/.rhosts && \
|
chmod 600 /root/.rhosts && \
|
||||||
/bin/echo -e "auto eth0\niface eth0 inet static\naddress 254.255.255.2/24" > /etc/network/interfaces.d/eth0 && \
|
/bin/echo -e "auto eth0\niface eth0 inet static\naddress 254.255.255.2/24" > /etc/network/interfaces.d/eth0 && \
|
||||||
sed -i '/pam_securetty/d' /etc/pam.d/rlogin && \
|
sed -i '/pam_securetty/d' /etc/pam.d/rlogin && \
|
||||||
cp /usr/share/systemd/tmp.mount /etc/systemd/system && \
|
cp /usr/share/systemd/tmp.mount /etc/systemd/system && \
|
||||||
systemctl enable tmp.mount
|
systemctl enable tmp.mount
|
||||||
|
|
||||||
RUN echo "deb http://deb.debian.org/debian experimental main" >> /etc/apt/sources.list && \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y make && \
|
|
||||||
apt-get install -y -t experimental cgroup-tools
|
|
||||||
|
11
Makefile
11
Makefile
@ -14,12 +14,15 @@ $(BUILDBIN): % : build-$(ARCH) build-$(ARCH)/%
|
|||||||
|
|
||||||
$(BUILDBIN:%=build-$(ARCH)/%) : build-$(ARCH)/% : cmd/%
|
$(BUILDBIN:%=build-$(ARCH)/%) : build-$(ARCH)/% : cmd/%
|
||||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go get ./$<
|
GOOS=$(GOOS) GOARCH=$(GOARCH) go get ./$<
|
||||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ -ldflags ${LDFLAGS} github.com/tuna/tunasync/$<
|
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 go build -o $@ -ldflags ${LDFLAGS} github.com/tuna/tunasync/$<
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test -v -covermode=count -coverprofile=profile.cov ./...
|
go test -v -covermode=count -coverprofile=profile.gcov ./...
|
||||||
|
|
||||||
build-test-worker:
|
build-test-worker:
|
||||||
go test -c -covermode=count ./worker
|
CGO_ENABLED=0 go test -c -covermode=count github.com/tuna/tunasync/worker
|
||||||
|
|
||||||
.PHONY: all test $(BUILDBIN) build-test-worker
|
clean:
|
||||||
|
rm -rf build-$(ARCH)
|
||||||
|
|
||||||
|
.PHONY: all test $(BUILDBIN) build-test-worker clean
|
||||||
|
@ -51,10 +51,13 @@ PreSyncing Syncing Succe
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Go version: 1.13
|
Go version: 1.22
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
# for native arch
|
||||||
> make all
|
> make all
|
||||||
|
# for other arch
|
||||||
|
> make ARCH=linux-arm64 all
|
||||||
```
|
```
|
||||||
|
|
||||||
Binaries in the `build-linux-amd64/`.
|
Binaries are in `build-$ARCH/`, e.g., `build-linux-amd64/`.
|
||||||
|
@ -9,10 +9,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/moby/sys/reexec"
|
||||||
"github.com/pkg/profile"
|
"github.com/pkg/profile"
|
||||||
"gopkg.in/op/go-logging.v1"
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"github.com/moby/moby/pkg/reexec"
|
"gopkg.in/op/go-logging.v1"
|
||||||
|
|
||||||
tunasync "github.com/tuna/tunasync/internal"
|
tunasync "github.com/tuna/tunasync/internal"
|
||||||
"github.com/tuna/tunasync/manager"
|
"github.com/tuna/tunasync/manager"
|
||||||
@ -40,7 +40,7 @@ func startManager(c *cli.Context) error {
|
|||||||
|
|
||||||
m := manager.GetTUNASyncManager(cfg)
|
m := manager.GetTUNASyncManager(cfg)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
logger.Errorf("Error intializing TUNA sync worker.")
|
logger.Errorf("Error intializing TUNA sync manager.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -122,7 +122,7 @@ func initialize(c *cli.Context) error {
|
|||||||
var err error
|
var err error
|
||||||
client, err = tunasync.CreateHTTPClient(cfg.CACert)
|
client, err = tunasync.CreateHTTPClient(cfg.CACert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Error initializing HTTP client: %s", err.Error())
|
err = fmt.Errorf("error initializing HTTP client: %s", err.Error())
|
||||||
// logger.Error(err.Error())
|
// logger.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ func listJobs(c *cli.Context) error {
|
|||||||
func updateMirrorSize(c *cli.Context) error {
|
func updateMirrorSize(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return cli.NewExitError("Usage: tunasynctl -w <worker-id> <mirror> <size>", 1)
|
return cli.NewExitError("Usage: tunasynctl set-size -w <worker-id> <mirror> <size>", 1)
|
||||||
}
|
}
|
||||||
workerID := c.String("worker")
|
workerID := c.String("worker")
|
||||||
mirrorID := args.Get(0)
|
mirrorID := args.Get(0)
|
||||||
@ -292,7 +292,7 @@ func updateMirrorSize(c *cli.Context) error {
|
|||||||
1)
|
1)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return cli.NewExitError(
|
return cli.NewExitError(
|
||||||
fmt.Sprintf("Manager failed to update mirror size: %s", body), 1,
|
fmt.Sprintf("Manager failed to update mirror size: %s", body), 1,
|
||||||
@ -338,7 +338,7 @@ func removeWorker(c *cli.Context) error {
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(
|
return cli.NewExitError(
|
||||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||||
@ -351,7 +351,7 @@ func removeWorker(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := map[string]string{}
|
res := map[string]string{}
|
||||||
err = json.NewDecoder(resp.Body).Decode(&res)
|
_ = json.NewDecoder(resp.Body).Decode(&res)
|
||||||
if res["message"] == "deleted" {
|
if res["message"] == "deleted" {
|
||||||
fmt.Println("Successfully removed the worker")
|
fmt.Println("Successfully removed the worker")
|
||||||
} else {
|
} else {
|
||||||
@ -376,7 +376,7 @@ func flushDisabledJobs(c *cli.Context) error {
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(
|
return cli.NewExitError(
|
||||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||||
@ -430,7 +430,7 @@ func cmdJob(cmd tunasync.CmdVerb) cli.ActionFunc {
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(
|
return cli.NewExitError(
|
||||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||||
@ -468,7 +468,7 @@ func cmdWorker(cmd tunasync.CmdVerb) cli.ActionFunc {
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(
|
return cli.NewExitError(
|
||||||
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
fmt.Sprintf("Failed to parse response: %s", err.Error()),
|
||||||
|
@ -39,7 +39,7 @@ name = "test_worker"
|
|||||||
log_dir = "/tmp/tunasync/log/tunasync/{{.Name}}"
|
log_dir = "/tmp/tunasync/log/tunasync/{{.Name}}"
|
||||||
mirror_dir = "/tmp/tunasync"
|
mirror_dir = "/tmp/tunasync"
|
||||||
concurrent = 10
|
concurrent = 10
|
||||||
interval = 1
|
interval = 120
|
||||||
|
|
||||||
[manager]
|
[manager]
|
||||||
api_base = "http://localhost:12345"
|
api_base = "http://localhost:12345"
|
||||||
|
103
go.mod
103
go.mod
@ -1,38 +1,89 @@
|
|||||||
module github.com/tuna/tunasync
|
module github.com/tuna/tunasync
|
||||||
|
|
||||||
go 1.13
|
go 1.23.0
|
||||||
|
|
||||||
|
toolchain go1.23.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v1.4.0
|
||||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
|
|
||||||
github.com/alicebob/miniredis v2.5.0+incompatible
|
github.com/alicebob/miniredis v2.5.0+incompatible
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||||
github.com/boltdb/bolt v1.3.1
|
github.com/boltdb/bolt v1.3.1
|
||||||
github.com/cilium/ebpf v0.6.2 // indirect
|
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe
|
||||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27
|
github.com/containerd/cgroups/v3 v3.0.5
|
||||||
github.com/containerd/cgroups v1.0.2-0.20210729163027-ddda8a174e9a
|
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6
|
||||||
github.com/dennwc/btrfs v0.0.0-20190517175702-d917b30ff035
|
github.com/dgraph-io/badger/v2 v2.2007.4
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/gin-gonic/gin v1.7.0
|
github.com/imdario/mergo v0.3.16
|
||||||
github.com/go-redis/redis/v8 v8.3.0
|
github.com/moby/moby v28.0.1+incompatible
|
||||||
github.com/gomodule/redigo v1.8.2 // indirect
|
github.com/moby/sys/reexec v0.1.0
|
||||||
github.com/imdario/mergo v0.3.9
|
github.com/opencontainers/runtime-spec v1.2.1
|
||||||
github.com/moby/moby v20.10.7+incompatible
|
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pkg/profile v1.4.0
|
github.com/pkg/profile v1.7.0
|
||||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46
|
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
|
||||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
|
||||||
github.com/smartystreets/goconvey v1.6.4
|
github.com/smartystreets/goconvey v1.6.4
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/urfave/cli v1.22.3
|
github.com/urfave/cli v1.22.16
|
||||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect
|
golang.org/x/sys v0.30.0
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887
|
|
||||||
google.golang.org/protobuf v1.26.0 // indirect
|
|
||||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
||||||
gotest.tools/v3 v3.0.3 // indirect
|
)
|
||||||
|
|
||||||
|
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/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/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/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/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/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/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
|
||||||
|
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/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/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.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
|
||||||
)
|
)
|
||||||
|
403
go.sum
403
go.sum
@ -1,178 +1,239 @@
|
|||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
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 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
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 h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
|
||||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
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 h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI=
|
||||||
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
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 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
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=
|
||||||
|
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||||
|
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
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 v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||||
github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI=
|
github.com/cilium/ebpf v0.17.1 h1:G8mzU81R2JA1nE5/8SRubzqvBMmAmri2VL8BIZPWvV0=
|
||||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
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 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe h1:69JI97HlzP+PH5Mi1thcGlDoBr6PS2Oe+l3mNmAkbs4=
|
||||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||||
github.com/containerd/cgroups v1.0.2-0.20210729163027-ddda8a174e9a h1:Se756mbFRj+3RITm/9NYHknEo1TJEpCV8jHI2e8QOEo=
|
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||||
github.com/containerd/cgroups v1.0.2-0.20210729163027-ddda8a174e9a/go.mod h1:M9MzGh4G4yzSq0e3Bf6tQCoDsvGewJdfhIix9CRaOWo=
|
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||||
|
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/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-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-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dennwc/btrfs v0.0.0-20190517175702-d917b30ff035 h1:4e+UEZaKPx0ZEiCMPUHMV51RGwbb1VJGCYqRFn/qmWM=
|
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6 h1:fV+JlCY0cCJh3l0jfE7iB3ZmrdfJSgfcjdrCQhPokGg=
|
||||||
github.com/dennwc/btrfs v0.0.0-20190517175702-d917b30ff035/go.mod h1:MYsOV9Dgsec3FFSOjywi0QK5r6TeBbdWxdrMGtiYXHA=
|
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 h1:DsWAAjIxRqNcLn9x6mwfuf2pet3iB7aK90K4tF16rLg=
|
||||||
github.com/dennwc/ioctl v1.0.0/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
|
github.com/dennwc/ioctl v1.0.0/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k=
|
github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o=
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
|
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 h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA=
|
|
||||||
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
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/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||||
|
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 h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
|
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
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.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 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||||
github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU=
|
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||||
github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-redis/redis/v8 v8.3.0 h1:Xrwvn8+QqUYD1MbQmda3cVR2U9li5XbtRFkKZN5Y0hk=
|
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||||
github.com/go-redis/redis/v8 v8.3.0/go.mod h1:a2xkpBM7NJUN5V5kiF46X5Ltx4WeXJ9757X/ScKUBdE=
|
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
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/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.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.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
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.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.1/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 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
|
||||||
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
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-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 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
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/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||||
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
|
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
|
||||||
|
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
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 h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
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.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
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/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/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/moby/moby v20.10.7+incompatible h1:mMDsIjUeon2FpxCJz0Xj32wzRcTbGLVzG1uEbPalok4=
|
github.com/moby/moby v27.4.1+incompatible h1:z6detzbcLRt7U+w4ovHV+8oYpJfpHKTmUbFWPG6cudA=
|
||||||
github.com/moby/moby v20.10.7+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
github.com/moby/moby v27.4.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
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=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
|
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||||
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/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 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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI=
|
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||||
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
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 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=
|
||||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
|
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
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 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||||
@ -188,95 +249,85 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
|
|||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
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/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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.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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.6.1/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/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
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 v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
|
||||||
github.com/urfave/cli v1.22.3 h1:FpNT6zq26xNpHZy08emi755QwzLPs6Pukqjlc7RfOMU=
|
github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
|
||||||
github.com/urfave/cli v1.22.3/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0=
|
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=
|
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||||
go.opentelemetry.io/otel v0.13.0 h1:2isEnyzjjJZq6r2EKMsFj4TxiQiexsM04AVhwbR/oBA=
|
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||||
go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY=
|
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||||
|
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-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.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/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.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-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-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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/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-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
|
|
||||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
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=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
|
||||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
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 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE=
|
||||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog=
|
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog=
|
||||||
@ -284,11 +335,9 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
|
|||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
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=
|
||||||
|
@ -71,8 +71,7 @@ func TestStatus(t *testing.T) {
|
|||||||
Size: "4GB",
|
Size: "4GB",
|
||||||
}
|
}
|
||||||
|
|
||||||
var m2 WebMirrorStatus
|
var m2 WebMirrorStatus = BuildWebMirrorStatus(m)
|
||||||
m2 = BuildWebMirrorStatus(m)
|
|
||||||
// fmt.Printf("%#v", m2)
|
// fmt.Printf("%#v", m2)
|
||||||
So(m2.Name, ShouldEqual, m.Name)
|
So(m2.Name, ShouldEqual, m.Name)
|
||||||
So(m2.Status, ShouldEqual, m.Status)
|
So(m2.Status, ShouldEqual, m.Status)
|
||||||
|
@ -7,8 +7,9 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
@ -39,19 +40,19 @@ var rsyncExitValues = map[int]string{
|
|||||||
|
|
||||||
// GetTLSConfig generate tls.Config from CAFile
|
// GetTLSConfig generate tls.Config from CAFile
|
||||||
func GetTLSConfig(CAFile string) (*tls.Config, error) {
|
func GetTLSConfig(CAFile string) (*tls.Config, error) {
|
||||||
caCert, err := ioutil.ReadFile(CAFile)
|
caCert, err := os.ReadFile(CAFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
caCertPool := x509.NewCertPool()
|
caCertPool := x509.NewCertPool()
|
||||||
if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
|
if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
|
||||||
return nil, errors.New("Failed to add CA to pool")
|
return nil, errors.New("failed to add CA to pool")
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
RootCAs: caCertPool,
|
RootCAs: caCertPool,
|
||||||
}
|
}
|
||||||
tlsConfig.BuildNameToCertificate()
|
// tlsConfig.BuildNameToCertificate()
|
||||||
return tlsConfig, nil
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ func GetJSON(url string, obj interface{}, client *http.Client) (*http.Response,
|
|||||||
return resp, errors.New("HTTP status code is not 200")
|
return resp, errors.New("HTTP status code is not 200")
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
@ -114,10 +115,10 @@ func GetJSON(url string, obj interface{}, client *http.Client) (*http.Response,
|
|||||||
// FindAllSubmatchInFile calls re.FindAllSubmatch to find matches in given file
|
// FindAllSubmatchInFile calls re.FindAllSubmatch to find matches in given file
|
||||||
func FindAllSubmatchInFile(fileName string, re *regexp.Regexp) (matches [][][]byte, err error) {
|
func FindAllSubmatchInFile(fileName string, re *regexp.Regexp) (matches [][][]byte, err error) {
|
||||||
if fileName == "/dev/null" {
|
if fileName == "/dev/null" {
|
||||||
err = errors.New("Invalid log file")
|
err = errors.New("invalid log file")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if content, err := ioutil.ReadFile(fileName); err == nil {
|
if content, err := os.ReadFile(fileName); err == nil {
|
||||||
matches = re.FindAllSubmatch(content, -1)
|
matches = re.FindAllSubmatch(content, -1)
|
||||||
// fmt.Printf("FindAllSubmatchInFile: %q\n", matches)
|
// fmt.Printf("FindAllSubmatchInFile: %q\n", matches)
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ func FindAllSubmatchInFile(fileName string, re *regexp.Regexp) (matches [][][]by
|
|||||||
// ExtractSizeFromLog uses a regexp to extract the size from log files
|
// ExtractSizeFromLog uses a regexp to extract the size from log files
|
||||||
func ExtractSizeFromLog(logFile string, re *regexp.Regexp) string {
|
func ExtractSizeFromLog(logFile string, re *regexp.Regexp) string {
|
||||||
matches, _ := FindAllSubmatchInFile(logFile, re)
|
matches, _ := FindAllSubmatchInFile(logFile, re)
|
||||||
if matches == nil || len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
// return the first capture group of the last occurrence
|
// return the first capture group of the last occurrence
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -29,11 +28,11 @@ sent 7.55M bytes received 823.25M bytes 5.11M bytes/sec
|
|||||||
total size is 1.33T speedup is 1,604.11
|
total size is 1.33T speedup is 1,604.11
|
||||||
`
|
`
|
||||||
Convey("Log parser should work", t, func() {
|
Convey("Log parser should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
logFile := filepath.Join(tmpDir, "rs.log")
|
logFile := filepath.Join(tmpDir, "rs.log")
|
||||||
err = ioutil.WriteFile(logFile, []byte(realLogContent), 0755)
|
err = os.WriteFile(logFile, []byte(realLogContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
res := ExtractSizeFromRsyncLog(logFile)
|
res := ExtractSizeFromRsyncLog(logFile)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
// Version of the program
|
// Version of the program
|
||||||
const Version string = "0.8.0"
|
const Version string = "0.9.3"
|
||||||
|
@ -2,7 +2,6 @@ package manager
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -37,11 +36,11 @@ func TestConfig(t *testing.T) {
|
|||||||
|
|
||||||
Convey("load Config should work", t, func() {
|
Convey("load Config should work", t, func() {
|
||||||
Convey("create config file & cli context", func() {
|
Convey("create config file & cli context", func() {
|
||||||
tmpfile, err := ioutil.TempFile("", "tunasync")
|
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
err = ioutil.WriteFile(tmpfile.Name(), []byte(cfgBlob), 0644)
|
err = os.WriteFile(tmpfile.Name(), []byte(cfgBlob), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer tmpfile.Close()
|
defer tmpfile.Close()
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
bolt "github.com/boltdb/bolt"
|
||||||
"github.com/dgraph-io/badger/v2"
|
"github.com/dgraph-io/badger/v2"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -141,7 +141,7 @@ func (b *kvDBAdapter) ListWorkers() (ws []WorkerStatus, err error) {
|
|||||||
|
|
||||||
func (b *kvDBAdapter) GetWorker(workerID string) (w WorkerStatus, err error) {
|
func (b *kvDBAdapter) GetWorker(workerID string) (w WorkerStatus, err error) {
|
||||||
var v []byte
|
var v []byte
|
||||||
v, err = b.db.Get(_workerBucketKey, workerID)
|
v, _ = b.db.Get(_workerBucketKey, workerID)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
err = fmt.Errorf("invalid workerID %s", workerID)
|
err = fmt.Errorf("invalid workerID %s", workerID)
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,7 +3,7 @@ package manager
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
bolt "github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// implement kv interface backed by boltdb
|
// implement kv interface backed by boltdb
|
||||||
|
@ -3,7 +3,6 @@ package manager
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@ -32,7 +31,7 @@ func DBAdapterTest(db dbAdapter) {
|
|||||||
LastOnline: time.Now(),
|
LastOnline: time.Now(),
|
||||||
LastRegister: time.Now(),
|
LastRegister: time.Now(),
|
||||||
}
|
}
|
||||||
w, err = db.CreateWorker(w)
|
_, err = db.CreateWorker(w)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ func DBAdapterTest(db dbAdapter) {
|
|||||||
|
|
||||||
Convey("update mirror status", func() {
|
Convey("update mirror status", func() {
|
||||||
status := []MirrorStatus{
|
status := []MirrorStatus{
|
||||||
MirrorStatus{
|
{
|
||||||
Name: "arch-sync1",
|
Name: "arch-sync1",
|
||||||
Worker: testWorkerIDs[0],
|
Worker: testWorkerIDs[0],
|
||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
@ -84,7 +83,7 @@ func DBAdapterTest(db dbAdapter) {
|
|||||||
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
Size: "3GB",
|
Size: "3GB",
|
||||||
},
|
},
|
||||||
MirrorStatus{
|
{
|
||||||
Name: "arch-sync2",
|
Name: "arch-sync2",
|
||||||
Worker: testWorkerIDs[1],
|
Worker: testWorkerIDs[1],
|
||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
@ -95,7 +94,7 @@ func DBAdapterTest(db dbAdapter) {
|
|||||||
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
Size: "4GB",
|
Size: "4GB",
|
||||||
},
|
},
|
||||||
MirrorStatus{
|
{
|
||||||
Name: "arch-sync3",
|
Name: "arch-sync3",
|
||||||
Worker: testWorkerIDs[1],
|
Worker: testWorkerIDs[1],
|
||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
@ -159,12 +158,11 @@ func DBAdapterTest(db dbAdapter) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDBAdapter(t *testing.T) {
|
func TestDBAdapter(t *testing.T) {
|
||||||
Convey("boltAdapter should work", t, func() {
|
Convey("boltAdapter should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -200,7 +198,7 @@ func TestDBAdapter(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("badgerAdapter should work", t, func() {
|
Convey("badgerAdapter should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -218,7 +216,7 @@ func TestDBAdapter(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("leveldbAdapter should work", t, func() {
|
Convey("leveldbAdapter should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ func (s *Manager) updateSchedulesOfWorker(c *gin.Context) {
|
|||||||
if len(mirrorName) == 0 {
|
if len(mirrorName) == 0 {
|
||||||
s.returnErrJSON(
|
s.returnErrJSON(
|
||||||
c, http.StatusBadRequest,
|
c, http.StatusBadRequest,
|
||||||
errors.New("Mirror Name should not be empty"),
|
errors.New("mirror Name should not be empty"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +312,7 @@ func (s *Manager) updateJobOfWorker(c *gin.Context) {
|
|||||||
if len(mirrorName) == 0 {
|
if len(mirrorName) == 0 {
|
||||||
s.returnErrJSON(
|
s.returnErrJSON(
|
||||||
c, http.StatusBadRequest,
|
c, http.StatusBadRequest,
|
||||||
errors.New("Mirror Name should not be empty"),
|
errors.New("mirror Name should not be empty"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,11 @@ package manager
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -35,7 +36,7 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(s, ShouldNotBeNil)
|
So(s, ShouldNotBeNil)
|
||||||
s.setDBAdapter(&mockDBAdapter{
|
s.setDBAdapter(&mockDBAdapter{
|
||||||
workerStore: map[string]WorkerStatus{
|
workerStore: map[string]WorkerStatus{
|
||||||
_magicBadWorkerID: WorkerStatus{
|
_magicBadWorkerID: {
|
||||||
ID: _magicBadWorkerID,
|
ID: _magicBadWorkerID,
|
||||||
}},
|
}},
|
||||||
statusStore: make(map[string]MirrorStatus),
|
statusStore: make(map[string]MirrorStatus),
|
||||||
@ -47,7 +48,7 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(resp.StatusCode, ShouldEqual, http.StatusOK)
|
So(resp.StatusCode, ShouldEqual, http.StatusOK)
|
||||||
So(resp.Header.Get("Content-Type"), ShouldEqual, "application/json; charset=utf-8")
|
So(resp.Header.Get("Content-Type"), ShouldEqual, "application/json; charset=utf-8")
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
var p map[string]string
|
var p map[string]string
|
||||||
err = json.Unmarshal(body, &p)
|
err = json.Unmarshal(body, &p)
|
||||||
@ -179,9 +180,9 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Upstream, ShouldEqual, status.Upstream)
|
So(m.Upstream, ShouldEqual, status.Upstream)
|
||||||
So(m.Size, ShouldEqual, status.Size)
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 1*time.Second)
|
So(time.Since(m.LastUpdate), ShouldBeLessThan, 1*time.Second)
|
||||||
So(m.LastStarted.IsZero(), ShouldBeTrue) // hasn't been initialized yet
|
So(m.LastStarted.IsZero(), ShouldBeTrue) // hasn't been initialized yet
|
||||||
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
So(time.Since(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -207,11 +208,11 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Upstream, ShouldEqual, status.Upstream)
|
So(m.Upstream, ShouldEqual, status.Upstream)
|
||||||
So(m.Size, ShouldEqual, status.Size)
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 3*time.Second)
|
So(time.Since(m.LastUpdate), ShouldBeLessThan, 3*time.Second)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeGreaterThan, 1*time.Second)
|
So(time.Since(m.LastUpdate), ShouldBeGreaterThan, 1*time.Second)
|
||||||
So(time.Now().Sub(m.LastStarted), ShouldBeLessThan, 2*time.Second)
|
So(time.Since(m.LastStarted), ShouldBeLessThan, 2*time.Second)
|
||||||
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 3*time.Second)
|
So(time.Since(m.LastEnded), ShouldBeLessThan, 3*time.Second)
|
||||||
So(time.Now().Sub(m.LastEnded), ShouldBeGreaterThan, 1*time.Second)
|
So(time.Since(m.LastEnded), ShouldBeGreaterThan, 1*time.Second)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -227,9 +228,9 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Upstream, ShouldEqual, status.Upstream)
|
So(m.Upstream, ShouldEqual, status.Upstream)
|
||||||
So(m.Size, ShouldEqual, status.Size)
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate.Time), ShouldBeLessThan, 3*time.Second)
|
So(time.Since(m.LastUpdate.Time), ShouldBeLessThan, 3*time.Second)
|
||||||
So(time.Now().Sub(m.LastStarted.Time), ShouldBeLessThan, 2*time.Second)
|
So(time.Since(m.LastStarted.Time), ShouldBeLessThan, 2*time.Second)
|
||||||
So(time.Now().Sub(m.LastEnded.Time), ShouldBeLessThan, 3*time.Second)
|
So(time.Since(m.LastEnded.Time), ShouldBeLessThan, 3*time.Second)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -258,17 +259,17 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Upstream, ShouldEqual, status.Upstream)
|
So(m.Upstream, ShouldEqual, status.Upstream)
|
||||||
So(m.Size, ShouldEqual, "5GB")
|
So(m.Size, ShouldEqual, "5GB")
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 3*time.Second)
|
So(time.Since(m.LastUpdate), ShouldBeLessThan, 3*time.Second)
|
||||||
So(time.Now().Sub(m.LastStarted), ShouldBeLessThan, 2*time.Second)
|
So(time.Since(m.LastStarted), ShouldBeLessThan, 2*time.Second)
|
||||||
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 3*time.Second)
|
So(time.Since(m.LastEnded), ShouldBeLessThan, 3*time.Second)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Update schedule of valid mirrors", func(ctx C) {
|
Convey("Update schedule of valid mirrors", func(ctx C) {
|
||||||
msg := MirrorSchedules{
|
msg := MirrorSchedules{
|
||||||
[]MirrorSchedule{
|
Schedules: []MirrorSchedule{
|
||||||
MirrorSchedule{"arch-sync1", time.Now().Add(time.Minute * 10)},
|
{MirrorName: "arch-sync1", NextSchedule: time.Now().Add(time.Minute * 10)},
|
||||||
MirrorSchedule{"arch-sync2", time.Now().Add(time.Minute * 7)},
|
{MirrorName: "arch-sync2", NextSchedule: time.Now().Add(time.Minute * 7)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,9 +313,9 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Upstream, ShouldEqual, status.Upstream)
|
So(m.Upstream, ShouldEqual, status.Upstream)
|
||||||
So(m.Size, ShouldEqual, status.Size)
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeGreaterThan, 3*time.Second)
|
So(time.Since(m.LastUpdate), ShouldBeGreaterThan, 3*time.Second)
|
||||||
So(time.Now().Sub(m.LastStarted), ShouldBeGreaterThan, 3*time.Second)
|
So(time.Since(m.LastStarted), ShouldBeGreaterThan, 3*time.Second)
|
||||||
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
So(time.Since(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -344,9 +345,9 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
Convey("update schedule of an non-existent worker", func(ctx C) {
|
Convey("update schedule of an non-existent worker", func(ctx C) {
|
||||||
invalidWorker := "test_worker2"
|
invalidWorker := "test_worker2"
|
||||||
sch := MirrorSchedules{
|
sch := MirrorSchedules{
|
||||||
[]MirrorSchedule{
|
Schedules: []MirrorSchedule{
|
||||||
MirrorSchedule{"arch-sync1", time.Now().Add(time.Minute * 10)},
|
{MirrorName: "arch-sync1", NextSchedule: time.Now().Add(time.Minute * 10)},
|
||||||
MirrorSchedule{"arch-sync2", time.Now().Add(time.Minute * 7)},
|
{MirrorName: "arch-sync2", NextSchedule: time.Now().Add(time.Minute * 7)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
resp, err := PostJSON(fmt.Sprintf("%s/workers/%s/schedules",
|
resp, err := PostJSON(fmt.Sprintf("%s/workers/%s/schedules",
|
||||||
@ -424,6 +425,8 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
type mockDBAdapter struct {
|
type mockDBAdapter struct {
|
||||||
workerStore map[string]WorkerStatus
|
workerStore map[string]WorkerStatus
|
||||||
statusStore map[string]MirrorStatus
|
statusStore map[string]MirrorStatus
|
||||||
|
workerLock sync.RWMutex
|
||||||
|
statusLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *mockDBAdapter) Init() error {
|
func (b *mockDBAdapter) Init() error {
|
||||||
@ -431,17 +434,22 @@ func (b *mockDBAdapter) Init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *mockDBAdapter) ListWorkers() ([]WorkerStatus, error) {
|
func (b *mockDBAdapter) ListWorkers() ([]WorkerStatus, error) {
|
||||||
|
b.workerLock.RLock()
|
||||||
workers := make([]WorkerStatus, len(b.workerStore))
|
workers := make([]WorkerStatus, len(b.workerStore))
|
||||||
idx := 0
|
idx := 0
|
||||||
for _, w := range b.workerStore {
|
for _, w := range b.workerStore {
|
||||||
workers[idx] = w
|
workers[idx] = w
|
||||||
idx++
|
idx++
|
||||||
}
|
}
|
||||||
|
b.workerLock.RUnlock()
|
||||||
return workers, nil
|
return workers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *mockDBAdapter) GetWorker(workerID string) (WorkerStatus, error) {
|
func (b *mockDBAdapter) GetWorker(workerID string) (WorkerStatus, error) {
|
||||||
|
b.workerLock.RLock()
|
||||||
|
defer b.workerLock.RUnlock()
|
||||||
w, ok := b.workerStore[workerID]
|
w, ok := b.workerStore[workerID]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return WorkerStatus{}, fmt.Errorf("invalid workerId")
|
return WorkerStatus{}, fmt.Errorf("invalid workerId")
|
||||||
}
|
}
|
||||||
@ -449,7 +457,9 @@ func (b *mockDBAdapter) GetWorker(workerID string) (WorkerStatus, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *mockDBAdapter) DeleteWorker(workerID string) error {
|
func (b *mockDBAdapter) DeleteWorker(workerID string) error {
|
||||||
|
b.workerLock.Lock()
|
||||||
delete(b.workerStore, workerID)
|
delete(b.workerStore, workerID)
|
||||||
|
b.workerLock.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +468,9 @@ func (b *mockDBAdapter) CreateWorker(w WorkerStatus) (WorkerStatus, error) {
|
|||||||
// if ok {
|
// if ok {
|
||||||
// return workerStatus{}, fmt.Errorf("duplicate worker name")
|
// return workerStatus{}, fmt.Errorf("duplicate worker name")
|
||||||
// }
|
// }
|
||||||
|
b.workerLock.Lock()
|
||||||
b.workerStore[w.ID] = w
|
b.workerStore[w.ID] = w
|
||||||
|
b.workerLock.Unlock()
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +485,9 @@ func (b *mockDBAdapter) RefreshWorker(workerID string) (w WorkerStatus, err erro
|
|||||||
|
|
||||||
func (b *mockDBAdapter) GetMirrorStatus(workerID, mirrorID string) (MirrorStatus, error) {
|
func (b *mockDBAdapter) GetMirrorStatus(workerID, mirrorID string) (MirrorStatus, error) {
|
||||||
id := mirrorID + "/" + workerID
|
id := mirrorID + "/" + workerID
|
||||||
|
b.statusLock.RLock()
|
||||||
status, ok := b.statusStore[id]
|
status, ok := b.statusStore[id]
|
||||||
|
b.statusLock.RUnlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
return MirrorStatus{}, fmt.Errorf("no mirror %s exists in worker %s", mirrorID, workerID)
|
return MirrorStatus{}, fmt.Errorf("no mirror %s exists in worker %s", mirrorID, workerID)
|
||||||
}
|
}
|
||||||
@ -487,7 +501,9 @@ func (b *mockDBAdapter) UpdateMirrorStatus(workerID, mirrorID string, status Mir
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
id := mirrorID + "/" + workerID
|
id := mirrorID + "/" + workerID
|
||||||
|
b.statusLock.Lock()
|
||||||
b.statusStore[id] = status
|
b.statusStore[id] = status
|
||||||
|
b.statusLock.Unlock()
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,19 +513,23 @@ func (b *mockDBAdapter) ListMirrorStatus(workerID string) ([]MirrorStatus, error
|
|||||||
if workerID == _magicBadWorkerID {
|
if workerID == _magicBadWorkerID {
|
||||||
return []MirrorStatus{}, fmt.Errorf("database fail")
|
return []MirrorStatus{}, fmt.Errorf("database fail")
|
||||||
}
|
}
|
||||||
|
b.statusLock.RLock()
|
||||||
for k, v := range b.statusStore {
|
for k, v := range b.statusStore {
|
||||||
if wID := strings.Split(k, "/")[1]; wID == workerID {
|
if wID := strings.Split(k, "/")[1]; wID == workerID {
|
||||||
mirrorStatusList = append(mirrorStatusList, v)
|
mirrorStatusList = append(mirrorStatusList, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
b.statusLock.RUnlock()
|
||||||
return mirrorStatusList, nil
|
return mirrorStatusList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *mockDBAdapter) ListAllMirrorStatus() ([]MirrorStatus, error) {
|
func (b *mockDBAdapter) ListAllMirrorStatus() ([]MirrorStatus, error) {
|
||||||
var mirrorStatusList []MirrorStatus
|
var mirrorStatusList []MirrorStatus
|
||||||
|
b.statusLock.RLock()
|
||||||
for _, v := range b.statusStore {
|
for _, v := range b.statusStore {
|
||||||
mirrorStatusList = append(mirrorStatusList, v)
|
mirrorStatusList = append(mirrorStatusList, v)
|
||||||
}
|
}
|
||||||
|
b.statusLock.RUnlock()
|
||||||
return mirrorStatusList, nil
|
return mirrorStatusList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build ignore
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build ignore
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build ignore
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build ignore
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@ -22,6 +22,7 @@ type baseProvider struct {
|
|||||||
cmd *cmdJob
|
cmd *cmdJob
|
||||||
logFileFd *os.File
|
logFileFd *os.File
|
||||||
isRunning atomic.Value
|
isRunning atomic.Value
|
||||||
|
successExitCodes []int
|
||||||
|
|
||||||
cgroup *cgroupHook
|
cgroup *cgroupHook
|
||||||
zfs *zfsHook
|
zfs *zfsHook
|
||||||
@ -186,3 +187,18 @@ func (p *baseProvider) Terminate() error {
|
|||||||
func (p *baseProvider) DataSize() string {
|
func (p *baseProvider) DataSize() string {
|
||||||
return ""
|
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
|
||||||
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package worker
|
package worker
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package worker
|
package worker
|
||||||
|
@ -3,7 +3,7 @@ package worker
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -12,9 +12,10 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/moby/moby/pkg/reexec"
|
cgroups "github.com/containerd/cgroups/v3"
|
||||||
cgv1 "github.com/containerd/cgroups"
|
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||||
cgv2 "github.com/containerd/cgroups/v2"
|
cgv2 "github.com/containerd/cgroups/v3/cgroup2"
|
||||||
|
"github.com/moby/sys/reexec"
|
||||||
contspecs "github.com/opencontainers/runtime-spec/specs-go"
|
contspecs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ func waitExec () {
|
|||||||
pipe := os.NewFile(3, "pipe")
|
pipe := os.NewFile(3, "pipe")
|
||||||
if pipe != nil {
|
if pipe != nil {
|
||||||
if _, err := pipe.Stat(); err == nil {
|
if _, err := pipe.Stat(); err == nil {
|
||||||
cmdBytes, err := ioutil.ReadAll(pipe)
|
cmdBytes, err := io.ReadAll(pipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -71,7 +72,7 @@ func waitExec () {
|
|||||||
panic("Exec failed.")
|
panic("Exec failed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initCgroup(cfg *cgroupConfig) (error) {
|
func initCgroup(cfg *cgroupConfig) error {
|
||||||
|
|
||||||
logger.Debugf("Initializing cgroup")
|
logger.Debugf("Initializing cgroup")
|
||||||
baseGroup := cfg.Group
|
baseGroup := cfg.Group
|
||||||
@ -83,7 +84,7 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
baseGroup = filepath.Join("/", baseGroup)
|
baseGroup = filepath.Join("/", baseGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.isUnified = cgv1.Mode() == cgv1.Unified
|
cfg.isUnified = cgroups.Mode() == cgroups.Unified
|
||||||
|
|
||||||
if cfg.isUnified {
|
if cfg.isUnified {
|
||||||
logger.Debugf("Cgroup V2 detected")
|
logger.Debugf("Cgroup V2 detected")
|
||||||
@ -98,12 +99,12 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
logger.Infof("Using cgroup path: %s", g)
|
logger.Infof("Using cgroup path: %s", g)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if cfg.cgMgrV2, err = cgv2.LoadManager("/sys/fs/cgroup", g); err != nil {
|
if cfg.cgMgrV2, err = cgv2.Load(g); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if baseGroup == "" {
|
if baseGroup == "" {
|
||||||
logger.Debugf("Creating a sub group and move all processes into it")
|
logger.Debugf("Creating a sub group and move all processes into it")
|
||||||
wkrMgr, err := cfg.cgMgrV2.NewChild("__worker", nil);
|
wkrMgr, err := cfg.cgMgrV2.NewChild("__worker", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -117,7 +118,7 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
if len(procs) == 0 {
|
if len(procs) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, p := range(procs) {
|
for _, p := range procs {
|
||||||
if err := wkrMgr.AddProc(p); err != nil {
|
if err := wkrMgr.AddProc(p); err != nil {
|
||||||
if errors.Is(err, syscall.ESRCH) {
|
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")
|
||||||
@ -129,7 +130,7 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("Trying to create a sub group in that group")
|
logger.Debugf("Trying to create a sub group in that group")
|
||||||
testMgr, err := cfg.cgMgrV2.NewChild("__test", nil);
|
testMgr, err := cfg.cgMgrV2.NewChild("__test", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Cannot create a sub group in the cgroup")
|
logger.Errorf("Cannot create a sub group in the cgroup")
|
||||||
return err
|
return err
|
||||||
@ -152,9 +153,9 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
if baseGroup != "" {
|
if baseGroup != "" {
|
||||||
pather = cgv1.StaticPath(baseGroup)
|
pather = cgv1.StaticPath(baseGroup)
|
||||||
} else {
|
} else {
|
||||||
pather = (func(p cgv1.Path) (cgv1.Path){
|
pather = (func(p cgv1.Path) cgv1.Path {
|
||||||
return func(subsys cgv1.Name) (string, error) {
|
return func(subsys cgv1.Name) (string, error) {
|
||||||
path, err := p(subsys);
|
path, err := p(subsys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -167,14 +168,14 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
}
|
}
|
||||||
logger.Infof("Loading cgroup")
|
logger.Infof("Loading cgroup")
|
||||||
var err error
|
var err error
|
||||||
if cfg.cgMgrV1, err = cgv1.Load(cgv1.V1, pather, func(cfg *cgv1.InitConfig) error{
|
if cfg.cgMgrV1, err = cgv1.Load(pather, func(cfg *cgv1.InitConfig) error {
|
||||||
cfg.InitCheck = cgv1.AllowAny
|
cfg.InitCheck = cgv1.AllowAny
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logger.Debugf("Available subsystems:")
|
logger.Debugf("Available subsystems:")
|
||||||
for _, subsys := range(cfg.cgMgrV1.Subsystems()) {
|
for _, subsys := range cfg.cgMgrV1.Subsystems() {
|
||||||
p, err := pather(subsys.Name())
|
p, err := pather(subsys.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -183,11 +184,11 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
}
|
}
|
||||||
if baseGroup == "" {
|
if baseGroup == "" {
|
||||||
logger.Debugf("Creating a sub group and move all processes into it")
|
logger.Debugf("Creating a sub group and move all processes into it")
|
||||||
wkrMgr, err := cfg.cgMgrV1.New("__worker", &contspecs.LinuxResources{});
|
wkrMgr, err := cfg.cgMgrV1.New("__worker", &contspecs.LinuxResources{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, subsys := range(cfg.cgMgrV1.Subsystems()) {
|
for _, subsys := range cfg.cgMgrV1.Subsystems() {
|
||||||
logger.Debugf("Reading pids for subsystem %s", subsys.Name())
|
logger.Debugf("Reading pids for subsystem %s", subsys.Name())
|
||||||
for {
|
for {
|
||||||
procs, err := cfg.cgMgrV1.Processes(subsys.Name(), false)
|
procs, err := cfg.cgMgrV1.Processes(subsys.Name(), false)
|
||||||
@ -202,7 +203,7 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
if len(procs) == 0 {
|
if len(procs) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, proc := range(procs) {
|
for _, proc := range procs {
|
||||||
if err := wkrMgr.Add(proc); err != nil {
|
if err := wkrMgr.Add(proc); err != nil {
|
||||||
if errors.Is(err, syscall.ESRCH) {
|
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")
|
||||||
@ -215,7 +216,7 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("Trying to create a sub group in that group")
|
logger.Debugf("Trying to create a sub group in that group")
|
||||||
testMgr, err := cfg.cgMgrV1.New("__test", &contspecs.LinuxResources{});
|
testMgr, err := cfg.cgMgrV1.New("__test", &contspecs.LinuxResources{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Cannot create a sub group in the cgroup")
|
logger.Errorf("Cannot create a sub group in the cgroup")
|
||||||
return err
|
return err
|
||||||
@ -223,7 +224,7 @@ func initCgroup(cfg *cgroupConfig) (error) {
|
|||||||
if err := testMgr.Delete(); err != nil {
|
if err := testMgr.Delete(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, subsys := range(cfg.cgMgrV1.Subsystems()) {
|
for _, subsys := range cfg.cgMgrV1.Subsystems() {
|
||||||
logger.Debugf("Reading pids for subsystem %s", subsys.Name())
|
logger.Debugf("Reading pids for subsystem %s", subsys.Name())
|
||||||
procs, err := cfg.cgMgrV1.Processes(subsys.Name(), false)
|
procs, err := cfg.cgMgrV1.Processes(subsys.Name(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -334,7 +335,7 @@ func (c *cgroupHook) killAll() error {
|
|||||||
taskList := []int{}
|
taskList := []int{}
|
||||||
if c.cgCfg.isUnified {
|
if c.cgCfg.isUnified {
|
||||||
procs, err := c.cgMgrV2.Procs(false)
|
procs, err := c.cgMgrV2.Procs(false)
|
||||||
if (err != nil) {
|
if err != nil {
|
||||||
return []int{}, err
|
return []int{}, err
|
||||||
}
|
}
|
||||||
for _, proc := range procs {
|
for _, proc := range procs {
|
||||||
@ -342,16 +343,16 @@ func (c *cgroupHook) killAll() error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
taskSet := make(map[int]struct{})
|
taskSet := make(map[int]struct{})
|
||||||
for _, subsys := range(c.cgMgrV1.Subsystems()) {
|
for _, subsys := range c.cgMgrV1.Subsystems() {
|
||||||
procs, err := c.cgMgrV1.Processes(subsys.Name(), false)
|
procs, err := c.cgMgrV1.Processes(subsys.Name(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []int{}, err
|
return []int{}, err
|
||||||
}
|
}
|
||||||
for _, proc := range(procs) {
|
for _, proc := range procs {
|
||||||
taskSet[proc.Pid] = struct{}{}
|
taskSet[proc.Pid] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for proc := range(taskSet) {
|
for proc := range taskSet {
|
||||||
taskList = append(taskList, proc)
|
taskList = append(taskList, proc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
package worker
|
package worker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"errors"
|
|
||||||
"syscall"
|
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||||
cgv1 "github.com/containerd/cgroups"
|
cgv2 "github.com/containerd/cgroups/v3/cgroup2"
|
||||||
cgv2 "github.com/containerd/cgroups/v2"
|
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
"github.com/moby/moby/pkg/reexec"
|
"github.com/moby/sys/reexec"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
)
|
)
|
||||||
@ -98,7 +98,7 @@ func TestCgroup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Convey("Cgroup Should Work", func(ctx C) {
|
Convey("Cgroup Should Work", func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
cmdScript := filepath.Join(tmpDir, "cmd.sh")
|
cmdScript := filepath.Join(tmpDir, "cmd.sh")
|
||||||
@ -148,9 +148,9 @@ sleep 5
|
|||||||
echo $$ > $BG_PIDFILE
|
echo $$ > $BG_PIDFILE
|
||||||
sleep 30
|
sleep 30
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(cmdScript, []byte(cmdScriptContent), 0755)
|
err = os.WriteFile(cmdScript, []byte(cmdScriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
err = ioutil.WriteFile(daemonScript, []byte(daemonScriptContent), 0755)
|
err = os.WriteFile(daemonScript, []byte(daemonScriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
provider, err := newCmdProvider(c)
|
provider, err := newCmdProvider(c)
|
||||||
@ -169,7 +169,7 @@ sleep 30
|
|||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
// Deamon should be started
|
// Deamon should be started
|
||||||
daemonPidBytes, err := ioutil.ReadFile(bgPidfile)
|
daemonPidBytes, err := os.ReadFile(bgPidfile)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
daemonPid := strings.Trim(string(daemonPidBytes), " \n")
|
daemonPid := strings.Trim(string(daemonPidBytes), " \n")
|
||||||
logger.Debug("daemon pid: %s", daemonPid)
|
logger.Debug("daemon pid: %s", daemonPid)
|
||||||
@ -192,7 +192,7 @@ sleep 30
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("Rsync Memory Should Be Limited", func() {
|
Convey("Rsync Memory Should Be Limited", func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "myrsync")
|
scriptFile := filepath.Join(tmpDir, "myrsync")
|
||||||
@ -224,11 +224,11 @@ sleep 30
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
cgpath = filepath.Join(cgcf.BasePath, group)
|
cgpath = filepath.Join(cgcf.BasePath, group)
|
||||||
}
|
}
|
||||||
memoLimit, err := ioutil.ReadFile(filepath.Join(cgpath, "memory.max"))
|
memoLimit, err := os.ReadFile(filepath.Join(cgpath, "memory.max"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(strings.Trim(string(memoLimit), "\n"), ShouldEqual, strconv.Itoa(512*1024*1024))
|
So(strings.Trim(string(memoLimit), "\n"), ShouldEqual, strconv.Itoa(512*1024*1024))
|
||||||
} else {
|
} else {
|
||||||
for _, subsys := range(cg.cgMgrV1.Subsystems()) {
|
for _, subsys := range cg.cgMgrV1.Subsystems() {
|
||||||
if subsys.Name() == cgv1.Memory {
|
if subsys.Name() == cgv1.Memory {
|
||||||
cgpath := filepath.Join(cgcf.Group, provider.Name())
|
cgpath := filepath.Join(cgcf.Group, provider.Name())
|
||||||
if useCurrentCgroup {
|
if useCurrentCgroup {
|
||||||
@ -236,7 +236,7 @@ sleep 30
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
cgpath = p
|
cgpath = p
|
||||||
}
|
}
|
||||||
memoLimit, err := ioutil.ReadFile(filepath.Join(cgcf.BasePath, "memory", cgpath, "memory.limit_in_bytes"))
|
memoLimit, err := os.ReadFile(filepath.Join(cgcf.BasePath, "memory", cgpath, "memory.limit_in_bytes"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(strings.Trim(string(memoLimit), "\n"), ShouldEqual, strconv.Itoa(512*1024*1024))
|
So(strings.Trim(string(memoLimit), "\n"), ShouldEqual, strconv.Itoa(512*1024*1024))
|
||||||
}
|
}
|
||||||
@ -248,9 +248,9 @@ sleep 30
|
|||||||
Reset(func() {
|
Reset(func() {
|
||||||
if cgcf.isUnified {
|
if cgcf.isUnified {
|
||||||
if cgcf.Group == "" {
|
if cgcf.Group == "" {
|
||||||
wkrg, err := cgv2.NestedGroupPath("");
|
wkrg, err := cgv2.NestedGroupPath("")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
wkrMgr, err := cgv2.LoadManager("/sys/fs/cgroup", wkrg);
|
wkrMgr, _ := cgv2.Load(wkrg)
|
||||||
allCtrls, err := wkrMgr.Controllers()
|
allCtrls, err := wkrMgr.Controllers()
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
err = wkrMgr.ToggleControllers(allCtrls, cgv2.Disable)
|
err = wkrMgr.ToggleControllers(allCtrls, cgv2.Disable)
|
||||||
@ -263,7 +263,7 @@ sleep 30
|
|||||||
if len(procs) == 0 {
|
if len(procs) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, p := range(procs) {
|
for _, p := range procs {
|
||||||
if err := origMgr.AddProc(p); err != nil {
|
if err := origMgr.AddProc(p); err != nil {
|
||||||
if errors.Is(err, syscall.ESRCH) {
|
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")
|
||||||
@ -278,9 +278,9 @@ sleep 30
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if cgcf.Group == "" {
|
if cgcf.Group == "" {
|
||||||
pather := (func(p cgv1.Path) (cgv1.Path){
|
pather := (func(p cgv1.Path) cgv1.Path {
|
||||||
return func(subsys cgv1.Name) (string, error) {
|
return func(subsys cgv1.Name) (string, error) {
|
||||||
path, err := p(subsys);
|
path, err := p(subsys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -290,20 +290,20 @@ sleep 30
|
|||||||
return path, err
|
return path, err
|
||||||
}
|
}
|
||||||
})(cgv1.NestedPath(""))
|
})(cgv1.NestedPath(""))
|
||||||
wkrMgr, err := cgv1.Load(cgv1.V1, pather, func(cfg *cgv1.InitConfig) error{
|
wkrMgr, err := cgv1.Load(pather, func(cfg *cgv1.InitConfig) error {
|
||||||
cfg.InitCheck = cgv1.AllowAny
|
cfg.InitCheck = cgv1.AllowAny
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
origMgr := cgcf.cgMgrV1
|
origMgr := cgcf.cgMgrV1
|
||||||
for _, subsys := range(wkrMgr.Subsystems()){
|
for _, subsys := range wkrMgr.Subsystems() {
|
||||||
for {
|
for {
|
||||||
procs, err := wkrMgr.Processes(subsys.Name(), false)
|
procs, err := wkrMgr.Processes(subsys.Name(), false)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
if len(procs) == 0 {
|
if len(procs) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, proc := range(procs) {
|
for _, proc := range procs {
|
||||||
if err := origMgr.Add(proc); err != nil {
|
if err := origMgr.Add(proc); err != nil {
|
||||||
if errors.Is(err, syscall.ESRCH) {
|
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")
|
||||||
|
@ -6,10 +6,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/imdario/mergo"
|
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||||
|
cgv2 "github.com/containerd/cgroups/v3/cgroup2"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
cgv1 "github.com/containerd/cgroups"
|
"github.com/imdario/mergo"
|
||||||
cgv2 "github.com/containerd/cgroups/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type providerEnum uint8
|
type providerEnum uint8
|
||||||
@ -58,8 +58,14 @@ type globalConfig struct {
|
|||||||
Retry int `toml:"retry"`
|
Retry int `toml:"retry"`
|
||||||
Timeout int `toml:"timeout"`
|
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"`
|
ExecOnSuccess []string `toml:"exec_on_success"`
|
||||||
ExecOnFailure []string `toml:"exec_on_failure"`
|
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 {
|
type managerConfig struct {
|
||||||
@ -162,10 +168,13 @@ type mirrorConfig struct {
|
|||||||
ExecOnSuccess []string `toml:"exec_on_success"`
|
ExecOnSuccess []string `toml:"exec_on_success"`
|
||||||
ExecOnFailure []string `toml:"exec_on_failure"`
|
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"`
|
ExecOnSuccessExtra []string `toml:"exec_on_success_extra"`
|
||||||
ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
|
ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
|
||||||
|
|
||||||
|
// will be merged with global option
|
||||||
|
SuccessExitCodes []int `toml:"success_exit_codes"`
|
||||||
|
|
||||||
Command string `toml:"command"`
|
Command string `toml:"command"`
|
||||||
FailOnMatch string `toml:"fail_on_match"`
|
FailOnMatch string `toml:"fail_on_match"`
|
||||||
SizePattern string `toml:"size_pattern"`
|
SizePattern string `toml:"size_pattern"`
|
||||||
@ -178,6 +187,7 @@ type mirrorConfig struct {
|
|||||||
RsyncTimeout int `toml:"rsync_timeout"`
|
RsyncTimeout int `toml:"rsync_timeout"`
|
||||||
RsyncOptions []string `toml:"rsync_options"`
|
RsyncOptions []string `toml:"rsync_options"`
|
||||||
RsyncOverride []string `toml:"rsync_override"`
|
RsyncOverride []string `toml:"rsync_override"`
|
||||||
|
RsyncOverrideOnly bool `toml:"rsync_override_only"` // only use provided overridden options if true
|
||||||
Stage1Profile string `toml:"stage1_profile"`
|
Stage1Profile string `toml:"stage1_profile"`
|
||||||
|
|
||||||
MemoryLimit MemBytes `toml:"memory_limit"`
|
MemoryLimit MemBytes `toml:"memory_limit"`
|
||||||
|
@ -53,6 +53,7 @@ func diffMirrorConfig(oldList, newList []mirrorConfig) []mirrorCfgTrans {
|
|||||||
sort.Sort(sortableMirrorList(oList))
|
sort.Sort(sortableMirrorList(oList))
|
||||||
sort.Sort(sortableMirrorList(nList))
|
sort.Sort(sortableMirrorList(nList))
|
||||||
|
|
||||||
|
if len(oList) != 0 && len(nList) != 0 {
|
||||||
// insert a tail node to both lists
|
// insert a tail node to both lists
|
||||||
// as the maximum node
|
// as the maximum node
|
||||||
lastOld, lastNew := oList[len(oList)-1], nList[len(nList)-1]
|
lastOld, lastNew := oList[len(oList)-1], nList[len(nList)-1]
|
||||||
@ -83,6 +84,14 @@ func diffMirrorConfig(oldList, newList []mirrorConfig) []mirrorCfgTrans {
|
|||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for i := 0; i < len(oList); i++ {
|
||||||
|
operations = append(operations, mirrorCfgTrans{diffDelete, oList[i]})
|
||||||
|
}
|
||||||
|
for i := 0; i < len(nList); i++ {
|
||||||
|
operations = append(operations, mirrorCfgTrans{diffAdd, nList[i]})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return operations
|
return operations
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,12 @@ import (
|
|||||||
func TestConfigDiff(t *testing.T) {
|
func TestConfigDiff(t *testing.T) {
|
||||||
Convey("When old and new configs are equal", t, func() {
|
Convey("When old and new configs are equal", t, func() {
|
||||||
oldList := []mirrorConfig{
|
oldList := []mirrorConfig{
|
||||||
mirrorConfig{Name: "debian"},
|
{Name: "debian"},
|
||||||
mirrorConfig{Name: "debian-security"},
|
{Name: "debian-security"},
|
||||||
mirrorConfig{Name: "fedora"},
|
{Name: "fedora"},
|
||||||
mirrorConfig{Name: "archlinux"},
|
{Name: "archlinux"},
|
||||||
mirrorConfig{Name: "AOSP"},
|
{Name: "AOSP"},
|
||||||
mirrorConfig{Name: "ubuntu"},
|
{Name: "ubuntu"},
|
||||||
}
|
}
|
||||||
newList := make([]mirrorConfig, len(oldList))
|
newList := make([]mirrorConfig, len(oldList))
|
||||||
copy(newList, oldList)
|
copy(newList, oldList)
|
||||||
@ -23,21 +23,49 @@ func TestConfigDiff(t *testing.T) {
|
|||||||
difference := diffMirrorConfig(oldList, newList)
|
difference := diffMirrorConfig(oldList, newList)
|
||||||
So(len(difference), ShouldEqual, 0)
|
So(len(difference), ShouldEqual, 0)
|
||||||
})
|
})
|
||||||
|
Convey("When old config is empty", t, func() {
|
||||||
|
newList := []mirrorConfig{
|
||||||
|
{Name: "debian"},
|
||||||
|
{Name: "debian-security"},
|
||||||
|
{Name: "fedora"},
|
||||||
|
{Name: "archlinux"},
|
||||||
|
{Name: "AOSP"},
|
||||||
|
{Name: "ubuntu"},
|
||||||
|
}
|
||||||
|
oldList := make([]mirrorConfig, 0)
|
||||||
|
|
||||||
|
difference := diffMirrorConfig(oldList, newList)
|
||||||
|
So(len(difference), ShouldEqual, len(newList))
|
||||||
|
})
|
||||||
|
Convey("When new config is empty", t, func() {
|
||||||
|
oldList := []mirrorConfig{
|
||||||
|
{Name: "debian"},
|
||||||
|
{Name: "debian-security"},
|
||||||
|
{Name: "fedora"},
|
||||||
|
{Name: "archlinux"},
|
||||||
|
{Name: "AOSP"},
|
||||||
|
{Name: "ubuntu"},
|
||||||
|
}
|
||||||
|
newList := make([]mirrorConfig, 0)
|
||||||
|
|
||||||
|
difference := diffMirrorConfig(oldList, newList)
|
||||||
|
So(len(difference), ShouldEqual, len(oldList))
|
||||||
|
})
|
||||||
Convey("When giving two config lists with different names", t, func() {
|
Convey("When giving two config lists with different names", t, func() {
|
||||||
oldList := []mirrorConfig{
|
oldList := []mirrorConfig{
|
||||||
mirrorConfig{Name: "debian"},
|
{Name: "debian"},
|
||||||
mirrorConfig{Name: "debian-security"},
|
{Name: "debian-security"},
|
||||||
mirrorConfig{Name: "fedora"},
|
{Name: "fedora"},
|
||||||
mirrorConfig{Name: "archlinux"},
|
{Name: "archlinux"},
|
||||||
mirrorConfig{Name: "AOSP", Env: map[string]string{"REPO": "/usr/bin/repo"}},
|
{Name: "AOSP", Env: map[string]string{"REPO": "/usr/bin/repo"}},
|
||||||
mirrorConfig{Name: "ubuntu"},
|
{Name: "ubuntu"},
|
||||||
}
|
}
|
||||||
newList := []mirrorConfig{
|
newList := []mirrorConfig{
|
||||||
mirrorConfig{Name: "debian"},
|
{Name: "debian"},
|
||||||
mirrorConfig{Name: "debian-cd"},
|
{Name: "debian-cd"},
|
||||||
mirrorConfig{Name: "archlinuxcn"},
|
{Name: "archlinuxcn"},
|
||||||
mirrorConfig{Name: "AOSP", Env: map[string]string{"REPO": "/usr/local/bin/aosp-repo"}},
|
{Name: "AOSP", Env: map[string]string{"REPO": "/usr/local/bin/aosp-repo"}},
|
||||||
mirrorConfig{Name: "ubuntu-ports"},
|
{Name: "ubuntu-ports"},
|
||||||
}
|
}
|
||||||
|
|
||||||
difference := diffMirrorConfig(oldList, newList)
|
difference := diffMirrorConfig(oldList, newList)
|
||||||
|
@ -2,11 +2,11 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
@ -76,11 +76,11 @@ exec_on_failure = [
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("Everything should work on valid config file", t, func() {
|
Convey("Everything should work on valid config file", t, func() {
|
||||||
tmpfile, err := ioutil.TempFile("", "tunasync")
|
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ exec_on_failure = [
|
|||||||
|
|
||||||
curCfgBlob := cfgBlob + incSection
|
curCfgBlob := cfgBlob + incSection
|
||||||
|
|
||||||
err = ioutil.WriteFile(tmpfile.Name(), []byte(curCfgBlob), 0644)
|
err = os.WriteFile(tmpfile.Name(), []byte(curCfgBlob), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer tmpfile.Close()
|
defer tmpfile.Close()
|
||||||
|
|
||||||
@ -116,9 +116,9 @@ provider = "two-stage-rsync"
|
|||||||
stage1_profile = "debian"
|
stage1_profile = "debian"
|
||||||
use_ipv6 = true
|
use_ipv6 = true
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "debian.conf"), []byte(incBlob1), 0644)
|
err = os.WriteFile(filepath.Join(tmpDir, "debian.conf"), []byte(incBlob1), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "ubuntu.conf"), []byte(incBlob2), 0644)
|
err = os.WriteFile(filepath.Join(tmpDir, "ubuntu.conf"), []byte(incBlob2), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
|
|
||||||
cfg, err := LoadConfig(tmpfile.Name())
|
cfg, err := LoadConfig(tmpfile.Name())
|
||||||
@ -170,11 +170,11 @@ use_ipv6 = true
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("Everything should work on nested config file", t, func() {
|
Convey("Everything should work on nested config file", t, func() {
|
||||||
tmpfile, err := ioutil.TempFile("", "tunasync")
|
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ use_ipv6 = true
|
|||||||
|
|
||||||
curCfgBlob := cfgBlob + incSection
|
curCfgBlob := cfgBlob + incSection
|
||||||
|
|
||||||
err = ioutil.WriteFile(tmpfile.Name(), []byte(curCfgBlob), 0644)
|
err = os.WriteFile(tmpfile.Name(), []byte(curCfgBlob), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer tmpfile.Close()
|
defer tmpfile.Close()
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ use_ipv6 = true
|
|||||||
provider = "rsync"
|
provider = "rsync"
|
||||||
upstream = "rsync://test.host3/debian-cd/"
|
upstream = "rsync://test.host3/debian-cd/"
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "nest.conf"), []byte(incBlob1), 0644)
|
err = os.WriteFile(filepath.Join(tmpDir, "nest.conf"), []byte(incBlob1), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
|
|
||||||
cfg, err := LoadConfig(tmpfile.Name())
|
cfg, err := LoadConfig(tmpfile.Name())
|
||||||
@ -266,11 +266,11 @@ use_ipv6 = true
|
|||||||
So(len(cfg.Mirrors), ShouldEqual, 6)
|
So(len(cfg.Mirrors), ShouldEqual, 6)
|
||||||
})
|
})
|
||||||
Convey("Providers can be inited from a valid config file", t, func() {
|
Convey("Providers can be inited from a valid config file", t, func() {
|
||||||
tmpfile, err := ioutil.TempFile("", "tunasync")
|
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
err = ioutil.WriteFile(tmpfile.Name(), []byte(cfgBlob), 0644)
|
err = os.WriteFile(tmpfile.Name(), []byte(cfgBlob), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer tmpfile.Close()
|
defer tmpfile.Close()
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ use_ipv6 = true
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("MirrorSubdir should work", t, func() {
|
Convey("MirrorSubdir should work", t, func() {
|
||||||
tmpfile, err := ioutil.TempFile("", "tunasync")
|
tmpfile, err := os.CreateTemp("", "tunasync")
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ use_ipv6 = true
|
|||||||
provider = "rsync"
|
provider = "rsync"
|
||||||
upstream = "rsync://test.host3/debian-cd/"
|
upstream = "rsync://test.host3/debian-cd/"
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(tmpfile.Name(), []byte(cfgBlob1), 0644)
|
err = os.WriteFile(tmpfile.Name(), []byte(cfgBlob1), 0644)
|
||||||
So(err, ShouldEqual, nil)
|
So(err, ShouldEqual, nil)
|
||||||
defer tmpfile.Close()
|
defer tmpfile.Close()
|
||||||
|
|
||||||
@ -403,4 +403,178 @@ use_ipv6 = true
|
|||||||
So(rp.WorkingDir(), ShouldEqual, "/data/mirrors/debian-cd")
|
So(rp.WorkingDir(), ShouldEqual, "/data/mirrors/debian-cd")
|
||||||
So(p.Timeout(), ShouldEqual, 86400*time.Second)
|
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})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
|
|
||||||
"github.com/codeskyblue/go-sh"
|
"github.com/codeskyblue/go-sh"
|
||||||
@ -40,7 +40,7 @@ func getDockerByName(name string) (string, error) {
|
|||||||
|
|
||||||
func TestDocker(t *testing.T) {
|
func TestDocker(t *testing.T) {
|
||||||
Convey("Docker Should Work", t, func(ctx C) {
|
Convey("Docker Should Work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
cmdScript := filepath.Join(tmpDir, "cmd.sh")
|
cmdScript := filepath.Join(tmpDir, "cmd.sh")
|
||||||
@ -64,7 +64,7 @@ func TestDocker(t *testing.T) {
|
|||||||
echo ${TEST_CONTENT}
|
echo ${TEST_CONTENT}
|
||||||
sleep 20
|
sleep 20
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(cmdScript, []byte(cmdScriptContent), 0755)
|
err = os.WriteFile(cmdScript, []byte(cmdScriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
provider, err := newCmdProvider(c)
|
provider, err := newCmdProvider(c)
|
||||||
@ -125,7 +125,7 @@ sleep 20
|
|||||||
So(names, ShouldEqual, "")
|
So(names, ShouldEqual, "")
|
||||||
|
|
||||||
// check log content
|
// check log content
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput+"\n")
|
So(string(loggedContent), ShouldEqual, expectedOutput+"\n")
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package worker
|
package worker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -13,7 +12,7 @@ import (
|
|||||||
|
|
||||||
func TestExecPost(t *testing.T) {
|
func TestExecPost(t *testing.T) {
|
||||||
Convey("ExecPost should work", t, func(ctx C) {
|
Convey("ExecPost should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
||||||
@ -46,7 +45,7 @@ echo $TUNASYNC_UPSTREAM_URL
|
|||||||
echo $TUNASYNC_LOG_FILE
|
echo $TUNASYNC_LOG_FILE
|
||||||
`
|
`
|
||||||
|
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
go job.Run(managerChan, semaphore)
|
go job.Run(managerChan, semaphore)
|
||||||
@ -64,7 +63,7 @@ echo $TUNASYNC_LOG_FILE
|
|||||||
|
|
||||||
expectedOutput := "success\n"
|
expectedOutput := "success\n"
|
||||||
|
|
||||||
outputContent, err := ioutil.ReadFile(filepath.Join(provider.WorkingDir(), "exit_status"))
|
outputContent, err := os.ReadFile(filepath.Join(provider.WorkingDir(), "exit_status"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(outputContent), ShouldEqual, expectedOutput)
|
So(string(outputContent), ShouldEqual, expectedOutput)
|
||||||
})
|
})
|
||||||
@ -85,7 +84,7 @@ echo $TUNASYNC_LOG_FILE
|
|||||||
exit 1
|
exit 1
|
||||||
`
|
`
|
||||||
|
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
go job.Run(managerChan, semaphore)
|
go job.Run(managerChan, semaphore)
|
||||||
@ -105,7 +104,7 @@ exit 1
|
|||||||
|
|
||||||
expectedOutput := "failure\n"
|
expectedOutput := "failure\n"
|
||||||
|
|
||||||
outputContent, err := ioutil.ReadFile(filepath.Join(provider.WorkingDir(), "exit_status"))
|
outputContent, err := os.ReadFile(filepath.Join(provider.WorkingDir(), "exit_status"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(outputContent), ShouldEqual, expectedOutput)
|
So(string(outputContent), ShouldEqual, expectedOutput)
|
||||||
})
|
})
|
||||||
|
@ -87,10 +87,12 @@ func (m *mirrorJob) SetProvider(provider mirrorProvider) error {
|
|||||||
|
|
||||||
// runMirrorJob is the goroutine where syncing job runs in
|
// runMirrorJob is the goroutine where syncing job runs in
|
||||||
// arguments:
|
// arguments:
|
||||||
|
//
|
||||||
// provider: mirror provider object
|
// provider: mirror provider object
|
||||||
// ctrlChan: receives messages from the manager
|
// ctrlChan: receives messages from the manager
|
||||||
// managerChan: push messages to the manager, this channel should have a larger buffer
|
// managerChan: push messages to the manager, this channel should have a larger buffer
|
||||||
// sempaphore: make sure the concurrent running syncing job won't explode
|
// sempaphore: make sure the concurrent running syncing job won't explode
|
||||||
|
//
|
||||||
// TODO: message struct for managerChan
|
// TODO: message struct for managerChan
|
||||||
func (m *mirrorJob) Run(managerChan chan<- jobMessage, semaphore chan empty) error {
|
func (m *mirrorJob) Run(managerChan chan<- jobMessage, semaphore chan empty) error {
|
||||||
jobsDone.Add(1)
|
jobsDone.Add(1)
|
||||||
|
@ -2,7 +2,6 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -17,7 +16,7 @@ func TestMirrorJob(t *testing.T) {
|
|||||||
InitLogger(true, true, false)
|
InitLogger(true, true, false)
|
||||||
|
|
||||||
Convey("MirrorJob should work", t, func(ctx C) {
|
Convey("MirrorJob should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
||||||
@ -58,9 +57,9 @@ func TestMirrorJob(t *testing.T) {
|
|||||||
provider.upstreamURL,
|
provider.upstreamURL,
|
||||||
provider.LogFile(),
|
provider.LogFile(),
|
||||||
)
|
)
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
readedScriptContent, err := ioutil.ReadFile(scriptFile)
|
readedScriptContent, err := os.ReadFile(scriptFile)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ func TestMirrorJob(t *testing.T) {
|
|||||||
So(msg.status, ShouldEqual, Syncing)
|
So(msg.status, ShouldEqual, Syncing)
|
||||||
msg = <-managerChan
|
msg = <-managerChan
|
||||||
So(msg.status, ShouldEqual, Success)
|
So(msg.status, ShouldEqual, Success)
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
job.ctrlChan <- jobStart
|
job.ctrlChan <- jobStart
|
||||||
@ -123,11 +122,11 @@ sleep 3
|
|||||||
echo $TUNASYNC_WORKING_DIR
|
echo $TUNASYNC_WORKING_DIR
|
||||||
echo '------'
|
echo '------'
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
hookScriptFile := filepath.Join(tmpDir, "hook.sh")
|
hookScriptFile := filepath.Join(tmpDir, "hook.sh")
|
||||||
err = ioutil.WriteFile(hookScriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(hookScriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
h, err := newExecPostHook(provider, execOnFailure, hookScriptFile)
|
h, err := newExecPostHook(provider, execOnFailure, hookScriptFile)
|
||||||
@ -188,7 +187,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
sleep 5
|
sleep 5
|
||||||
echo $TUNASYNC_WORKING_DIR
|
echo $TUNASYNC_WORKING_DIR
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
managerChan := make(chan jobMessage, 10)
|
managerChan := make(chan jobMessage, 10)
|
||||||
@ -213,7 +212,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
So(msg.status, ShouldEqual, Failed)
|
So(msg.status, ShouldEqual, Failed)
|
||||||
|
|
||||||
expectedOutput := fmt.Sprintf("%s\n", provider.WorkingDir())
|
expectedOutput := fmt.Sprintf("%s\n", provider.WorkingDir())
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
job.ctrlChan <- jobDisable
|
job.ctrlChan <- jobDisable
|
||||||
@ -236,7 +235,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
provider.WorkingDir(), provider.WorkingDir(),
|
provider.WorkingDir(), provider.WorkingDir(),
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
job.ctrlChan <- jobDisable
|
job.ctrlChan <- jobDisable
|
||||||
@ -270,7 +269,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
provider.WorkingDir(), provider.WorkingDir(),
|
provider.WorkingDir(), provider.WorkingDir(),
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
job.ctrlChan <- jobDisable
|
job.ctrlChan <- jobDisable
|
||||||
@ -326,7 +325,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
provider.WorkingDir(), provider.WorkingDir(),
|
provider.WorkingDir(), provider.WorkingDir(),
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
|
|
||||||
@ -341,7 +340,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
sleep 10
|
sleep 10
|
||||||
echo $TUNASYNC_WORKING_DIR
|
echo $TUNASYNC_WORKING_DIR
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
managerChan := make(chan jobMessage, 10)
|
managerChan := make(chan jobMessage, 10)
|
||||||
@ -364,7 +363,7 @@ echo $TUNASYNC_WORKING_DIR
|
|||||||
So(msg.status, ShouldEqual, Failed)
|
So(msg.status, ShouldEqual, Failed)
|
||||||
|
|
||||||
expectedOutput := fmt.Sprintf("%s\n", provider.WorkingDir())
|
expectedOutput := fmt.Sprintf("%s\n", provider.WorkingDir())
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
job.ctrlChan <- jobDisable
|
job.ctrlChan <- jobDisable
|
||||||
@ -404,7 +403,7 @@ func TestConcurrentMirrorJobs(t *testing.T) {
|
|||||||
InitLogger(true, true, false)
|
InitLogger(true, true, false)
|
||||||
|
|
||||||
Convey("Concurrent MirrorJobs should work", t, func(ctx C) {
|
Convey("Concurrent MirrorJobs should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@ -39,7 +38,7 @@ func (l *logLimiter) preExec() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logDir := p.LogDir()
|
logDir := p.LogDir()
|
||||||
files, err := ioutil.ReadDir(logDir)
|
files, err := os.ReadDir(logDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
os.MkdirAll(logDir, 0755)
|
os.MkdirAll(logDir, 0755)
|
||||||
@ -50,7 +49,8 @@ func (l *logLimiter) preExec() error {
|
|||||||
matchedFiles := []os.FileInfo{}
|
matchedFiles := []os.FileInfo{}
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if strings.HasPrefix(f.Name(), p.Name()) {
|
if strings.HasPrefix(f.Name(), p.Name()) {
|
||||||
matchedFiles = append(matchedFiles, f)
|
info, _ := f.Info()
|
||||||
|
matchedFiles = append(matchedFiles, info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -14,8 +13,8 @@ import (
|
|||||||
|
|
||||||
func TestLogLimiter(t *testing.T) {
|
func TestLogLimiter(t *testing.T) {
|
||||||
Convey("LogLimiter should work", t, func(ctx C) {
|
Convey("LogLimiter should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, _ := os.MkdirTemp("", "tunasync")
|
||||||
tmpLogDir, err := ioutil.TempDir("", "tunasync-log")
|
tmpLogDir, err := os.MkdirTemp("", "tunasync-log")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
defer os.RemoveAll(tmpLogDir)
|
defer os.RemoveAll(tmpLogDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -58,7 +57,7 @@ echo $TUNASYNC_UPSTREAM_URL
|
|||||||
echo $TUNASYNC_LOG_FILE
|
echo $TUNASYNC_LOG_FILE
|
||||||
`
|
`
|
||||||
|
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
go job.Run(managerChan, semaphore)
|
go job.Run(managerChan, semaphore)
|
||||||
@ -86,7 +85,7 @@ echo $TUNASYNC_LOG_FILE
|
|||||||
logFile,
|
logFile,
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(filepath.Join(provider.LogDir(), "latest"))
|
loggedContent, err := os.ReadFile(filepath.Join(provider.LogDir(), "latest"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
})
|
})
|
||||||
@ -104,7 +103,7 @@ echo $TUNASYNC_LOG_FILE
|
|||||||
sleep 5
|
sleep 5
|
||||||
`
|
`
|
||||||
|
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
go job.Run(managerChan, semaphore)
|
go job.Run(managerChan, semaphore)
|
||||||
@ -134,10 +133,10 @@ sleep 5
|
|||||||
logFile,
|
logFile,
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(filepath.Join(provider.LogDir(), "latest"))
|
loggedContent, err := os.ReadFile(filepath.Join(provider.LogDir(), "latest"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
loggedContent, err = ioutil.ReadFile(logFile + ".fail")
|
loggedContent, err = os.ReadFile(logFile + ".fail")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
})
|
})
|
||||||
|
@ -60,6 +60,10 @@ type mirrorProvider interface {
|
|||||||
ExitContext() *Context
|
ExitContext() *Context
|
||||||
// return context
|
// return context
|
||||||
Context() *Context
|
Context() *Context
|
||||||
|
|
||||||
|
// set in newMirrorProvider, used by cmdJob.Wait
|
||||||
|
SetSuccessExitCodes(codes []int)
|
||||||
|
GetSuccessExitCodes() []int
|
||||||
}
|
}
|
||||||
|
|
||||||
// newProvider creates a mirrorProvider instance
|
// newProvider creates a mirrorProvider instance
|
||||||
@ -142,7 +146,9 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider {
|
|||||||
extraOptions: mirror.RsyncOptions,
|
extraOptions: mirror.RsyncOptions,
|
||||||
rsyncNeverTimeout: mirror.RsyncNoTimeo,
|
rsyncNeverTimeout: mirror.RsyncNoTimeo,
|
||||||
rsyncTimeoutValue: mirror.RsyncTimeout,
|
rsyncTimeoutValue: mirror.RsyncTimeout,
|
||||||
|
globalOptions: cfg.Global.RsyncOptions,
|
||||||
overriddenOptions: mirror.RsyncOverride,
|
overriddenOptions: mirror.RsyncOverride,
|
||||||
|
useOverrideOnly: mirror.RsyncOverrideOnly,
|
||||||
rsyncEnv: mirror.Env,
|
rsyncEnv: mirror.Env,
|
||||||
workingDir: mirrorDir,
|
workingDir: mirrorDir,
|
||||||
logDir: logDir,
|
logDir: logDir,
|
||||||
@ -247,5 +253,17 @@ func newMirrorProvider(mirror mirrorConfig, cfg *Config) mirrorProvider {
|
|||||||
}
|
}
|
||||||
addHookFromCmdList(mirror.ExecOnFailureExtra, execOnFailure)
|
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
|
return provider
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -14,7 +13,7 @@ import (
|
|||||||
|
|
||||||
func TestRsyncProvider(t *testing.T) {
|
func TestRsyncProvider(t *testing.T) {
|
||||||
Convey("Rsync Provider should work", t, func() {
|
Convey("Rsync Provider should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "myrsync")
|
scriptFile := filepath.Join(tmpDir, "myrsync")
|
||||||
@ -80,7 +79,7 @@ echo "Total file size: 1.33T bytes"
|
|||||||
echo "Done"
|
echo "Done"
|
||||||
exit 0
|
exit 0
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
|
targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
|
||||||
@ -100,7 +99,7 @@ exit 0
|
|||||||
|
|
||||||
err = provider.Run(make(chan empty, 1))
|
err = provider.Run(make(chan empty, 1))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
// fmt.Println(string(loggedContent))
|
// fmt.Println(string(loggedContent))
|
||||||
@ -109,7 +108,7 @@ exit 0
|
|||||||
|
|
||||||
})
|
})
|
||||||
Convey("If the rsync program fails", t, func() {
|
Convey("If the rsync program fails", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
tmpFile := filepath.Join(tmpDir, "log_file")
|
tmpFile := filepath.Join(tmpDir, "log_file")
|
||||||
@ -131,7 +130,7 @@ exit 0
|
|||||||
|
|
||||||
err = provider.Run(make(chan empty, 1))
|
err = provider.Run(make(chan empty, 1))
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldContainSubstring, "Syntax or usage error")
|
So(string(loggedContent), ShouldContainSubstring, "Syntax or usage error")
|
||||||
})
|
})
|
||||||
@ -140,7 +139,7 @@ exit 0
|
|||||||
|
|
||||||
func TestRsyncProviderWithAuthentication(t *testing.T) {
|
func TestRsyncProviderWithAuthentication(t *testing.T) {
|
||||||
Convey("Rsync Provider with password should work", t, func() {
|
Convey("Rsync Provider with password should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "myrsync")
|
scriptFile := filepath.Join(tmpDir, "myrsync")
|
||||||
@ -180,7 +179,7 @@ sleep 1
|
|||||||
echo "Done"
|
echo "Done"
|
||||||
exit 0
|
exit 0
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
|
targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
|
||||||
@ -200,7 +199,7 @@ exit 0
|
|||||||
|
|
||||||
err = provider.Run(make(chan empty, 1))
|
err = provider.Run(make(chan empty, 1))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
// fmt.Println(string(loggedContent))
|
// fmt.Println(string(loggedContent))
|
||||||
@ -211,7 +210,7 @@ exit 0
|
|||||||
|
|
||||||
func TestRsyncProviderWithOverriddenOptions(t *testing.T) {
|
func TestRsyncProviderWithOverriddenOptions(t *testing.T) {
|
||||||
Convey("Rsync Provider with overridden options should work", t, func() {
|
Convey("Rsync Provider with overridden options should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "myrsync")
|
scriptFile := filepath.Join(tmpDir, "myrsync")
|
||||||
@ -248,7 +247,7 @@ sleep 1
|
|||||||
echo "Done"
|
echo "Done"
|
||||||
exit 0
|
exit 0
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
|
targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
|
||||||
@ -263,7 +262,7 @@ exit 0
|
|||||||
|
|
||||||
err = provider.Run(make(chan empty, 1))
|
err = provider.Run(make(chan empty, 1))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
// fmt.Println(string(loggedContent))
|
// fmt.Println(string(loggedContent))
|
||||||
@ -274,7 +273,7 @@ exit 0
|
|||||||
|
|
||||||
func TestRsyncProviderWithDocker(t *testing.T) {
|
func TestRsyncProviderWithDocker(t *testing.T) {
|
||||||
Convey("Rsync in Docker should work", t, func() {
|
Convey("Rsync in Docker should work", t, func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "myrsync")
|
scriptFile := filepath.Join(tmpDir, "myrsync")
|
||||||
@ -323,9 +322,9 @@ fi
|
|||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(cmdScriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(cmdScriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
err = ioutil.WriteFile(excludeFile, []byte("__some_pattern"), 0755)
|
err = os.WriteFile(excludeFile, []byte("__some_pattern"), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
for _, hook := range provider.Hooks() {
|
for _, hook := range provider.Hooks() {
|
||||||
@ -338,7 +337,7 @@ done
|
|||||||
err = hook.postExec()
|
err = hook.postExec()
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
}
|
}
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, "__some_pattern")
|
So(string(loggedContent), ShouldEqual, "__some_pattern")
|
||||||
})
|
})
|
||||||
@ -346,7 +345,7 @@ done
|
|||||||
|
|
||||||
func TestCmdProvider(t *testing.T) {
|
func TestCmdProvider(t *testing.T) {
|
||||||
Convey("Command Provider should work", t, func(ctx C) {
|
Convey("Command Provider should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
scriptFile := filepath.Join(tmpDir, "cmd.sh")
|
||||||
@ -391,25 +390,25 @@ echo $AOSP_REPO_BIN
|
|||||||
provider.LogFile(),
|
provider.LogFile(),
|
||||||
"/usr/local/bin/repo",
|
"/usr/local/bin/repo",
|
||||||
)
|
)
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
readedScriptContent, err := ioutil.ReadFile(scriptFile)
|
readedScriptContent, err := os.ReadFile(scriptFile)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
||||||
|
|
||||||
err = provider.Run(make(chan empty, 1))
|
err = provider.Run(make(chan empty, 1))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("If a command fails", func() {
|
Convey("If a command fails", func() {
|
||||||
scriptContent := `exit 1`
|
scriptContent := `exit 1`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
readedScriptContent, err := ioutil.ReadFile(scriptFile)
|
readedScriptContent, err := os.ReadFile(scriptFile)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
So(readedScriptContent, ShouldResemble, []byte(scriptContent))
|
||||||
|
|
||||||
@ -422,7 +421,7 @@ echo $AOSP_REPO_BIN
|
|||||||
scriptContent := `#!/bin/bash
|
scriptContent := `#!/bin/bash
|
||||||
sleep 10
|
sleep 10
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
started := make(chan empty, 1)
|
started := make(chan empty, 1)
|
||||||
@ -440,7 +439,7 @@ sleep 10
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
Convey("Command Provider without log file should work", t, func(ctx C) {
|
Convey("Command Provider without log file should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -474,7 +473,7 @@ sleep 10
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
Convey("Command Provider with RegExprs should work", t, func(ctx C) {
|
Convey("Command Provider with RegExprs should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
tmpFile := filepath.Join(tmpDir, "log_file")
|
tmpFile := filepath.Join(tmpDir, "log_file")
|
||||||
@ -553,11 +552,64 @@ sleep 10
|
|||||||
So(provider.DataSize(), ShouldBeEmpty)
|
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) {
|
func TestTwoStageRsyncProvider(t *testing.T) {
|
||||||
Convey("TwoStageRsync Provider should work", t, func(ctx C) {
|
Convey("TwoStageRsync Provider should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
scriptFile := filepath.Join(tmpDir, "myrsync")
|
scriptFile := filepath.Join(tmpDir, "myrsync")
|
||||||
@ -597,7 +649,7 @@ sleep 1
|
|||||||
echo "Done"
|
echo "Done"
|
||||||
exit 0
|
exit 0
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = provider.Run(make(chan empty, 2))
|
err = provider.Run(make(chan empty, 2))
|
||||||
@ -614,7 +666,7 @@ exit 0
|
|||||||
targetDir,
|
targetDir,
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"-aHvh --no-o --no-g --stats --filter risk .~tmp~/ --exclude .~tmp~/ --safe-links "+
|
"-aHvh --no-o --no-g --stats --filter risk .~tmp~/ --exclude .~tmp~/ --safe-links "+
|
||||||
"--include=*.diff/ --exclude=*.diff/Index --exclude=Packages* --exclude=Sources* --exclude=Release* --exclude=InRelease --include=i18n/by-hash --exclude=i18n/* --exclude=ls-lR* --timeout=30 -6 "+
|
"--include=*.diff/ --include=by-hash/ --exclude=*.diff/Index --exclude=Contents* --exclude=Packages* --exclude=Sources* --exclude=Release* --exclude=InRelease --exclude=i18n/* --exclude=dep11/* --exclude=installer-*/current --exclude=ls-lR* --timeout=30 -6 "+
|
||||||
"--exclude-from %s %s %s",
|
"--exclude-from %s %s %s",
|
||||||
provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
|
provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
|
||||||
),
|
),
|
||||||
@ -627,7 +679,7 @@ exit 0
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldEqual, expectedOutput)
|
So(string(loggedContent), ShouldEqual, expectedOutput)
|
||||||
// fmt.Println(string(loggedContent))
|
// fmt.Println(string(loggedContent))
|
||||||
@ -639,7 +691,7 @@ echo $@
|
|||||||
sleep 10
|
sleep 10
|
||||||
exit 0
|
exit 0
|
||||||
`
|
`
|
||||||
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
err = os.WriteFile(scriptFile, []byte(scriptContent), 0755)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
started := make(chan empty, 2)
|
started := make(chan empty, 2)
|
||||||
@ -656,12 +708,12 @@ exit 0
|
|||||||
|
|
||||||
expectedOutput := fmt.Sprintf(
|
expectedOutput := fmt.Sprintf(
|
||||||
"-aHvh --no-o --no-g --stats --filter risk .~tmp~/ --exclude .~tmp~/ --safe-links "+
|
"-aHvh --no-o --no-g --stats --filter risk .~tmp~/ --exclude .~tmp~/ --safe-links "+
|
||||||
"--include=*.diff/ --exclude=*.diff/Index --exclude=Packages* --exclude=Sources* --exclude=Release* --exclude=InRelease --include=i18n/by-hash --exclude=i18n/* --exclude=ls-lR* --timeout=30 -6 "+
|
"--include=*.diff/ --include=by-hash/ --exclude=*.diff/Index --exclude=Contents* --exclude=Packages* --exclude=Sources* --exclude=Release* --exclude=InRelease --exclude=i18n/* --exclude=dep11/* --exclude=installer-*/current --exclude=ls-lR* --timeout=30 -6 "+
|
||||||
"--exclude-from %s %s %s\n",
|
"--exclude-from %s %s %s\n",
|
||||||
provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
|
provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
|
||||||
)
|
)
|
||||||
|
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldStartWith, expectedOutput)
|
So(string(loggedContent), ShouldStartWith, expectedOutput)
|
||||||
// fmt.Println(string(loggedContent))
|
// fmt.Println(string(loggedContent))
|
||||||
@ -669,7 +721,7 @@ exit 0
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("If the rsync program fails", t, func(ctx C) {
|
Convey("If the rsync program fails", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, err := os.MkdirTemp("", "tunasync")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
tmpFile := filepath.Join(tmpDir, "log_file")
|
tmpFile := filepath.Join(tmpDir, "log_file")
|
||||||
@ -691,7 +743,7 @@ exit 0
|
|||||||
|
|
||||||
err = provider.Run(make(chan empty, 2))
|
err = provider.Run(make(chan empty, 2))
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
loggedContent, err := ioutil.ReadFile(provider.LogFile())
|
loggedContent, err := os.ReadFile(provider.LogFile())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(loggedContent), ShouldContainSubstring, "Error in socket I/O")
|
So(string(loggedContent), ShouldContainSubstring, "Error in socket I/O")
|
||||||
|
|
||||||
|
@ -14,7 +14,9 @@ type rsyncConfig struct {
|
|||||||
rsyncCmd string
|
rsyncCmd string
|
||||||
upstreamURL, username, password, excludeFile string
|
upstreamURL, username, password, excludeFile string
|
||||||
extraOptions []string
|
extraOptions []string
|
||||||
|
globalOptions []string
|
||||||
overriddenOptions []string
|
overriddenOptions []string
|
||||||
|
useOverrideOnly bool
|
||||||
rsyncNeverTimeout bool
|
rsyncNeverTimeout bool
|
||||||
rsyncTimeoutValue int
|
rsyncTimeoutValue int
|
||||||
rsyncEnv map[string]string
|
rsyncEnv map[string]string
|
||||||
@ -75,6 +77,12 @@ func newRsyncProvider(c rsyncConfig) (*rsyncProvider, error) {
|
|||||||
options = c.overriddenOptions
|
options = c.overriddenOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
if !c.rsyncNeverTimeout {
|
||||||
timeo := 120
|
timeo := 120
|
||||||
if c.rsyncTimeoutValue > 0 {
|
if c.rsyncTimeoutValue > 0 {
|
||||||
@ -92,9 +100,14 @@ func newRsyncProvider(c rsyncConfig) (*rsyncProvider, error) {
|
|||||||
if c.excludeFile != "" {
|
if c.excludeFile != "" {
|
||||||
options = append(options, "--exclude-from", c.excludeFile)
|
options = append(options, "--exclude-from", c.excludeFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.globalOptions != nil {
|
||||||
|
options = append(options, c.globalOptions...)
|
||||||
|
}
|
||||||
if c.extraOptions != nil {
|
if c.extraOptions != nil {
|
||||||
options = append(options, c.extraOptions...)
|
options = append(options, c.extraOptions...)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
provider.options = options
|
provider.options = options
|
||||||
|
|
||||||
provider.ctx.Set(_WorkingDirKey, c.workingDir)
|
provider.ctx.Set(_WorkingDirKey, c.workingDir)
|
||||||
|
@ -5,15 +5,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/codeskyblue/go-sh"
|
"github.com/codeskyblue/go-sh"
|
||||||
|
cgv1 "github.com/containerd/cgroups/v3/cgroup1"
|
||||||
|
"github.com/moby/sys/reexec"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"github.com/moby/moby/pkg/reexec"
|
|
||||||
cgv1 "github.com/containerd/cgroups"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// runner is to run os commands giving command line, env and log file
|
// runner is to run os commands giving command line, env and log file
|
||||||
@ -115,7 +116,7 @@ func (c *cmdJob) Start() error {
|
|||||||
if cg != nil {
|
if cg != nil {
|
||||||
logger.Debugf("Preparing cgroup sync pipes for job %s", c.provider.Name())
|
logger.Debugf("Preparing cgroup sync pipes for job %s", c.provider.Name())
|
||||||
var err error
|
var err error
|
||||||
pipeR, pipeW, err = os.Pipe();
|
pipeR, pipeW, err = os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -171,9 +172,18 @@ func (c *cmdJob) Wait() error {
|
|||||||
return c.retErr
|
return c.retErr
|
||||||
default:
|
default:
|
||||||
err := c.cmd.Wait()
|
err := c.cmd.Wait()
|
||||||
c.retErr = err
|
|
||||||
close(c.finished)
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,20 @@ type twoStageRsyncProvider struct {
|
|||||||
|
|
||||||
// ref: https://salsa.debian.org/mirror-team/archvsync/-/blob/master/bin/ftpsync#L431
|
// ref: https://salsa.debian.org/mirror-team/archvsync/-/blob/master/bin/ftpsync#L431
|
||||||
var rsyncStage1Profiles = map[string]([]string){
|
var rsyncStage1Profiles = map[string]([]string){
|
||||||
"debian": []string{"--include=*.diff/", "--exclude=*.diff/Index", "--exclude=Packages*", "--exclude=Sources*", "--exclude=Release*", "--exclude=InRelease", "--include=i18n/by-hash", "--exclude=i18n/*", "--exclude=ls-lR*"},
|
"debian": []string{
|
||||||
|
"--include=*.diff/",
|
||||||
|
"--include=by-hash/",
|
||||||
|
"--exclude=*.diff/Index",
|
||||||
|
"--exclude=Contents*",
|
||||||
|
"--exclude=Packages*",
|
||||||
|
"--exclude=Sources*",
|
||||||
|
"--exclude=Release*",
|
||||||
|
"--exclude=InRelease",
|
||||||
|
"--exclude=i18n/*",
|
||||||
|
"--exclude=dep11/*",
|
||||||
|
"--exclude=installer-*/current",
|
||||||
|
"--exclude=ls-lR*",
|
||||||
|
},
|
||||||
"debian-oldstyle": []string{
|
"debian-oldstyle": []string{
|
||||||
"--exclude=Packages*", "--exclude=Sources*", "--exclude=Release*",
|
"--exclude=Packages*", "--exclude=Sources*", "--exclude=Release*",
|
||||||
"--exclude=InRelease", "--exclude=i18n/*", "--exclude=ls-lR*", "--exclude=dep11/*",
|
"--exclude=InRelease", "--exclude=i18n/*", "--exclude=ls-lR*", "--exclude=dep11/*",
|
||||||
@ -114,9 +127,7 @@ func (p *twoStageRsyncProvider) Options(stage int) ([]string, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Invalid Stage 1 Profile")
|
return nil, errors.New("Invalid Stage 1 Profile")
|
||||||
}
|
}
|
||||||
for _, exc := range stage1Profile {
|
options = append(options, stage1Profile...)
|
||||||
options = append(options, exc)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if stage == 2 {
|
} else if stage == 2 {
|
||||||
options = append(options, p.stage2Options...)
|
options = append(options, p.stage2Options...)
|
||||||
|
@ -317,7 +317,7 @@ func (w *Worker) runSchedule() {
|
|||||||
schedInfo := w.schedule.GetJobs()
|
schedInfo := w.schedule.GetJobs()
|
||||||
w.updateSchedInfo(schedInfo)
|
w.updateSchedInfo(schedInfo)
|
||||||
|
|
||||||
tick := time.Tick(5 * time.Second)
|
tick := time.NewTicker(5 * time.Second).C
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case jobMsg := <-w.managerChan:
|
case jobMsg := <-w.managerChan:
|
||||||
|
@ -147,7 +147,7 @@ func TestWorker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
Convey("with one job", func(ctx C) {
|
Convey("with one job", func(ctx C) {
|
||||||
workerCfg.Mirrors = []mirrorConfig{
|
workerCfg.Mirrors = []mirrorConfig{
|
||||||
mirrorConfig{
|
{
|
||||||
Name: "job-ls",
|
Name: "job-ls",
|
||||||
Provider: provCommand,
|
Provider: provCommand,
|
||||||
Command: "ls",
|
Command: "ls",
|
||||||
@ -194,17 +194,17 @@ func TestWorker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
Convey("with several jobs", func(ctx C) {
|
Convey("with several jobs", func(ctx C) {
|
||||||
workerCfg.Mirrors = []mirrorConfig{
|
workerCfg.Mirrors = []mirrorConfig{
|
||||||
mirrorConfig{
|
{
|
||||||
Name: "job-ls-1",
|
Name: "job-ls-1",
|
||||||
Provider: provCommand,
|
Provider: provCommand,
|
||||||
Command: "ls",
|
Command: "ls",
|
||||||
},
|
},
|
||||||
mirrorConfig{
|
{
|
||||||
Name: "job-fail",
|
Name: "job-fail",
|
||||||
Provider: provCommand,
|
Provider: provCommand,
|
||||||
Command: "non-existent-command-xxxx",
|
Command: "non-existent-command-xxxx",
|
||||||
},
|
},
|
||||||
mirrorConfig{
|
{
|
||||||
Name: "job-ls-2",
|
Name: "job-ls-2",
|
||||||
Provider: provCommand,
|
Provider: provCommand,
|
||||||
Command: "ls",
|
Command: "ls",
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package worker
|
package worker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -13,7 +12,7 @@ import (
|
|||||||
func TestZFSHook(t *testing.T) {
|
func TestZFSHook(t *testing.T) {
|
||||||
|
|
||||||
Convey("ZFS Hook should work", t, func(ctx C) {
|
Convey("ZFS Hook should work", t, func(ctx C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tunasync")
|
tmpDir, _ := os.MkdirTemp("", "tunasync")
|
||||||
tmpFile := filepath.Join(tmpDir, "log_file")
|
tmpFile := filepath.Join(tmpDir, "log_file")
|
||||||
|
|
||||||
c := cmdConfig{
|
c := cmdConfig{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user