Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30ea465591 | |||
| 3755c97a86 | |||
| d7ede3f82c | |||
| bca37c741c | |||
| 98073c7dca | |||
| f1608aba15 | |||
| dc05cd00f2 | |||
| 2923009689 | |||
| cc0f3b1f13 | |||
| 20abaa2e7f | |||
| 908807bd59 | |||
| b9b9ad10cf | |||
| 904c1512a3 | |||
| 3df5e223be | |||
| b8f55a97ba | |||
| 82adb2b9f5 | |||
| 7b6adab6b1 | |||
| e390aa0c5a | |||
| 5a8f0b9a24 | |||
| 3cb1865909 | |||
| 0ab92d4861 | |||
| 740ab4b1b2 | |||
| 48c5b60024 | |||
| 40fd700855 | |||
| def510abfd | |||
| 08769a8752 | |||
| affe00aefe | |||
| 5615f4929a | |||
| 440b07443f | |||
| e2fcf9ff5b | |||
| a5f6bc3697 | |||
| 9c63736489 | |||
| 830536715e | |||
| ebc46cf1c0 | |||
| 27012e5623 | |||
| 30faaec26a | |||
| 21e0ae63a6 | |||
| 370f40881d | |||
| fb71a7e4b0 | |||
| ef9a63b075 | |||
| faef059edf | |||
| ad9fbf7b6d | |||
| 3bd17b8069 | |||
| 99bf1487ae | |||
| c3b4f01c44 | |||
| 9d5c892023 | |||
| d8d1d25ec2 | |||
| d02d7e5e1d | |||
| 39f8ff62f0 | |||
| 9a434b0e54 | |||
| b5053d2659 | |||
| 0fe2ac6b90 | |||
| 95c924968a | |||
| 523a3bb26b | |||
| 96396b2e86 | |||
| 8749f0bd3d | |||
| bc92660e09 | |||
| 8b0637ddcc | |||
| bbdc6f5465 | |||
| bc5e1ede04 | |||
| 2b3daaf9f1 | |||
| 2b3df7e342 | |||
| 5e4d4188f4 | |||
| 1e8ffe4486 | |||
| 59389b84a2 | |||
| 4fae0bb68e | |||
| 9777a441e9 | |||
| 1a72edea5d | |||
| 96db636582 | |||
| 190ab7c08d | |||
| 6be133f55d | |||
| 5ffd470596 | |||
| 2119dc40ab | |||
| 0df1c4cdcc | |||
| 2658695a35 | |||
| 1ac1635b3d | |||
| 4a2806f6d1 | |||
| 0a264b9b41 | |||
| a3379d6785 | |||
| 6260b75031 | |||
| 3ffb69bfb0 | |||
| 1da8f848f2 | |||
| 6ed4626df9 | |||
| c07f9ec62e | |||
| fd5b0e6831 | |||
| a4cea1b4f3 | |||
| c0b52b92d5 | |||
| 12018b3685 | |||
| a91fb873e4 | |||
| a6aa610165 | |||
| 6c87bdb9fb | |||
| b9250a41a2 |
+135
-214
@@ -1,5 +1,8 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
# NB: this is not the Go version, but the Orb version
|
||||
# https://circleci.com/developer/orbs/orb/circleci/go#usage-go-modules-cache
|
||||
go: circleci/go@1.11.0
|
||||
commands:
|
||||
setup-home-local-bin:
|
||||
steps:
|
||||
@@ -12,132 +15,64 @@ commands:
|
||||
echo "$line" >> $BASH_ENV
|
||||
fi
|
||||
|
||||
invoke-lazy-sh:
|
||||
parameters:
|
||||
subcommand:
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
environment:
|
||||
TERM: xterm
|
||||
command: ./lazy.sh <<parameters.subcommand>>
|
||||
|
||||
apt-update-and-install-common-deps:
|
||||
steps:
|
||||
- run: sudo apt update && sudo apt install gawk make
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install -y gawk make
|
||||
# CircleCI doesn't update its cimg/go images.
|
||||
# So, need to update manually to get up-to-date trust chains.
|
||||
# The need for this was required for cimg/go:1.12, but let's future proof this here and now.
|
||||
- run: sudo apt-get install -y git ca-certificates
|
||||
|
||||
restore-cache-gomod:
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: go-mod-v4-{{ checksum "go.sum" }}
|
||||
save-cache-gomod:
|
||||
steps:
|
||||
- save_cache:
|
||||
key: go-mod-v4-{{ checksum "go.sum" }}
|
||||
paths:
|
||||
- "/go/pkg/mod"
|
||||
|
||||
install-godep:
|
||||
steps:
|
||||
- apt-update-and-install-common-deps
|
||||
- invoke-lazy-sh:
|
||||
subcommand: godep
|
||||
|
||||
install-docdep:
|
||||
steps:
|
||||
- apt-update-and-install-common-deps
|
||||
- run: sudo apt install python3 python3-pip libgirepository1.0-dev
|
||||
- invoke-lazy-sh:
|
||||
subcommand: docdep
|
||||
- run: pip3 install -r docs/requirements.txt
|
||||
|
||||
download-and-install-minio-client:
|
||||
steps:
|
||||
- setup-home-local-bin
|
||||
- restore_cache:
|
||||
key: minio-client-v2
|
||||
- run:
|
||||
shell: /bin/bash -eo pipefail
|
||||
command: |
|
||||
if which mc; then exit 0; fi
|
||||
sudo curl -sSL https://dl.min.io/client/mc/release/linux-amd64/archive/mc.RELEASE.2020-08-20T00-23-01Z \
|
||||
-o "$HOME/.local/bin/mc"
|
||||
sudo chmod +x "$HOME/.local/bin/mc"
|
||||
- save_cache:
|
||||
key: minio-client-v2
|
||||
paths:
|
||||
- "$HOME/.local/bin/mc"
|
||||
|
||||
upload-minio:
|
||||
docs-publish-sh:
|
||||
parameters:
|
||||
src:
|
||||
type: string
|
||||
dst:
|
||||
type: string
|
||||
push:
|
||||
type: boolean
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
shell: /bin/bash -eo pipefail
|
||||
when: always
|
||||
command: |
|
||||
if [ -n "$CIRCLE_PR_NUMBER" ]; then # CIRCLE_PR_NUMBER is guaranteed to be only present in forked PRs (external)
|
||||
echo "Forked PR detected. Sry, can't trust you with credentials to external artifact store, use CircleCI's instead."
|
||||
exit 0
|
||||
fi
|
||||
set -u # from now on
|
||||
git config --global user.email "zreplbot@cschwarz.com"
|
||||
git config --global user.name "zrepl-github-io-ci"
|
||||
|
||||
mc config host add --api s3v4 zrepl-minio https://minio.cschwarz.com ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY}
|
||||
# if we're pushing, we need to add the deploy key
|
||||
# which is stored as "Additional SSH Keys" in the CircleCI project settings.
|
||||
# We can't use the CircleCI-manage deploy key because we're pushing
|
||||
# to a different repo than the one we're building.
|
||||
- when:
|
||||
condition: << parameters.push >>
|
||||
steps:
|
||||
# https://circleci.com/docs/2.0/add-ssh-key/#adding-multiple-keys-with-blank-hostnames
|
||||
- run: ssh-add -D
|
||||
# the default circleci ssh config only additional ssh keys for Host !github.com
|
||||
- run:
|
||||
command: |
|
||||
cat > ~/.ssh/config \<<EOF
|
||||
Host *
|
||||
IdentityFile /home/circleci/.ssh/id_rsa_458e62c517f6c480e40452126ce47421
|
||||
EOF
|
||||
- add_ssh_keys:
|
||||
fingerprints:
|
||||
# deploy key for zrepl.github.io
|
||||
- "45:8e:62:c5:17:f6:c4:80:e4:04:52:12:6c:e4:74:21"
|
||||
|
||||
# keep in sync with set-github-minio-status
|
||||
jobprefix=zrepl-ci-artifacts/${CIRCLE_SHA1}-pipeline-<<pipeline.number>>/${CIRCLE_JOB}
|
||||
|
||||
# Upload artifacts
|
||||
mkdir -p ./artifacts
|
||||
mc cp -r <<parameters.src>> "zrepl-minio/$jobprefix/<<parameters.dst>>"
|
||||
|
||||
set-github-minio-status:
|
||||
parameters:
|
||||
context:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
minio-dst:
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
shell: /bin/bash -eo pipefail
|
||||
command: |
|
||||
if [ -n "$CIRCLE_PR_NUMBER" ]; then # CIRCLE_PR_NUMBER is guaranteed to be only present in forked PRs (external)
|
||||
echo "Forked PR detected. Sry, can't trust you with credentials to external artifact store, use CircleCI's instead."
|
||||
exit 0
|
||||
fi
|
||||
set -u # from now on
|
||||
|
||||
# keep in sync with with upload-minio command
|
||||
jobprefix=zrepl-ci-artifacts/${CIRCLE_SHA1}-pipeline-<<pipeline.number>>/${CIRCLE_JOB}
|
||||
# Push Artifact Link to GitHub
|
||||
REPO="zrepl/zrepl"
|
||||
COMMIT="${CIRCLE_SHA1}"
|
||||
JOB_NAME="${CIRCLE_JOB}"
|
||||
CONTEXT="<<parameters.context>>"
|
||||
DESCRIPTION="<<parameters.description>>"
|
||||
TARGETURL=https://minio.cschwarz.com/minio/"$jobprefix"/"<<parameters.minio-dst>>"
|
||||
curl "https://api.github.com/repos/$REPO/statuses/$COMMIT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: token $GITHUB_COMMIT_STATUS_TOKEN" \
|
||||
-X POST \
|
||||
-d '{"context":"'"$CONTEXT"'", "state": "success", "description":"'"$DESCRIPTION"'", "target_url":"'"$TARGETURL"'"}'
|
||||
|
||||
|
||||
trigger-pipeline:
|
||||
parameters:
|
||||
body_no_shell_subst:
|
||||
type: string
|
||||
steps:
|
||||
- run: |
|
||||
curl -X POST https://circleci.com/api/v2/project/github/zrepl/zrepl/pipeline \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H "Circle-Token: $ZREPL_BOT_CIRCLE_TOKEN" \
|
||||
--data '<<parameters.body_no_shell_subst>>'
|
||||
# caller must install-docdep
|
||||
- when:
|
||||
condition: << parameters.push >>
|
||||
steps:
|
||||
- run: bash -x docs/publish.sh -c -a -P
|
||||
- when:
|
||||
condition:
|
||||
not: << parameters.push >>
|
||||
steps:
|
||||
- run: bash -x docs/publish.sh -c -a
|
||||
|
||||
parameters:
|
||||
do_ci:
|
||||
@@ -148,10 +83,6 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
release_docker_baseimage_tag:
|
||||
type: string
|
||||
default: "1.17"
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
@@ -159,20 +90,20 @@ workflows:
|
||||
when: << pipeline.parameters.do_ci >>
|
||||
jobs:
|
||||
- quickcheck-docs
|
||||
- quickcheck-go: &quickcheck-go-smoketest
|
||||
name: quickcheck-go-amd64-linux-1.17
|
||||
goversion: &latest-go-release "1.17"
|
||||
- quickcheck-go:
|
||||
name: quickcheck-go-amd64-linux-1.23.1
|
||||
goversion: &latest-go-release "1.23.1"
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
- test-go-on-latest-go-release:
|
||||
- test-go:
|
||||
goversion: *latest-go-release
|
||||
- quickcheck-go:
|
||||
requires:
|
||||
- quickcheck-go-amd64-linux-1.17 #quickcheck-go-smoketest.name
|
||||
matrix: &quickcheck-go-matrix
|
||||
- quickcheck-go-amd64-linux-1.23.1 #quickcheck-go-smoketest.name
|
||||
matrix:
|
||||
alias: quickcheck-go-matrix
|
||||
parameters:
|
||||
goversion: [*latest-go-release, "1.12"]
|
||||
goversion: [*latest-go-release, "1.22.7"]
|
||||
goos: ["linux", "freebsd"]
|
||||
goarch: ["amd64", "arm64"]
|
||||
exclude:
|
||||
@@ -180,10 +111,15 @@ workflows:
|
||||
- goversion: *latest-go-release
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
# not supported by Go 1.12
|
||||
- goversion: "1.12"
|
||||
goos: freebsd
|
||||
goarch: arm64
|
||||
- platformtest:
|
||||
matrix:
|
||||
parameters:
|
||||
goversion: [*latest-go-release]
|
||||
goos: ["linux"]
|
||||
goarch: ["amd64"]
|
||||
requires:
|
||||
- test-go
|
||||
- quickcheck-go-<< matrix.goarch >>-<< matrix.goos >>-<< matrix.goversion >>
|
||||
|
||||
release:
|
||||
when: << pipeline.parameters.do_release >>
|
||||
@@ -201,20 +137,7 @@ workflows:
|
||||
- release-deb
|
||||
- release-rpm
|
||||
|
||||
periodic:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "00 17 * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- stable
|
||||
- problame/circleci-build
|
||||
jobs:
|
||||
- periodic-full-pipeline-run
|
||||
|
||||
zrepl.github.io:
|
||||
publish-zrepl.github.io:
|
||||
jobs:
|
||||
- publish-zrepl-github-io:
|
||||
filters:
|
||||
@@ -225,20 +148,15 @@ workflows:
|
||||
jobs:
|
||||
quickcheck-docs:
|
||||
docker:
|
||||
- image: cimg/base:2020.08
|
||||
- image: cimg/base:2024.09
|
||||
steps:
|
||||
- checkout
|
||||
- install-docdep
|
||||
# do the current docs build
|
||||
- run: make docs
|
||||
|
||||
- download-and-install-minio-client
|
||||
- upload-minio:
|
||||
src: artifacts
|
||||
dst: ""
|
||||
- set-github-minio-status:
|
||||
context: artifacts/${CIRCLE_JOB}
|
||||
description: artifacts of CI job ${CIRCLE_JOB}
|
||||
minio-dst: ""
|
||||
# does the publish.sh script still work?
|
||||
- docs-publish-sh:
|
||||
push: false
|
||||
|
||||
quickcheck-go:
|
||||
parameters:
|
||||
@@ -249,62 +167,98 @@ jobs:
|
||||
goarch:
|
||||
type: string
|
||||
docker:
|
||||
- image: circleci/golang:<<parameters.goversion>>
|
||||
# any toolchain >= 1.22 will auto-download GOTOOLCHAIN
|
||||
- image: &cimg_with_modern_go cimg/go:1.22
|
||||
environment:
|
||||
GOOS: <<parameters.goos>>
|
||||
GOARCH: <<parameters.goarch>>
|
||||
GOTOOLCHAIN: "go<<parameters.goversion>>"
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- restore-cache-gomod
|
||||
- go/load-cache:
|
||||
key: quickcheck-<<parameters.goversion>>
|
||||
- run: make build/install
|
||||
- run: go mod download
|
||||
- run: cd build && go mod download
|
||||
- save-cache-gomod
|
||||
- go/save-cache:
|
||||
key: quickcheck-<<parameters.goversion>>
|
||||
|
||||
- install-godep
|
||||
- run: make formatcheck
|
||||
- run: make generate-platform-test-list
|
||||
# ensure all code has been generated
|
||||
- run: make generate
|
||||
- run: |
|
||||
if output=$(git status --porcelain) && [ -z "$output" ]; then
|
||||
echo "Working directory clean"
|
||||
else
|
||||
echo "Uncommitted changes"
|
||||
echo ""
|
||||
echo "$output"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# other checks
|
||||
- run: make zrepl-bin test-platform-bin
|
||||
- run: make vet
|
||||
- run: make lint
|
||||
|
||||
- download-and-install-minio-client
|
||||
- run: rm -f artifacts/generate-platform-test-list
|
||||
- store_artifacts:
|
||||
path: artifacts
|
||||
- upload-minio:
|
||||
src: artifacts
|
||||
dst: ""
|
||||
- set-github-minio-status:
|
||||
context: artifacts/${CIRCLE_JOB}
|
||||
description: artifacts of CI job ${CIRCLE_JOB}
|
||||
minio-dst: ""
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: [.]
|
||||
|
||||
test-go-on-latest-go-release:
|
||||
platformtest:
|
||||
parameters:
|
||||
goversion:
|
||||
type: string
|
||||
goos:
|
||||
type: string
|
||||
goarch:
|
||||
type: string
|
||||
machine:
|
||||
image: ubuntu-2204:current
|
||||
resource_class: medium
|
||||
environment:
|
||||
GOOS: <<parameters.goos>>
|
||||
GOARCH: <<parameters.goarch>>
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install -y zfsutils-linux
|
||||
- run: sudo zfs version
|
||||
- run: sudo make test-platform GOOS="$GOOS" GOARCH="$GOARCH"
|
||||
|
||||
test-go:
|
||||
parameters:
|
||||
goversion:
|
||||
type: string
|
||||
docker:
|
||||
- image: circleci/golang:<<parameters.goversion>>
|
||||
- image: *cimg_with_modern_go
|
||||
environment:
|
||||
GOTOOLCHAIN: "go<<parameters.goversion>>"
|
||||
steps:
|
||||
- checkout
|
||||
- restore-cache-gomod
|
||||
- go/load-cache:
|
||||
key: make-test-go
|
||||
- run: make test-go
|
||||
# don't save-cache-gomod here, test-go doesn't pull all the dependencies
|
||||
- go/save-cache:
|
||||
key: make-test-go
|
||||
|
||||
release-build:
|
||||
machine:
|
||||
image: ubuntu-2004:202201-02
|
||||
image: &release-vm-image "ubuntu-2404:current"
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run: make release-docker RELEASE_DOCKER_BASEIMAGE_TAG=<<pipeline.parameters.release_docker_baseimage_tag>>
|
||||
- run: make release-docker
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: [.]
|
||||
release-deb:
|
||||
machine:
|
||||
image: ubuntu-2004:202201-02
|
||||
image: *release-vm-image
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
@@ -316,7 +270,7 @@ jobs:
|
||||
|
||||
release-rpm:
|
||||
machine:
|
||||
image: ubuntu-2004:202201-02
|
||||
image: *release-vm-image
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
@@ -328,52 +282,19 @@ jobs:
|
||||
|
||||
release-upload:
|
||||
docker:
|
||||
- image: cimg/base:2020.08
|
||||
- image: cimg/base:2024.09
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: make wrapup-and-checksum
|
||||
- store_artifacts:
|
||||
path: artifacts
|
||||
- download-and-install-minio-client
|
||||
- upload-minio:
|
||||
src: artifacts
|
||||
dst: ""
|
||||
- set-github-minio-status:
|
||||
context: artifacts/release
|
||||
description: CI-generated release artifacts
|
||||
minio-dst: ""
|
||||
|
||||
periodic-full-pipeline-run:
|
||||
docker:
|
||||
- image: cimg/base:2020.08
|
||||
steps:
|
||||
- trigger-pipeline:
|
||||
body_no_shell_subst: '{"branch":"<<pipeline.git.branch>>", "parameters": { "do_ci": true, "do_release": true }}'
|
||||
path: artifacts/release
|
||||
|
||||
publish-zrepl-github-io:
|
||||
docker:
|
||||
- image: cimg/python:3.7
|
||||
- image: cimg/base:2024.09
|
||||
steps:
|
||||
- checkout
|
||||
- invoke-lazy-sh:
|
||||
subcommand: docdep
|
||||
- run:
|
||||
command: |
|
||||
git config --global user.email "zreplbot@cschwarz.com"
|
||||
git config --global user.name "zrepl-github-io-ci"
|
||||
|
||||
# https://circleci.com/docs/2.0/add-ssh-key/#adding-multiple-keys-with-blank-hostnames
|
||||
- run: ssh-add -D
|
||||
# the default circleci ssh config only additional ssh keys for Host !github.com
|
||||
- run:
|
||||
command: |
|
||||
cat > ~/.ssh/config \<<EOF
|
||||
Host *
|
||||
IdentityFile /home/circleci/.ssh/id_rsa_458e62c517f6c480e40452126ce47421
|
||||
EOF
|
||||
- add_ssh_keys:
|
||||
fingerprints:
|
||||
# deploy key for zrepl.github.io
|
||||
- "45:8e:62:c5:17:f6:c4:80:e4:04:52:12:6c:e4:74:21"
|
||||
|
||||
- run: bash -x docs/publish.sh -c -a
|
||||
- install-docdep
|
||||
- docs-publish-sh:
|
||||
push: true
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
import requests
|
||||
|
||||
import time
|
||||
|
||||
import os
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
circle_token = os.environ.get('CIRCLE_TOKEN')
|
||||
if not circle_token:
|
||||
raise ValueError('CIRCLE_TOKEN environment variable not set')
|
||||
|
||||
parser = argparse.ArgumentParser(description='Download artifacts from CircleCI')
|
||||
parser.add_argument('build_num', type=str, help='Build number')
|
||||
parser.add_argument('dst', type=Path, help='Destination directory')
|
||||
parser.add_argument('--prefix', type=str, default='', help='Filter for prefix')
|
||||
parser.add_argument('--match', type=str, default='.*', help='Only include paths matching the given regex')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
res = requests.get(
|
||||
f"https://circleci.com/api/v1.1/project/github/zrepl/zrepl/{args.build_num}/artifacts",
|
||||
headers={
|
||||
"Circle-Token": circle_token,
|
||||
},
|
||||
)
|
||||
res.raise_for_status()
|
||||
|
||||
# https://circleci.com/docs/api/v1/index.html#artifacts-of-a-job
|
||||
# [ {
|
||||
# "path" : "raw-test-output/go-test-report.xml",
|
||||
# "pretty_path" : "raw-test-output/go-test-report.xml",
|
||||
# "node_index" : 0,
|
||||
# "url" : "https://24-88881093-gh.circle-artifacts.com/0/raw-test-output/go-test-report.xml"
|
||||
# }, {
|
||||
# "path" : "raw-test-output/go-test.out",
|
||||
# "pretty_path" : "raw-test-output/go-test.out",
|
||||
# "node_index" : 0,
|
||||
# "url" : "https://24-88881093-gh.circle-artifacts.com/0/raw-test-output/go-test.out"
|
||||
# } ]
|
||||
res = res.json()
|
||||
|
||||
for artifact in res:
|
||||
if not artifact["pretty_path"].startswith(args.prefix):
|
||||
continue
|
||||
if not re.match(args.match, artifact["pretty_path"]):
|
||||
continue
|
||||
stripped = artifact["pretty_path"][len(args.prefix):]
|
||||
print(f"Downloading {artifact['pretty_path']} to {args.dst / stripped}")
|
||||
artifact_rel = Path(stripped)
|
||||
artifact_dst = args.dst / artifact_rel
|
||||
artifact_dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
res = requests.get(
|
||||
artifact["url"],
|
||||
headers={
|
||||
"Circle-Token": circle_token,
|
||||
},
|
||||
stream=True,
|
||||
)
|
||||
res.raise_for_status()
|
||||
|
||||
total_size = int(res.headers.get("Content-Length", 0))
|
||||
block_size = 128 * 1024
|
||||
with open(artifact_dst, "wb") as f:
|
||||
progress = 0
|
||||
start_time = time.time()
|
||||
for chunk in res.iter_content(chunk_size=block_size):
|
||||
f.write(chunk)
|
||||
progress += len(chunk)
|
||||
percent = progress / total_size * 100
|
||||
elapsed_time = time.time() - start_time
|
||||
if elapsed_time >= 5:
|
||||
print(f"Downloaded {progress}/{total_size} bytes ({percent:.2f}%)", end="\r")
|
||||
start_time = time.time()
|
||||
print(f"Downloaded {progress}/{total_size} bytes ({percent:.2f}%)")
|
||||
print("Download complete!")
|
||||
|
||||
print("All files downloaded")
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
COMMIT="$1"
|
||||
GO_VERSION="$2"
|
||||
|
||||
curl -v -X POST https://api.github.com/repos/zrepl/debian-binary-packaging/dispatches \
|
||||
-H 'Accept: application/vnd.github.v3+json' \
|
||||
-H "Authorization: token $GITHUB_ACCESS_TOKEN" \
|
||||
--data '{"event_type": "push", "client_payload": { "zrepl_main_repo_commit": "'"$COMMIT"'", "go_version": "'"$GO_VERSION"'" }}'
|
||||
@@ -0,0 +1,9 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Docs use Python only for static site generation.
|
||||
- package-ecosystem: "pip"
|
||||
directory: /docs
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
@@ -1,6 +1,14 @@
|
||||
linters:
|
||||
enable:
|
||||
- goimports
|
||||
- revive
|
||||
|
||||
linters-settings:
|
||||
goimports:
|
||||
local-prefixes: github.com/zrepl/zrepl
|
||||
revive:
|
||||
rules:
|
||||
- name: time-equal
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.PHONY: generate build test vet cover release docs docs-clean clean format lint platformtest
|
||||
.PHONY: release bins-all release-noarch
|
||||
.PHONY: release release-noarch
|
||||
.DEFAULT_GOAL := zrepl-bin
|
||||
|
||||
ARTIFACTDIR := artifacts
|
||||
@@ -14,22 +14,25 @@ ifndef _ZREPL_VERSION
|
||||
endif
|
||||
endif
|
||||
|
||||
ZREPL_PACKAGE_RELEASE := 1
|
||||
|
||||
GO := go
|
||||
GOOS ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOOS"')
|
||||
GOARCH ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOARCH"')
|
||||
GOARM ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOARM"')
|
||||
GOHOSTOS ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOHOSTOS"')
|
||||
GOHOSTARCH ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOHOSTARCH"')
|
||||
GO_ENV_VARS := GO111MODULE=on
|
||||
GO_ENV_VARS := CGO_ENABLED=0
|
||||
GO_LDFLAGS := "-X github.com/zrepl/zrepl/version.zreplVersion=$(_ZREPL_VERSION)"
|
||||
GO_MOD_READONLY := -mod=readonly
|
||||
GO_EXTRA_BUILDFLAGS :=
|
||||
GO_BUILDFLAGS := $(GO_MOD_READONLY) $(GO_EXTRA_BUILDFLAGS)
|
||||
GO_BUILD := $(GO_ENV_VARS) $(GO) build $(GO_BUILDFLAGS) -ldflags $(GO_LDFLAGS)
|
||||
GOLANGCI_LINT := golangci-lint
|
||||
GOCOVMERGE := gocovmerge
|
||||
RELEASE_DOCKER_BASEIMAGE_TAG ?= 1.17
|
||||
RELEASE_DOCKER_BASEIMAGE ?= golang:$(RELEASE_DOCKER_BASEIMAGE_TAG)
|
||||
RELEASE_GOVERSION ?= go1.23.1
|
||||
STRIPPED_GOVERSION := $(subst go,,$(RELEASE_GOVERSION))
|
||||
RELEASE_DOCKER_BASEIMAGE ?= golang:$(STRIPPED_GOVERSION)
|
||||
RELEASE_DOCKER_CACHEMOUNT :=
|
||||
|
||||
ifneq ($(GOARM),)
|
||||
ZREPL_TARGET_TUPLE := $(GOOS)-$(GOARCH)v$(GOARM)
|
||||
@@ -37,34 +40,46 @@ else
|
||||
ZREPL_TARGET_TUPLE := $(GOOS)-$(GOARCH)
|
||||
endif
|
||||
|
||||
.PHONY: printvars
|
||||
printvars:
|
||||
@echo GOOS=$(GOOS)
|
||||
@echo GOARCH=$(GOARCH)
|
||||
@echo GOARM=$(GOARM)
|
||||
|
||||
ifneq ($(RELEASE_DOCKER_CACHEMOUNT),)
|
||||
_RELEASE_DOCKER_CACHEMOUNT := -v $(RELEASE_DOCKER_CACHEMOUNT)/mod:/go/pkg/mod -v $(RELEASE_DOCKER_CACHEMOUNT)/xdg-cache:/root/.cache/go-build
|
||||
.PHONY: release-docker-mkcachemount
|
||||
release-docker-mkcachemount:
|
||||
mkdir -p $(RELEASE_DOCKER_CACHEMOUNT)
|
||||
mkdir -p $(RELEASE_DOCKER_CACHEMOUNT)/mod
|
||||
mkdir -p $(RELEASE_DOCKER_CACHEMOUNT)/xdg-cache
|
||||
else
|
||||
_RELEASE_DOCKER_CACHEMOUNT :=
|
||||
.PHONY: release-docker-mkcachemount
|
||||
release-docker-mkcachemount:
|
||||
# nothing to do
|
||||
endif
|
||||
|
||||
##################### PRODUCING A RELEASE #############
|
||||
.PHONY: release wrapup-and-checksum check-git-clean sign clean
|
||||
.PHONY: release wrapup-and-checksum check-git-clean sign clean ensure-release-toolchain
|
||||
|
||||
release: clean
|
||||
# no cross-platform support for target test
|
||||
$(MAKE) test-go
|
||||
$(MAKE) bins-all
|
||||
ensure-release-toolchain:
|
||||
# ensure the toolchain is actually the one we expect
|
||||
test $(RELEASE_GOVERSION) = "$$($(GO_ENV_VARS) $(GO) env GOVERSION)"
|
||||
|
||||
release: ensure-release-toolchain
|
||||
$(MAKE) _run_make_foreach_target_tuple RUN_MAKE_FOREACH_TARGET_TUPLE_ARG="vet"
|
||||
$(MAKE) _run_make_foreach_target_tuple RUN_MAKE_FOREACH_TARGET_TUPLE_ARG="lint"
|
||||
$(MAKE) _run_make_foreach_target_tuple RUN_MAKE_FOREACH_TARGET_TUPLE_ARG="zrepl-bin"
|
||||
$(MAKE) _run_make_foreach_target_tuple RUN_MAKE_FOREACH_TARGET_TUPLE_ARG="test-platform-bin"
|
||||
$(MAKE) noarch
|
||||
$(MAKE) wrapup-and-checksum
|
||||
$(MAKE) check-git-clean
|
||||
ifeq (SIGN, 1)
|
||||
$(MAKE) sign
|
||||
endif
|
||||
@echo "ZREPL RELEASE ARTIFACTS AVAILABLE IN artifacts/release"
|
||||
|
||||
release-docker: $(ARTIFACTDIR)
|
||||
sed 's/FROM.*!SUBSTITUTED_BY_MAKEFILE/FROM $(RELEASE_DOCKER_BASEIMAGE)/' build.Dockerfile > artifacts/release-docker.Dockerfile
|
||||
docker build -t zrepl_release --pull -f artifacts/release-docker.Dockerfile .
|
||||
docker run --rm -i -v $(CURDIR):/src -u $$(id -u):$$(id -g) \
|
||||
release-docker: $(ARTIFACTDIR) release-docker-mkcachemount
|
||||
sed 's/FROM.*!SUBSTITUTED_BY_MAKEFILE/FROM $(RELEASE_DOCKER_BASEIMAGE)/' build/build.Dockerfile > $(ARTIFACTDIR)/build.Dockerfile
|
||||
docker build -t zrepl_release --pull -f $(ARTIFACTDIR)/build.Dockerfile .
|
||||
docker run --rm -i \
|
||||
$(_RELEASE_DOCKER_CACHEMOUNT) \
|
||||
-v $(CURDIR):/src -u $$(id -u):$$(id -g) \
|
||||
zrepl_release \
|
||||
make release GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM)
|
||||
make release \
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
|
||||
ZREPL_VERSION=$(ZREPL_VERSION) ZREPL_PACKAGE_RELEASE=$(ZREPL_PACKAGE_RELEASE) \
|
||||
RELEASE_GOVERSION=$(RELEASE_GOVERSION)
|
||||
|
||||
debs-docker:
|
||||
$(MAKE) _debs_or_rpms_docker _DEB_OR_RPM=deb
|
||||
@@ -81,9 +96,14 @@ rpm: $(ARTIFACTDIR) # artifacts/_zrepl.zsh_completion artifacts/bash_completion
|
||||
$(eval _ZREPL_RPM_TOPDIR_ABS := $(CURDIR)/$(ARTIFACTDIR)/rpmbuild)
|
||||
rm -rf "$(_ZREPL_RPM_TOPDIR_ABS)"
|
||||
mkdir "$(_ZREPL_RPM_TOPDIR_ABS)"
|
||||
mkdir -p "$(_ZREPL_RPM_TOPDIR_ABS)"/{SPECS,RPMS,BUILD,BUILDROOT}
|
||||
sed "s/^Version:.*/Version: $(_ZREPL_RPM_VERSION)/g" \
|
||||
packaging/rpm/zrepl.spec > $(_ZREPL_RPM_TOPDIR_ABS)/SPECS/zrepl.spec
|
||||
for d in BUILD BUILDROOT RPMS SOURCES SPECS SRPMS; do \
|
||||
mkdir -p "$(_ZREPL_RPM_TOPDIR_ABS)/$$d"; \
|
||||
done
|
||||
sed \
|
||||
-e "s/^Version:.*/Version: $(_ZREPL_RPM_VERSION)/g" \
|
||||
-e "s/^Release:.*/Release: $(ZREPL_PACKAGE_RELEASE)/g" \
|
||||
packaging/rpm/zrepl.spec \
|
||||
> $(_ZREPL_RPM_TOPDIR_ABS)/SPECS/zrepl.spec
|
||||
|
||||
# see /usr/lib/rpm/platform
|
||||
ifeq ($(GOARCH),amd64)
|
||||
@@ -110,13 +130,16 @@ rpm-docker:
|
||||
docker build -t zrepl_rpm_pkg --pull -f packaging/rpm/Dockerfile .
|
||||
docker run --rm -i -v $(CURDIR):/build/src -u $$(id -u):$$(id -g) \
|
||||
zrepl_rpm_pkg \
|
||||
make rpm GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM)
|
||||
make rpm \
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
|
||||
ZREPL_VERSION=$(ZREPL_VERSION) ZREPL_PACKAGE_RELEASE=$(ZREPL_PACKAGE_RELEASE)
|
||||
|
||||
|
||||
deb: $(ARTIFACTDIR) # artifacts/_zrepl.zsh_completion artifacts/bash_completion docs zrepl-bin
|
||||
|
||||
cp packaging/deb/debian/changelog.template packaging/deb/debian/changelog
|
||||
sed -i 's/DATE_DASH_R_OUTPUT/$(shell date -R)/' packaging/deb/debian/changelog
|
||||
VERSION="$(subst -,.,$(_ZREPL_VERSION))"; \
|
||||
VERSION="$(subst -,.,$(_ZREPL_VERSION))-$(ZREPL_PACKAGE_RELEASE)"; \
|
||||
export VERSION="$${VERSION#v}"; \
|
||||
sed -i 's/VERSION/'"$$VERSION"'/' packaging/deb/debian/changelog
|
||||
|
||||
@@ -134,28 +157,36 @@ endif
|
||||
|
||||
deb-docker:
|
||||
docker build -t zrepl_debian_pkg --pull -f packaging/deb/Dockerfile .
|
||||
# Use a small open file limit to make fakeroot work. If we don't
|
||||
# specify it, docker daemon will use its file limit. I don't know
|
||||
# what changed (Docker, its systemd service, its Go version). But I
|
||||
# observed fakeroot iterating close(i) up to i > 1000000, which costs
|
||||
# a good amount of CPU time and makes the build slow.
|
||||
docker run --rm -i -v $(CURDIR):/build/src -u $$(id -u):$$(id -g) \
|
||||
--ulimit nofile=1024:1024 \
|
||||
zrepl_debian_pkg \
|
||||
make deb GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM)
|
||||
make deb \
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
|
||||
ZREPL_VERSION=$(ZREPL_VERSION) ZREPL_PACKAGE_RELEASE=$(ZREPL_PACKAGE_RELEASE)
|
||||
|
||||
# expects `release` target to have run before
|
||||
# expects `release`, `deb` & `rpm` targets to have run before
|
||||
NOARCH_TARBALL := $(ARTIFACTDIR)/zrepl-noarch.tar
|
||||
wrapup-and-checksum:
|
||||
rm -f $(NOARCH_TARBALL)
|
||||
tar --mtime='1970-01-01' --sort=name \
|
||||
--transform 's/$(ARTIFACTDIR)/zrepl-$(_ZREPL_VERSION)-noarch/' \
|
||||
--transform 's#dist#zrepl-$(_ZREPL_VERSION)-noarch/dist#' \
|
||||
--transform 's#config/samples#zrepl-$(_ZREPL_VERSION)-noarch/config#' \
|
||||
--transform 's#internal/config/samples#zrepl-$(_ZREPL_VERSION)-noarch/config#' \
|
||||
-acf $(NOARCH_TARBALL) \
|
||||
$(ARTIFACTDIR)/docs/html \
|
||||
$(ARTIFACTDIR)/bash_completion \
|
||||
$(ARTIFACTDIR)/_zrepl.zsh_completion \
|
||||
$(ARTIFACTDIR)/go_env.txt \
|
||||
dist \
|
||||
config/samples
|
||||
internal/config/samples
|
||||
rm -rf "$(ARTIFACTDIR)/release"
|
||||
mkdir -p "$(ARTIFACTDIR)/release"
|
||||
cp -l $(ARTIFACTDIR)/zrepl-* \
|
||||
cp -l $(ARTIFACTDIR)/zrepl* \
|
||||
$(ARTIFACTDIR)/platformtest-* \
|
||||
"$(ARTIFACTDIR)/release"
|
||||
cd "$(ARTIFACTDIR)/release" && sha512sum $$(ls | sort) > sha512sum.txt
|
||||
@@ -175,42 +206,45 @@ check-git-clean:
|
||||
|
||||
tag-release:
|
||||
test -n "$(ZREPL_TAG_VERSION)" || exit 1
|
||||
git tag -u E27CA5FC -m "$(ZREPL_TAG_VERSION)" "$(ZREPL_TAG_VERSION)"
|
||||
git tag -u '328A6627FA98061D!' -m "$(ZREPL_TAG_VERSION)" "$(ZREPL_TAG_VERSION)"
|
||||
|
||||
sign:
|
||||
gpg -u "89BC 5D89 C845 568B F578 B306 CDBD 8EC8 E27C A5FC" \
|
||||
gpg -u '328A6627FA98061D!' \
|
||||
--armor \
|
||||
--detach-sign $(ARTIFACTDIR)/release/sha512sum.txt
|
||||
|
||||
clean: docs-clean
|
||||
rm -rf "$(ARTIFACTDIR)"
|
||||
|
||||
##################### BINARIES #####################
|
||||
.PHONY: bins-all lint test-go test-platform cover-merge cover-html vet zrepl-bin test-platform-bin generate-platform-test-list
|
||||
download-circleci-release:
|
||||
rm -rf "$(ARTIFACTDIR)"
|
||||
mkdir -p "$(ARTIFACTDIR)/release"
|
||||
python3 .circleci/download_artifacts.py --prefix 'artifacts/release/' "$(BUILD_NUM)" "$(ARTIFACTDIR)/release"
|
||||
|
||||
BINS_ALL_TARGETS := zrepl-bin test-platform-bin vet lint
|
||||
GO_SUPPORTS_ILLUMOS := $(shell $(GO) version | gawk -F '.' '/^go version /{split($$0, comps, " "); split(comps[3], v, "."); if (v[1] == "go1" && v[2] >= 13) { print "illumos"; } else { print "noillumos"; }}')
|
||||
bins-all:
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=freebsd GOARCH=amd64
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=freebsd GOARCH=386
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=freebsd GOARCH=arm GOARM=7
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=freebsd GOARCH=arm64
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=linux GOARCH=amd64
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=linux GOARCH=arm64
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=linux GOARCH=arm GOARM=7
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=linux GOARCH=386
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=darwin GOARCH=amd64
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=solaris GOARCH=amd64
|
||||
ifeq ($(GO_SUPPORTS_ILLUMOS), illumos)
|
||||
$(MAKE) $(BINS_ALL_TARGETS) GOOS=illumos GOARCH=amd64
|
||||
else ifeq ($(GO_SUPPORTS_ILLUMOS), noillumos)
|
||||
@echo "SKIPPING ILLUMOS BUILD BECAUSE GO VERSION DOESN'T SUPPORT IT"
|
||||
else
|
||||
@echo "CANNOT DETERMINE WHETHER GO VERSION SUPPORTS GOOS=illumos"; exit 1
|
||||
endif
|
||||
##################### MULTI-ARCH HELPERS #####################
|
||||
|
||||
lint:
|
||||
$(GO_ENV_VARS) $(GOLANGCI_LINT) run ./...
|
||||
_run_make_foreach_target_tuple:
|
||||
if [ "$(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG)" = "" ]; then \
|
||||
echo "RUN_MAKE_FOREACH_TARGET_TUPLE_ARG must be set"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=freebsd GOARCH=amd64
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=freebsd GOARCH=386
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=freebsd GOARCH=arm GOARM=7
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=freebsd GOARCH=arm64
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=linux GOARCH=amd64
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=linux GOARCH=arm64
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=linux GOARCH=arm GOARM=7
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=linux GOARCH=386
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=darwin GOARCH=amd64
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=solaris GOARCH=amd64
|
||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=illumos GOARCH=amd64
|
||||
|
||||
##################### REGULAR TARGETS #####################
|
||||
.PHONY: lint test-go test-platform cover-merge cover-html vet zrepl-bin test-platform-bin
|
||||
|
||||
lint: build/install
|
||||
$(GO_ENV_VARS) build/install/gobin/golangci-lint run ./...
|
||||
|
||||
vet:
|
||||
$(GO_ENV_VARS) $(GO) vet $(GO_BUILDFLAGS) ./...
|
||||
@@ -231,9 +265,6 @@ endif
|
||||
zrepl-bin:
|
||||
$(GO_BUILD) -o "$(ARTIFACTDIR)/zrepl-$(ZREPL_TARGET_TUPLE)"
|
||||
|
||||
generate-platform-test-list:
|
||||
$(GO_BUILD) -o $(ARTIFACTDIR)/generate-platform-test-list ./platformtest/tests/gen
|
||||
|
||||
COVER_PLATFORM_BIN_PATH := $(ARTIFACTDIR)/platformtest-cover-$(ZREPL_TARGET_TUPLE)
|
||||
cover-platform-bin:
|
||||
$(GO_ENV_VARS) $(GO) test $(GO_BUILDFLAGS) \
|
||||
@@ -250,7 +281,7 @@ cover-platform:
|
||||
|
||||
TEST_PLATFORM_BIN_PATH := $(ARTIFACTDIR)/platformtest-$(ZREPL_TARGET_TUPLE)
|
||||
test-platform-bin:
|
||||
$(GO_BUILD) -o "$(TEST_PLATFORM_BIN_PATH)" ./platformtest/harness
|
||||
$(GO_BUILD) -o "$(TEST_PLATFORM_BIN_PATH)" ./internal/platformtest/harness
|
||||
test-platform:
|
||||
export _TEST_PLATFORM_CMD="\"$(TEST_PLATFORM_BIN_PATH)\""; \
|
||||
$(MAKE) _test-or-cover-platform-impl
|
||||
@@ -267,7 +298,7 @@ ifndef _TEST_PLATFORM_CMD
|
||||
endif
|
||||
rm -f "$(ZREPL_PLATFORMTEST_ZFS_LOG)"
|
||||
rm -f "$(ARTIFACTDIR)/platformtest.cover"
|
||||
platformtest/logmockzfs/logzfsenv "$(ZREPL_PLATFORMTEST_ZFS_LOG)" `which zfs` \
|
||||
internal/platformtest/logmockzfs/logzfsenv "$(ZREPL_PLATFORMTEST_ZFS_LOG)" `which zfs` \
|
||||
$(_TEST_PLATFORM_CMD) \
|
||||
-poolname "$(ZREPL_PLATFORMTEST_POOLNAME)" \
|
||||
-imagepath "$(ZREPL_PLATFORMTEST_IMAGEPATH)" \
|
||||
@@ -289,23 +320,34 @@ cover-full:
|
||||
|
||||
##################### DEV TARGETS #####################
|
||||
# not part of the build, must do that manually
|
||||
.PHONY: generate formatcheck format
|
||||
.PHONY: generate format
|
||||
|
||||
generate: generate-platform-test-list
|
||||
protoc -I=replication/logic/pdu --go_out=replication/logic/pdu --go-grpc_out=replication/logic/pdu replication/logic/pdu/pdu.proto
|
||||
protoc -I=rpc/grpcclientidentity/example --go_out=rpc/grpcclientidentity/example/pdu --go-grpc_out=rpc/grpcclientidentity/example/pdu rpc/grpcclientidentity/example/grpcauth.proto
|
||||
$(GO_ENV_VARS) $(GO) generate $(GO_BUILDFLAGS) -x ./...
|
||||
build/install:
|
||||
rm -rf build/install.tmp
|
||||
mkdir build/install.tmp
|
||||
|
||||
-echo "installing protoc"
|
||||
mkdir build/install.tmp/protoc
|
||||
bash -x build/get_protoc.bash build/install.tmp/protoc
|
||||
|
||||
-echo "installing go tools"
|
||||
build/go_install_tools.bash build/install.tmp/gobin
|
||||
|
||||
mv build/install.tmp build/install
|
||||
|
||||
|
||||
generate: build/install
|
||||
# TODO: would be nice to run with a pure path here
|
||||
PATH="$(CURDIR)/build/install/gobin:$(CURDIR)/build/install/protoc/bin:$$PATH" && \
|
||||
build/install/protoc/bin/protoc -I=internal/replication/logic/pdu --go_out=internal/replication/logic/pdu --go-grpc_out=internal/replication/logic/pdu internal/replication/logic/pdu/pdu.proto && \
|
||||
build/install/protoc/bin/protoc -I=internal/rpc/grpcclientidentity/example --go_out=internal/rpc/grpcclientidentity/example/pdu --go-grpc_out=internal/rpc/grpcclientidentity/example/pdu internal/rpc/grpcclientidentity/example/grpcauth.proto && \
|
||||
$(GO) generate $(GO_BUILDFLAGS) -x ./... && \
|
||||
true
|
||||
|
||||
GOIMPORTS := goimports -srcdir . -local 'github.com/zrepl/zrepl'
|
||||
FINDSRCFILES := find . -type f -name '*.go' -not -path "./vendor/*" -not -name '*.pb.go' -not -name '*_enumer.go'
|
||||
|
||||
formatcheck:
|
||||
@# goimports doesn't have a knob to exit with non-zero status code if formatting is needed
|
||||
@# see https://go-review.googlesource.com/c/tools/+/237378
|
||||
@ affectedfiles=$$($(GOIMPORTS) -l $(shell $(FINDSRCFILES)) | tee /dev/stderr | wc -l); test "$$affectedfiles" = 0
|
||||
|
||||
format:
|
||||
@ $(GOIMPORTS) -w -d $(shell $(FINDSRCFILES))
|
||||
format: build/install
|
||||
@ build/install/gobin/goimports -w -local 'github.com/zrepl/zrepl' $$(find . -type f -name '*.go' -not -path "./vendor/*" -not -name '*.pb.go' -not -name '*_enumer.go')
|
||||
|
||||
##################### NOARCH #####################
|
||||
.PHONY: noarch $(ARTIFACTDIR)/bash_completion $(ARTIFACTDIR)/_zrepl.zsh_completion $(ARTIFACTDIR)/go_env.txt docs docs-clean
|
||||
|
||||
@@ -26,24 +26,40 @@ zrepl is a one-stop ZFS backup & replication solution.
|
||||
If so, think of an expressive configuration example.
|
||||
2. Think of at least one use case that generalizes from your concrete application.
|
||||
3. Open an issue on GitHub with example conf & use case attached.
|
||||
4. **Optional**: [Post a bounty](https://www.bountysource.com/teams/zrepl) on the issue, or [contact Christian Schwarz](https://cschwarz.com) for contract work.
|
||||
4. **Optional**: [Contact Christian Schwarz](https://cschwarz.com) for contract work.
|
||||
|
||||
The above does not apply if you already implemented everything.
|
||||
Check out the *Coding Workflow* section below for details.
|
||||
|
||||
## Building, Releasing, Downstream-Packaging
|
||||
|
||||
This section provides an overview of the zrepl build & release process.
|
||||
Check out `docs/installation/compile-from-source.rst` for build-from-source instructions.
|
||||
|
||||
### Overview
|
||||
## Development
|
||||
|
||||
zrepl is written in [Go](https://golang.org) and uses [Go modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
|
||||
The documentation is written in [ReStructured Text](http://docutils.sourceforge.net/rst.html) using the [Sphinx](https://www.sphinx-doc.org) framework.
|
||||
|
||||
Install **build dependencies** using `./lazy.sh devsetup`.
|
||||
`lazy.sh` uses `python3-pip` to fetch the build dependencies for the docs - you might want to use a [venv](https://docs.python.org/3/library/venv.html).
|
||||
If you just want to install the Go dependencies, run `./lazy.sh godep`.
|
||||
### Building
|
||||
|
||||
#### Go Code
|
||||
|
||||
Dependencies:
|
||||
|
||||
* Go 1.22 or newer
|
||||
* GNU Make
|
||||
* Git
|
||||
* wget (`make generate`)
|
||||
* unzip (`make generate`)
|
||||
|
||||
Some Go code is **generated**, and generated code is committed to the source tree.
|
||||
Therefore, building does not require having code generation tools set up.
|
||||
When making changes that require code to be (re-)generated, run `make generate`.
|
||||
I downloads and installs pinned versions of the code generation tools into `./build/install`.
|
||||
There is a CI check that ensures Git state is clean, i.e., code generation has been done by a PR and is deterministic.
|
||||
|
||||
#### Docs
|
||||
|
||||
Set up a Python environment that has `docs/requirements.txt` installed via `pip`.
|
||||
Use a [venv](https://docs.python.org/3/library/venv.html) to avoid global state.
|
||||
|
||||
### Testing
|
||||
|
||||
The **test suite** is split into pure **Go tests** (`make test-go`) and **platform tests** that interact with ZFS and thus generally **require root privileges** (`sudo make test-platform`).
|
||||
Platform tests run on their own pool with the name `zreplplatformtest`, which is created using the file vdev in `/tmp`.
|
||||
@@ -51,33 +67,28 @@ Platform tests run on their own pool with the name `zreplplatformtest`, which is
|
||||
For a full **code coverage** profile, run `make test-go COVER=1 && sudo make test-platform && make cover-merge`.
|
||||
An HTML report can be generated using `make cover-html`.
|
||||
|
||||
**Code generation** is triggered by `make generate`. Generated code is committed to the source tree.
|
||||
### Circle CI
|
||||
|
||||
### Build & Release Process
|
||||
We use CircleCI for automated build & test pre- and post-merge.
|
||||
|
||||
**The `Makefile` is catering to the needs of developers & CI, not distro packagers**.
|
||||
It provides phony targets for
|
||||
* local development (building, running tests, etc)
|
||||
* building a release in Docker (used by the CI & release management)
|
||||
* building .deb and .rpm packages out of the release artifacts.
|
||||
|
||||
**Build tooling & dependencies** are documented as code in `lazy.sh`.
|
||||
Go dependencies are then fetched by the go command and pip dependencies are pinned through a `requirements.txt`.
|
||||
|
||||
**We use CircleCI for continuous integration**.
|
||||
There are two workflows:
|
||||
|
||||
* `ci` runs for every commit / branch / tag pushed to GitHub.
|
||||
It is supposed to run very fast (<5min and provides quick feedback to developers).
|
||||
It runs formatting checks, lints and tests on the most important OSes / architectures.
|
||||
Artifacts are published to minio.cschwarz.com (see GitHub Commit Status).
|
||||
|
||||
* `release` runs
|
||||
* on manual triggers through the CircleCI API (in order to produce a release)
|
||||
* periodically on `master`
|
||||
Artifacts are published to minio.cschwarz.com (see GitHub Commit Status).
|
||||
|
||||
**Releases** are issued via Git tags + GitHub Releases feature.
|
||||
Artifacts are stored in CircleCI.
|
||||
|
||||
### Releasing
|
||||
|
||||
All zrepl releases are git-tagged and then published as a GitHub Release.
|
||||
There is a git tag for each zrepl release, usually `vMAJOR.MINOR.0`.
|
||||
We don't move git tags once the release has been published.
|
||||
|
||||
The procedure to issue a release is as follows:
|
||||
* Issue the source release:
|
||||
* Git tag the release on the `master` branch.
|
||||
@@ -88,14 +99,34 @@ The procedure to issue a release is as follows:
|
||||
* Download the artifacts to the release manager's machine.
|
||||
* Create a GitHub release, edit the changelog, upload all the release artifacts, including .rpm and .deb files.
|
||||
* Issue the GitHub release.
|
||||
* Add the .rpm and .deb files to the official zrepl repos, publish those.
|
||||
* Add the .rpm and .deb files to the official zrepl repos.
|
||||
* Code for management of these repos: https://github.com/zrepl/package-repo-ops (private repo at this time)
|
||||
|
||||
**Official binary releases are not re-built when Go receives an update. If the Go update is critical to zrepl (e.g. a Go security update that affects zrepl), we'd issue a new source release**.
|
||||
The rationale for this is that whereas distros provide a mechanism for this (`$zrepl_source_release-$distro_package_revision`), GitHub Releases doesn't which means we'd need to update the existing GitHub release's assets, which nobody would notice (no RSS feed updates, etc.).
|
||||
Downstream packagers can read the changelog to determine whether they want to push that minor release into their distro or simply skip it.
|
||||
#### Patch releases, Go toolchain updates, APT/RPM Package rebuilds
|
||||
|
||||
### Additional Notes to Distro Package Maintainers
|
||||
`vMAJOR.MINOR.0` is typically a tagged commit on `master`, because development velocity isn't high
|
||||
and thus release branches for stabilization aren't necessary.
|
||||
|
||||
Occasionally though there is a need for patch changes to a release, e.g.
|
||||
- security issue in a dependency
|
||||
- Go toolchain update (e.g. security issue in standard library)
|
||||
|
||||
The procedure for this is the following
|
||||
- create a branch off the release tag we need to patch, named `releases/MAJOR.MINOR.X`
|
||||
- that branch will never be merged into `master`, it'll be a dead-end for this specific patch
|
||||
- make changes in that branch
|
||||
- make the final commit that bumps version numbers
|
||||
- create the git tag
|
||||
- follow general procedure for publishing the release (previous sectino
|
||||
|
||||
For Go toolchain updates and package rebuilds with no source code changes, leverage the APT/RPM package revision field.
|
||||
Control via the `ZREPL_PACKAGE_RELEASE` Makefile variable, see `origin/releases/0.6.1-2` for an example.
|
||||
|
||||
|
||||
|
||||
## Notes to Distro Package Maintainers
|
||||
|
||||
* The `Makefile` in this project is not suitable for builds in distros.
|
||||
* Run the platform tests (Docs -> Usage -> Platform Tests) **on a test system** to validate that zrepl's abstractions on top of ZFS work with the system ZFS.
|
||||
* Ship a default config that adheres to your distro's `hier` and logging system.
|
||||
* Ship a service manager file and _please_ try to upstream it to this repository.
|
||||
@@ -105,31 +136,3 @@ Downstream packagers can read the changelog to determine whether they want to pu
|
||||
This is how `zrepl version` knows what version number to show.
|
||||
Your build system should set the `ldFlags` flags appropriately and add a prefix or suffix that indicates that the given zrepl binary is a distro build, not an official one.
|
||||
* Make sure you are informed about new zrepl versions, e.g. by subscribing to GitHub's release RSS feed.
|
||||
|
||||
|
||||
## Contributing Code
|
||||
|
||||
* Open an issue when starting to hack on a new feature
|
||||
* Commits should reference the issue they are related to
|
||||
* Docs improvements not documenting new features do not require an issue.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
Backward-incompatible changes must be documented in the git commit message and are listed in `docs/changelog.rst`.
|
||||
|
||||
### Glossary & Naming Inconsistencies
|
||||
|
||||
In ZFS, *dataset* refers to the objects *filesystem*, *ZVOL* and *snapshot*. <br />
|
||||
However, we need a word for *filesystem* & *ZVOL* but not a snapshot, bookmark, etc.
|
||||
|
||||
Toward the user, the following terminology is used:
|
||||
|
||||
* **filesystem**: a ZFS filesystem or a ZVOL
|
||||
* **filesystem version**: a ZFS snapshot or a bookmark
|
||||
|
||||
Sadly, the zrepl implementation is inconsistent in its use of these words:
|
||||
variables and types are often named *dataset* when they in fact refer to a *filesystem*.
|
||||
|
||||
There will not be a big refactoring (an attempt was made, but it's destroying too much history without much gain).
|
||||
|
||||
However, new contributions & patches should fix naming without further notice in the commit message.
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
FROM !SUBSTITUTED_BY_MAKEFILE
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3-pip \
|
||||
unzip \
|
||||
gawk
|
||||
|
||||
ADD build.installprotoc.bash ./
|
||||
RUN bash build.installprotoc.bash
|
||||
|
||||
ADD lazy.sh /tmp/lazy.sh
|
||||
ADD docs/requirements.txt /tmp/requirements.txt
|
||||
ENV ZREPL_LAZY_DOCS_REQPATH=/tmp/requirements.txt
|
||||
RUN /tmp/lazy.sh docdep
|
||||
|
||||
# prepare volume mount of git checkout to /zrepl
|
||||
RUN mkdir -p /src/github.com/zrepl/zrepl
|
||||
RUN mkdir -p /.cache && chmod -R 0777 /.cache
|
||||
|
||||
# $GOPATH is /go
|
||||
# Go 1.12 doesn't use modules within GOPATH, but 1.13 and later do
|
||||
# => store source outside of GOPATH
|
||||
WORKDIR /src
|
||||
|
||||
# Install build tools (e.g. protobuf generator, stringer) into $GOPATH/bin
|
||||
ADD build/ /tmp/build
|
||||
RUN /tmp/lazy.sh godep
|
||||
|
||||
RUN chmod -R 0777 /go
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
set -x
|
||||
|
||||
MACH=$(uname -m)
|
||||
MACH="${MACH/aarch64/aarch_64}"
|
||||
|
||||
VERSION=3.6.1
|
||||
FILENAME=protoc-"$VERSION"-linux-"$MACH".zip
|
||||
|
||||
if [ -e "$FILENAME" ]; then
|
||||
echo "$FILENAME" already exists 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wget https://github.com/protocolbuffers/protobuf/releases/download/v"$VERSION"/"$FILENAME"
|
||||
|
||||
stat "$FILENAME"
|
||||
|
||||
sha256sum -c --ignore-missing <<EOF
|
||||
6003de742ea3fcf703cfec1cd4a3380fd143081a2eb0e559065563496af27807 protoc-3.6.1-linux-x86_64.zip
|
||||
af8e5aaaf39ddec62ec8dd2be1b8d9602c6da66564883a16393ade5f71170922 protoc-3.6.1-linux-aarch_64.zip
|
||||
EOF
|
||||
|
||||
unzip -d /usr "$FILENAME"
|
||||
@@ -0,0 +1 @@
|
||||
install/
|
||||
@@ -0,0 +1,22 @@
|
||||
FROM !SUBSTITUTED_BY_MAKEFILE
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
unzip \
|
||||
gawk
|
||||
|
||||
# setup venv for docs
|
||||
ENV VIRTUAL_ENV=/opt/venv
|
||||
RUN python3 -m venv $VIRTUAL_ENV
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
ADD docs/requirements.txt /tmp/requirements.txt
|
||||
RUN pip3 install -r /tmp/requirements.txt
|
||||
|
||||
# Go toolchain uses xdg-cache
|
||||
RUN mkdir -p /.cache && chmod -R 0777 /.cache
|
||||
|
||||
# Go devtools are managed by Makefile
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
set -x
|
||||
|
||||
cd "$1"
|
||||
|
||||
MACH=$(uname -m)
|
||||
MACH="${MACH/aarch64/aarch_64}"
|
||||
|
||||
VERSION=28.0
|
||||
FILENAME=protoc-"$VERSION"-linux-"$MACH".zip
|
||||
|
||||
if [ -e "$FILENAME" ]; then
|
||||
echo "$FILENAME" already exists 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wget --continue https://github.com/protocolbuffers/protobuf/releases/download/v"$VERSION"/"$FILENAME"
|
||||
|
||||
stat "$FILENAME"
|
||||
|
||||
sha256sum -c --ignore-missing <<EOF
|
||||
d622619dcbfb5ecb281cfb92c1a74d6a0f42e752d9a2774b197f475f7ab1c8c4 protoc-28.0-linux-aarch_64.zip
|
||||
b2e187c8b9f2d97cd3ecae4926d1bb2cbebe3ab768e7c987cbc86bb17f319358 protoc-28.0-linux-x86_64.zip
|
||||
EOF
|
||||
|
||||
unzip -d . "$FILENAME"
|
||||
+188
-10
@@ -1,16 +1,194 @@
|
||||
module github.com/zrepl/zrepl/build
|
||||
|
||||
go 1.12
|
||||
go 1.22.7
|
||||
toolchain go1.23.1
|
||||
|
||||
require (
|
||||
github.com/alvaroloes/enumer v1.1.1
|
||||
github.com/golangci/golangci-lint v1.35.2
|
||||
github.com/golangci/misspell v0.3.4 // indirect
|
||||
github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 // indirect
|
||||
github.com/spf13/afero v1.2.2 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/alvaroloes/enumer v1.1.2
|
||||
github.com/golangci/golangci-lint v1.60.3
|
||||
github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad
|
||||
golang.org/x/tools v0.0.0-20210105210202-9ed45478a130
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 // indirect
|
||||
google.golang.org/protobuf v1.25.0
|
||||
golang.org/x/tools v0.24.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
|
||||
google.golang.org/protobuf v1.34.2
|
||||
)
|
||||
|
||||
require (
|
||||
4d63.com/gocheckcompilerdirectives v1.2.1 // indirect
|
||||
4d63.com/gochecknoglobals v0.2.1 // indirect
|
||||
github.com/4meepo/tagalign v1.3.4 // indirect
|
||||
github.com/Abirdcfly/dupword v0.1.1 // indirect
|
||||
github.com/Antonboom/errname v0.1.13 // indirect
|
||||
github.com/Antonboom/nilnil v0.1.9 // indirect
|
||||
github.com/Antonboom/testifylint v1.4.3 // indirect
|
||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
|
||||
github.com/Crocmagnon/fatcontext v0.5.2 // indirect
|
||||
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
|
||||
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect
|
||||
github.com/alecthomas/go-check-sumtype v0.1.4 // indirect
|
||||
github.com/alexkohler/nakedret/v2 v2.0.4 // indirect
|
||||
github.com/alexkohler/prealloc v1.0.0 // indirect
|
||||
github.com/alingse/asasalint v0.0.11 // indirect
|
||||
github.com/ashanbrown/forbidigo v1.6.0 // indirect
|
||||
github.com/ashanbrown/makezero v1.1.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bkielbasa/cyclop v1.2.1 // indirect
|
||||
github.com/blizzy78/varnamelen v0.8.0 // indirect
|
||||
github.com/bombsimon/wsl/v4 v4.4.1 // indirect
|
||||
github.com/breml/bidichk v0.2.7 // indirect
|
||||
github.com/breml/errchkjson v0.3.6 // indirect
|
||||
github.com/butuzov/ireturn v0.3.0 // indirect
|
||||
github.com/butuzov/mirror v1.2.0 // indirect
|
||||
github.com/catenacyber/perfsprint v0.7.1 // indirect
|
||||
github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/charithe/durationcheck v0.0.10 // indirect
|
||||
github.com/chavacava/garif v0.1.0 // indirect
|
||||
github.com/ckaznocha/intrange v0.1.2 // indirect
|
||||
github.com/curioswitch/go-reassign v0.2.0 // indirect
|
||||
github.com/daixiang0/gci v0.13.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/denis-tingaikin/go-header v0.5.0 // indirect
|
||||
github.com/ettle/strcase v0.2.0 // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/fatih/structtag v1.2.0 // indirect
|
||||
github.com/firefart/nonamedreturns v1.0.5 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fzipp/gocyclo v0.6.0 // indirect
|
||||
github.com/ghostiam/protogetter v0.3.6 // indirect
|
||||
github.com/go-critic/go-critic v0.11.4 // indirect
|
||||
github.com/go-toolsmith/astcast v1.1.0 // indirect
|
||||
github.com/go-toolsmith/astcopy v1.1.0 // indirect
|
||||
github.com/go-toolsmith/astequal v1.2.0 // indirect
|
||||
github.com/go-toolsmith/astfmt v1.1.0 // indirect
|
||||
github.com/go-toolsmith/astp v1.1.0 // indirect
|
||||
github.com/go-toolsmith/strparse v1.1.0 // indirect
|
||||
github.com/go-toolsmith/typep v1.1.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.1.0 // indirect
|
||||
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect
|
||||
github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 // indirect
|
||||
github.com/golangci/misspell v0.6.0 // indirect
|
||||
github.com/golangci/modinfo v0.3.4 // indirect
|
||||
github.com/golangci/plugin-module-register v0.1.1 // indirect
|
||||
github.com/golangci/revgrep v0.5.3 // indirect
|
||||
github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/gordonklaus/ineffassign v0.1.0 // indirect
|
||||
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
|
||||
github.com/gostaticanalysis/comment v1.4.2 // indirect
|
||||
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
|
||||
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jgautheron/goconst v1.7.1 // indirect
|
||||
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
|
||||
github.com/jjti/go-spancheck v0.6.2 // indirect
|
||||
github.com/julz/importas v0.1.0 // indirect
|
||||
github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect
|
||||
github.com/kisielk/errcheck v1.7.0 // indirect
|
||||
github.com/kkHAIKE/contextcheck v1.1.5 // indirect
|
||||
github.com/kulti/thelper v0.6.3 // indirect
|
||||
github.com/kunwardeep/paralleltest v1.0.10 // indirect
|
||||
github.com/kyoh86/exportloopref v0.1.11 // indirect
|
||||
github.com/lasiar/canonicalheader v1.1.1 // indirect
|
||||
github.com/ldez/gomoddirectives v0.2.4 // indirect
|
||||
github.com/ldez/tagliatelle v0.5.0 // indirect
|
||||
github.com/leonklingele/grouper v1.1.2 // indirect
|
||||
github.com/lufeee/execinquery v1.2.1 // indirect
|
||||
github.com/macabu/inamedparam v0.1.3 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/maratori/testableexamples v1.0.0 // indirect
|
||||
github.com/maratori/testpackage v1.1.1 // indirect
|
||||
github.com/matoous/godox v0.0.0-20240105082147-c5b5e0e7c0c0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mgechev/revive v1.3.9 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moricho/tparallel v0.3.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nakabonne/nestif v0.3.1 // indirect
|
||||
github.com/nishanths/exhaustive v0.12.0 // indirect
|
||||
github.com/nishanths/predeclared v0.2.2 // indirect
|
||||
github.com/nunnatsa/ginkgolinter v0.16.2 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pascaldekloe/name v1.0.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/polyfloyd/go-errorlint v1.6.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.3 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.59.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/quasilyte/go-ruleguard v0.4.2 // indirect
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
|
||||
github.com/quasilyte/gogrep v0.5.0 // indirect
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/ryancurrah/gomodguard v1.3.5 // indirect
|
||||
github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
|
||||
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
|
||||
github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect
|
||||
github.com/securego/gosec/v2 v2.21.1 // indirect
|
||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sivchari/containedctx v1.0.3 // indirect
|
||||
github.com/sivchari/tenv v1.10.0 // indirect
|
||||
github.com/sonatard/noctx v0.0.2 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/sourcegraph/go-diff v0.7.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
|
||||
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tdakkota/asciicheck v0.2.0 // indirect
|
||||
github.com/tetafro/godot v1.4.17 // indirect
|
||||
github.com/timakin/bodyclose v0.0.0-20240125160201-f835fa56326a // indirect
|
||||
github.com/timonwong/loggercheck v0.9.4 // indirect
|
||||
github.com/tomarrell/wrapcheck/v2 v2.9.0 // indirect
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
|
||||
github.com/ultraware/funlen v0.1.0 // indirect
|
||||
github.com/ultraware/whitespace v0.1.1 // indirect
|
||||
github.com/uudashr/gocognit v1.1.3 // indirect
|
||||
github.com/xen0n/gosmopolitan v1.2.2 // indirect
|
||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||
github.com/yeya24/promlinter v0.3.0 // indirect
|
||||
github.com/ykadowak/zerologlint v0.1.5 // indirect
|
||||
gitlab.com/bosi/decorder v0.4.2 // indirect
|
||||
go-simpler.org/musttag v0.12.2 // indirect
|
||||
go-simpler.org/sloglint v0.7.2 // indirect
|
||||
go.uber.org/automaxprocs v1.5.3 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
honnef.co/go/tools v0.5.1 // indirect
|
||||
mvdan.cc/gofumpt v0.7.0 // indirect
|
||||
mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect
|
||||
)
|
||||
|
||||
+507
-625
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
export GO111MODULE=on # otherwise, a checkout of this repo in GOPATH will disable modules on Go 1.12 and earlier
|
||||
source <(go env)
|
||||
# build tools for the host platform
|
||||
export GOOS="$GOHOSTOS"
|
||||
export GOARCH="$GOHOSTARCH"
|
||||
# TODO GOARM=$GOHOSTARM?
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
set -x
|
||||
|
||||
OUTDIR="$(readlink -f "$1")"
|
||||
if [ -e "$OUTDIR" ]; then
|
||||
echo "$OUTDIR" already exists 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# go install command below will install tools to $GOBIN
|
||||
export GOBIN="$OUTDIR"
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
source ./go_install_host_tool.source
|
||||
|
||||
cat tools.go | grep _ | awk -F'"' '{print $2}' | tee | xargs -tI '{}' go install '{}'
|
||||
@@ -1,90 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSnapshotting(t *testing.T) {
|
||||
tmpl := `
|
||||
jobs:
|
||||
- name: foo
|
||||
type: push
|
||||
connect:
|
||||
type: local
|
||||
listener_name: foo
|
||||
client_identity: bar
|
||||
filesystems: {"<": true}
|
||||
%s
|
||||
pruning:
|
||||
keep_sender:
|
||||
- type: last_n
|
||||
count: 10
|
||||
keep_receiver:
|
||||
- type: last_n
|
||||
count: 10
|
||||
`
|
||||
manual := `
|
||||
snapshotting:
|
||||
type: manual
|
||||
`
|
||||
periodic := `
|
||||
snapshotting:
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 10m
|
||||
`
|
||||
|
||||
hooks := `
|
||||
snapshotting:
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 10m
|
||||
hooks:
|
||||
- type: command
|
||||
path: /tmp/path/to/command
|
||||
- type: command
|
||||
path: /tmp/path/to/command
|
||||
filesystems: { "zroot<": true, "<": false }
|
||||
- type: postgres-checkpoint
|
||||
dsn: "host=localhost port=5432 user=postgres sslmode=disable"
|
||||
filesystems: {
|
||||
"tank/postgres/data11": true
|
||||
}
|
||||
- type: mysql-lock-tables
|
||||
dsn: "root@tcp(localhost)/"
|
||||
filesystems: {
|
||||
"tank/mysql": true
|
||||
}
|
||||
`
|
||||
|
||||
fillSnapshotting := func(s string) string { return fmt.Sprintf(tmpl, s) }
|
||||
var c *Config
|
||||
|
||||
t.Run("manual", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(manual))
|
||||
snm := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingManual)
|
||||
assert.Equal(t, "manual", snm.Type)
|
||||
})
|
||||
|
||||
t.Run("periodic", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(periodic))
|
||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingPeriodic)
|
||||
assert.Equal(t, "periodic", snp.Type)
|
||||
assert.Equal(t, 10*time.Minute, snp.Interval)
|
||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||
})
|
||||
|
||||
t.Run("hooks", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(hooks))
|
||||
hs := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingPeriodic).Hooks
|
||||
assert.Equal(t, hs[0].Ret.(*HookCommand).Filesystems["<"], true)
|
||||
assert.Equal(t, hs[1].Ret.(*HookCommand).Filesystems["zroot<"], true)
|
||||
assert.Equal(t, hs[2].Ret.(*HookPostgresCheckpoint).Filesystems["tank/postgres/data11"], true)
|
||||
assert.Equal(t, hs[3].Ret.(*HookMySQLLockTables).Filesystems["tank/mysql"], true)
|
||||
})
|
||||
|
||||
}
|
||||
+1488
-1216
File diff suppressed because it is too large
Load Diff
+23
@@ -0,0 +1,23 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
command='/usr/local/bin/zrepl'
|
||||
command_args='daemon'
|
||||
command_background='true'
|
||||
pidfile="/run/${RC_SVCNAME}.pid"
|
||||
output_log="/var/log/${RC_SVCNAME}.log"
|
||||
error_log="/var/log/${RC_SVCNAME}.log"
|
||||
|
||||
zrepl_runtime_dir='/var/run/zrepl'
|
||||
|
||||
start() {
|
||||
mkdir -p "$zrepl_runtime_dir/stdinserver"
|
||||
chmod -R 0700 "$zrepl_runtime_dir"
|
||||
default_start
|
||||
}
|
||||
|
||||
stop() {
|
||||
rm -rf "$zrepl_runtime_dir"
|
||||
default_stop
|
||||
}
|
||||
|
||||
# vi: noet sw=8 sts=0
|
||||
Vendored
+2
-19
@@ -9,25 +9,8 @@ ExecStart=/usr/local/bin/zrepl --config /etc/zrepl/zrepl.yml daemon
|
||||
RuntimeDirectory=zrepl zrepl/stdinserver
|
||||
RuntimeDirectoryMode=0700
|
||||
|
||||
ProtectSystem=strict
|
||||
#PrivateDevices=yes # TODO ZFS needs access to /dev/zfs, could we limit this?
|
||||
ProtectKernelTunables=yes
|
||||
ProtectControlGroups=yes
|
||||
PrivateTmp=yes
|
||||
#PrivateUsers=yes # TODO Does not work, why?
|
||||
ProtectKernelModules=true
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
RestrictNamespaces=true
|
||||
RestrictRealtime=yes
|
||||
SystemCallArchitectures=native
|
||||
|
||||
ProtectHome=read-only
|
||||
# ProtectHome=tmpfs totally possible, not by default though because of Debian stretch
|
||||
|
||||
# SystemCallFilter
|
||||
# ~@privileged doesn't work with Ubuntu 18.04 ssh
|
||||
SystemCallFilter=~ @mount @cpu-emulation @keyring @module @obsolete @raw-io @debug @clock @resources
|
||||
|
||||
# Make Go produce coredumps
|
||||
Environment=GOTRACEBACK='crash'
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@ BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" -c sphinxconf $(SPHINXOPTS) $(O)
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" -c sphinxconf $(SPHINXOPTS) $(O)
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
/* https://github.com/sphinx-contrib/sphinxcontrib-versioning/blob/0b56210959c6b21bbb730072e81876491b4e1371/sphinxcontrib/versioning/_static/banner.css */
|
||||
|
||||
.scv-banner {
|
||||
padding: 3px;
|
||||
border-radius: 2px;
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background: #d40 linear-gradient(-45deg,
|
||||
rgba(255, 255, 255, 0.2) 0%,
|
||||
rgba(255, 255, 255, 0.2) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.2) 75%,
|
||||
transparent 75%,
|
||||
transparent
|
||||
);
|
||||
background-size: 28px 28px;
|
||||
}
|
||||
.scv-banner > a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.scv-sphinx_rtd_theme {
|
||||
background-color: #2980B9;
|
||||
}
|
||||
|
||||
|
||||
.scv-bizstyle {
|
||||
background-color: #336699;
|
||||
}
|
||||
|
||||
|
||||
.scv-classic {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
|
||||
.scv-traditional {
|
||||
text-align: center !important;
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
{% extends "!page.html" %}
|
||||
{% block body %}
|
||||
{% if current_version and latest_version and current_version != latest_version %}
|
||||
<p class="scv-banner scv-sphinx_rtd_theme">
|
||||
<strong>
|
||||
{% if current_version.is_released %}
|
||||
You're reading an old version of this documentation.
|
||||
If you want up-to-date information, please have a look at <a href="{{ vpathto(latest_version.name) }}">{{latest_version.name}}</a>.
|
||||
{% else %}
|
||||
You're reading the documentation for a development version.
|
||||
For the latest released version, please have a look at <a href="{{ vpathto(latest_version.name) }}">{{latest_version.name}}</a>.
|
||||
{% endif %}
|
||||
</strong>
|
||||
</p>
|
||||
{% endif %}
|
||||
{{ super() }}
|
||||
{% endblock %}%
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
{%- if current_version %}
|
||||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
|
||||
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||
<span class="fa fa-book"> Other Versions</span>
|
||||
v: {{ current_version.name }}
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
{%- if versions.tags %}
|
||||
<dl>
|
||||
<dt>Tags</dt>
|
||||
{%- for item in versions.tags %}
|
||||
<dd><a href="{{ item.url }}">{{ item.name }}</a></dd>
|
||||
{%- endfor %}
|
||||
</dl>
|
||||
{%- endif %}
|
||||
{%- if versions.branches %}
|
||||
<dl>
|
||||
<dt>Branches</dt>
|
||||
{%- for item in versions.branches %}
|
||||
<dd><a href="{{ item.url }}">{{ item.name }}</a></dd>
|
||||
{%- endfor %}
|
||||
</dl>
|
||||
{%- endif %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif %}
|
||||
+72
-13
@@ -16,13 +16,73 @@ Changelog
|
||||
The changelog summarizes bugfixes that are deemed relevant for users and package maintainers.
|
||||
Developers should consult the git commit log or GitHub issue tracker.
|
||||
|
||||
0.6 (Unreleased)
|
||||
----------------
|
||||
Next Release
|
||||
------------
|
||||
|
||||
* `Feature Wishlist on GitHub <https://github.com/zrepl/zrepl/discussions/547>`_
|
||||
The plan for the next release is to revisit how zrepl does snapshot management.
|
||||
High-level goals:
|
||||
|
||||
- Make it easy to decouple snapshot management (snapshotting, pruning) from replication.
|
||||
- Ability to include/exclude snapshots from replication.
|
||||
This is useful for aforementioned decoupling, e.g., separate snapshot prefixes for local & remote replication.
|
||||
Also, it makes explicit that by default, zrepl replicates all snapshots, and that
|
||||
replication has no concept of "zrepl-created snapshots", which is a common misconception.
|
||||
- Use of ``zfs snapshot`` comma syntax or channel programs to take snapshots of multiple
|
||||
datasets atomically.
|
||||
- Provide an alternative to the ``grid`` pruning policy.
|
||||
Most likely something based on hourly/daily/weekly/monthly "trains" plus a count.
|
||||
- Ability to prune at the granularity of the **group** of snapshots created at a given
|
||||
time, as opposed to the individual snapshots within a dataset.
|
||||
Maybe this will be addressed by the alternative to the ``grid`` pruning policy,
|
||||
as it will likely be more predictable.
|
||||
|
||||
Those changes will likely come with some breakage in the config.
|
||||
However, I want to avoid breaking **use cases** that are satisfied by the current design.
|
||||
There will be beta/RC releases to give users a chance to evaluate.
|
||||
|
||||
0.7.0 (unreleased)
|
||||
------------------
|
||||
|
||||
INCOMPLETE LIST OF CHANGES
|
||||
|
||||
* |maint| Update to Go 1.23, require Go 1.22. Adopt `go.mod` toolchain aka `GOTOOLCHAIN` env var.
|
||||
* |maint| Fix deprecations exposed by the toolchain update.
|
||||
* |maint| Long-overdue update of all our dependencies & address deprecations.
|
||||
* |maint| The `make release-docker` in CircleCI produces executables that are bit-identical to my personal machine.
|
||||
|
||||
0.6.1
|
||||
-----
|
||||
|
||||
* |feature| add metric to detect filesystems rules that don't match any local dataset (thanks, `@gmekicaxcient <https://github.com/gmekicaxcient>`_).
|
||||
* |bugfix| ``zrepl status``: hide progress bar once all filesystems reach terminal state (thanks, `@0x3333 <https://github.com/0x3333>`_).
|
||||
* |bugfix| handling of tenative cursor presence if protection strategy doesn't use it (:issue:`714`).
|
||||
* |docs| address setup with two or more external disks (thanks, `@se-jaeger <https://github.com/se-jaeger>`_).
|
||||
* |docs| document ``replication`` and ``conflict_resolution`` options (thanks, `@InsanePrawn <https://github.com/InsanePrawn>`_).
|
||||
* |docs| docs: talks: add note on keep_bookmarks option (thanks, `@skirmess <https://github.com/skirmess>`_).
|
||||
* |maint| dist: add openrc service file (thanks, `@gramosg <https://github.com/gramosg>`_).
|
||||
* |maint| grafana: update dashboard to Grafana 9.3.6.
|
||||
* |maint| run platform tests as part of CI.
|
||||
* |maint| build: upgrade to Go 1.21 and update golangci-lint; minimum Go version for builds is now 1.20
|
||||
|
||||
.. NOTE::
|
||||
| zrepl is a spare-time project primarily developed by `Christian Schwarz <https://cschwarz.com>`_.
|
||||
| You can support maintenance and feature development through one of the following services:
|
||||
| |Donate via Patreon| |Donate via GitHub Sponsors| |Donate via Liberapay| |Donate via PayPal|
|
||||
| Note that PayPal processing fees are relatively high for small donations.
|
||||
| For SEPA wire transfer and **commercial support**, please `contact Christian directly <https://cschwarz.com>`_.
|
||||
|
||||
0.6
|
||||
---
|
||||
|
||||
* |feature| :ref:`Schedule-based snapshotting<job-snapshotting--cron>` using ``cron`` syntax instead of an interval.
|
||||
* |feature| Add ``ZREPL_DESTROY_MAX_BATCH_SIZE`` env var (default 0=unlimited).
|
||||
* |feature| Configurable initial replication policy.
|
||||
When a filesystem is first replicated to a receiver, this control whether just the newest
|
||||
snapshot will be replicated vs. all existing snapshots. Learn more :ref:`in the docs <conflict_resolution-initial_replication>`.
|
||||
* |feature| Configurable timestamp format for snapshot names via :ref:`timestamp_format<job-snapshotting-timestamp_format>`
|
||||
(Thanks, `@ydylla <https://github.com/ydylla>`_).
|
||||
* |feature| Add ``ZREPL_DESTROY_MAX_BATCH_SIZE`` env var (default 0=unlimited)
|
||||
(Thanks, `@3nprob <https://github.com/3nprob>`_).
|
||||
* |feature| Add ``zrepl configcheck --skip-cert-check`` flag (Thanks, `@cole-h <https://github.com/cole-h>`_).
|
||||
* |bugfix| Fix resuming from interrupted replications that use ``send.raw`` on unencrypted datasets.
|
||||
|
||||
* The send options introduced in zrepl 0.4 allow users to specify additional zfs send flags for zrepl to use.
|
||||
@@ -34,7 +94,7 @@ Developers should consult the git commit log or GitHub issue tracker.
|
||||
* However, this means that the ``zrepl status`` UI no longer indicates whether a replication step uses encrypted sends or not.
|
||||
The setting is still effective though.
|
||||
|
||||
* |break| |feature| convert Prometheus metric ``zrepl_version_daemon`` to ``zrepl_start_time`` metric
|
||||
* |break| convert Prometheus metric ``zrepl_version_daemon`` to ``zrepl_start_time`` metric
|
||||
|
||||
* The metric still reports the zrepl version in a label.
|
||||
But the metric *value* is now the Unix timestamp at the time the daemon was started.
|
||||
@@ -43,6 +103,13 @@ Developers should consult the git commit log or GitHub issue tracker.
|
||||
* |bugfix| transient zrepl status error: ``Post "http://unix/status": EOF``
|
||||
* |bugfix| don't treat receive-side bookmarks as a replication conflict.
|
||||
This facilitates chaining of replication jobs. See :issue:`490`.
|
||||
* |bugfix| workaround for Go/gRPC problem on Illumos where zrepl would
|
||||
crash when using the ``local`` transport type (:issue:`598`).
|
||||
* |bugfix| fix active child tasks panic that cold occur during replication plannig (:issue:`193abbe`)
|
||||
* |bugfix| ``zrepl status`` off-by-one error in display of completed step count (:commit:`ce6701f`)
|
||||
* |bugfix| Allow using day & week units for ``snapshotting.interval`` (:commit:`ffb1d89`)
|
||||
* |docs| ``docs/overview`` improvements (Thanks, `@jtagcat <https://github.com/jtagcat>`_).
|
||||
* |maint| Update to Go 1.19.
|
||||
|
||||
0.5
|
||||
---
|
||||
@@ -75,14 +142,6 @@ Note to all users: please read up on the following OpenZFS bugs, as you might be
|
||||
|
||||
Finally, I'd like to point you to the `GitHub discussion <https://github.com/zrepl/zrepl/discussions/547>`_ about which bugfixes and features should be prioritized in zrepl 0.6 and beyond!
|
||||
|
||||
.. NOTE::
|
||||
| zrepl is a spare-time project primarily developed by `Christian Schwarz <https://cschwarz.com>`_.
|
||||
| You can support maintenance and feature development through one of the following services:
|
||||
| |Donate via Patreon| |Donate via GitHub Sponsors| |Donate via Liberapay| |Donate via PayPal|
|
||||
| Note that PayPal processing fees are relatively high for small donations.
|
||||
| For SEPA wire transfer and **commercial support**, please `contact Christian directly <https://cschwarz.com>`_.
|
||||
|
||||
|
||||
0.4.0
|
||||
-----
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
sphinxconf/conf.py
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# zrepl documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Nov 8 22:28:10 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['sphinx.ext.todo',
|
||||
'sphinx.ext.githubpages',
|
||||
'sphinx.ext.extlinks',
|
||||
"sphinx_multiversion",
|
||||
]
|
||||
|
||||
# suppress_warnings = ['image.nonlocal_uri']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['./_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'zrepl'
|
||||
copyright = '2017-2023, Christian Schwarz'
|
||||
author = 'Christian Schwarz'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
#version = set by sphinxcontrib-versioning
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
#release = version
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'en'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
html_css_files = [
|
||||
'banner.css',
|
||||
]
|
||||
|
||||
html_logo = '_static/zrepl.svg'
|
||||
|
||||
html_context = {
|
||||
# https://github.com/rtfd/sphinx_rtd_theme/issues/205
|
||||
# Add 'Edit on Github' link instead of 'View page source'
|
||||
"display_github": True,
|
||||
"github_user": "zrepl",
|
||||
"github_repo": "zrepl",
|
||||
"github_version": "master",
|
||||
"conf_py_path": "/docs/",
|
||||
"source_suffix": source_suffix,
|
||||
}
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'zrepldoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'zrepl.tex', 'zrepl Documentation',
|
||||
'Christian Schwarz', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'zrepl', 'zrepl Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'zrepl', 'zrepl Documentation',
|
||||
author, 'zrepl', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for the extlinks extension -----------------------------------
|
||||
# http://www.sphinx-doc.org/en/stable/ext/extlinks.html
|
||||
extlinks = {
|
||||
'issue':('https://github.com/zrepl/zrepl/issues/%s', 'issue #%s'),
|
||||
'repomasterlink':('https://github.com/zrepl/zrepl/blob/master/%s', '%s'),
|
||||
'sampleconf':('https://github.com/zrepl/zrepl/blob/master/internal/config/samples%s', 'internal/config/samples%s'),
|
||||
'commit':('https://github.com/zrepl/zrepl/commit/%s', 'commit %s'),
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.. include:: ../global.rst.inc
|
||||
|
||||
.. _conflict_resolution-options:
|
||||
|
||||
Conflict Resolution Options
|
||||
===========================
|
||||
@@ -15,7 +16,7 @@ Conflict Resolution Options
|
||||
|
||||
...
|
||||
|
||||
.. _conflict_resolution-initial_replication-option-send_all_snapshots:
|
||||
.. _conflict_resolution-initial_replication:
|
||||
|
||||
|
||||
``initial_replication`` option
|
||||
|
||||
@@ -30,6 +30,10 @@ Job Type ``push``
|
||||
- |snapshotting-spec|
|
||||
* - ``pruning``
|
||||
- |pruning-spec|
|
||||
* - ``replication``
|
||||
- |replication-options|
|
||||
* - ``conflict_resolution``
|
||||
- |conflict-resolution-options|
|
||||
|
||||
Example config: :sampleconf:`/push.yml`
|
||||
|
||||
@@ -81,6 +85,10 @@ Job Type ``pull``
|
||||
| ``manual`` disables periodic pulling, replication then only happens on :ref:`wakeup <cli-signal-wakeup>`.
|
||||
* - ``pruning``
|
||||
- |pruning-spec|
|
||||
* - ``replication``
|
||||
- |replication-options|
|
||||
* - ``conflict_resolution``
|
||||
- |conflict-resolution-options|
|
||||
|
||||
Example config: :sampleconf:`/pull.yml`
|
||||
|
||||
|
||||
@@ -44,27 +44,3 @@ Interval & duration fields in job definitions, pruning configurations, etc. must
|
||||
|
||||
var durationStringRegex *regexp.Regexp = regexp.MustCompile(`^\s*(\d+)\s*(s|m|h|d|w)\s*$`)
|
||||
// s = second, m = minute, h = hour, d = day, w = week (7 days)
|
||||
|
||||
Super-Verbose Job Debugging
|
||||
---------------------------
|
||||
|
||||
You have probably landed here because you opened an issue on GitHub and some developer told you to do this...
|
||||
So just read the annotated comments ;)
|
||||
|
||||
::
|
||||
|
||||
job:
|
||||
- name: ...
|
||||
...
|
||||
# JOB DEBUGGING OPTIONS
|
||||
# should be equal for all job types, but each job implements the debugging itself
|
||||
debug:
|
||||
conn: # debug the io.ReadWriteCloser connection
|
||||
read_dump: /tmp/connlog_read # dump results of Read() invocations to this file
|
||||
write_dump: /tmp/connlog_write # dump results of Write() invocations to this file
|
||||
rpc: # debug the RPC protocol implementation
|
||||
log: true # log output from rpc layer to the job log
|
||||
|
||||
.. ATTENTION::
|
||||
|
||||
Connection dumps will almost certainly contain your or other's private data. Do not share it in a bug report.
|
||||
|
||||
@@ -130,7 +130,7 @@ The following high-level steps take place during replication and can be monitore
|
||||
* Move the **replication cursor** bookmark on the sending side (see below).
|
||||
* Move the **last-received-hold** on the receiving side (see below).
|
||||
* Release the send-side step-holds.
|
||||
|
||||
|
||||
The idea behind the execution order of replication steps is that if the sender snapshots all filesystems simultaneously at fixed intervals, the receiver will have all filesystems snapshotted at time ``T1`` before the first snapshot at ``T2 = T1 + $interval`` is replicated.
|
||||
|
||||
ZFS Background Knowledge
|
||||
@@ -258,6 +258,9 @@ On your setup, ensure that
|
||||
|
||||
* all ``filesystems`` filter specifications are disjoint
|
||||
* no ``root_fs`` is a prefix or equal to another ``root_fs``
|
||||
|
||||
* For ``sink`` jobs, consider all possible ``root_fs/${client_identity}``.
|
||||
|
||||
* no ``filesystems`` filter matches any ``root_fs``
|
||||
|
||||
**Exceptions to the rule**:
|
||||
|
||||
@@ -50,6 +50,7 @@ Example Configuration:
|
||||
regex: "^manual_.*"
|
||||
|
||||
.. DANGER::
|
||||
|
||||
You might have **existing snapshots** of filesystems affected by pruning which you want to keep, i.e. not be destroyed by zrepl.
|
||||
Make sure to actually add the necessary ``regex`` keep rules on both sides, like with ``manual`` in the example above.
|
||||
|
||||
@@ -71,6 +72,14 @@ It only makes sense to specify this rule for the ``keep_sender``.
|
||||
The reason is that, by definition, all snapshots on the receiver have already been replicated to there from the sender.
|
||||
To determine whether a sender-side snapshot has already been replicated, zrepl uses the :ref:`replication cursor bookmark <replication-cursor-and-last-received-hold>` which corresponds to the most recent successfully replicated snapshot.
|
||||
|
||||
.. ATTENTION::
|
||||
|
||||
If you use ``not_replicated`` in your pruning rules, make sure to :ref:`monitor <monitoring>` replication.
|
||||
If your replication gets stuck then ``not_replicated`` causes snapshots to pile uip on the sender.
|
||||
ZFS and especially the ``zfs`` management command are known to degrade in performance with a lot of snapshots.
|
||||
Such degradation impacts zrepl, any other scripts, and human ability to manage your zpool.
|
||||
|
||||
|
||||
.. _prune-keep-retention-grid:
|
||||
|
||||
Policy ``grid``
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.. include:: ../global.rst.inc
|
||||
|
||||
.. _replication-options:
|
||||
|
||||
Replication Options
|
||||
===================
|
||||
|
||||
@@ -197,11 +197,8 @@ Mount behaviour
|
||||
* ``canmount``
|
||||
* ``overlay``
|
||||
|
||||
Note: inheriting or overriding the ``mountpoint`` property on ZVOLs fails in ``zfs recv``.
|
||||
This is an `issue in OpenZFS <https://github.com/openzfs/zfs/issues/11416>`_ .
|
||||
As a workaround, consider creating separate zrepl jobs for your ZVOL and filesystem datasets.
|
||||
Please comment at zrepl :issue:`430` if you encounter this issue and/or would like zrepl to automatically work around it.
|
||||
|
||||
Note: Before `OpenZFS 2.0.5 <https://github.com/openzfs/zfs/issues/11416>`_, inheriting or overriding the ``mountpoint`` property on ZVOLs fails in ``zfs recv``.
|
||||
If you are on such an older version, consider creating separate zrepl jobs for your ZVOL and filesystem datasets.
|
||||
|
||||
Systemd
|
||||
-------
|
||||
|
||||
@@ -25,8 +25,9 @@ The following snapshotting types are supported:
|
||||
|
||||
The ``periodic`` and ``cron`` snapshotting types share some common options and behavior:
|
||||
|
||||
* **Naming:** The snapshot names are composed of a user-defined ``prefix`` followed by a UTC date formatted like ``20060102_150405_000``.
|
||||
We use UTC because it will avoid name conflicts when switching time zones or between summer and winter time.
|
||||
* **Naming:** The snapshot names are composed of a user-defined ``prefix`` followed by a UTC date formatted like ``20060102_150405_000`` by default.
|
||||
We either use UTC or timestamp with timezone information because it will avoid name conflicts when switching time zones or between summer and winter time.
|
||||
Note that if timestamp with time zone information is used, the "+" of the timezone (i.e. +02:00) is replaced by "_" (i.e. _02:00) to conform to allowed characters in ZFS snapshots.
|
||||
* **Hooks:** You can configure hooks to run before or after zrepl takes the snapshots. See :ref:`below <job-snapshotting-hooks>` for details.
|
||||
* **Push replication:** After creating all snapshots, the snapshotter will wake up the replication part of the job, if it's a ``push`` job.
|
||||
Note that snapshotting is decoupled from replication, i.e., if it is down or takes too long, snapshots will still be taken.
|
||||
@@ -62,6 +63,12 @@ The ``periodic`` and ``cron`` snapshotting types share some common options and b
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 10m
|
||||
# Timestamp format that is used as snapshot suffix.
|
||||
# Can be any of "dense" (default), "human", "iso-8601", "unix-seconds" or a custom Go time format (see https://go.dev/src/time/format.go)
|
||||
timestamp_format: dense
|
||||
# Specifies in which time zone the snapshot suffix is generated, optional, defaults to UTC, used only if time zone information is part of timestamp_format.
|
||||
# Can be "UTC" (default), "Local" (time zone information from the OS) or any of the IANA Time Zone names (see https://nodatime.org/TimeZones)
|
||||
timestamp_location: UTC
|
||||
hooks: ...
|
||||
pruning: ...
|
||||
|
||||
@@ -91,6 +98,12 @@ The snapshotter uses the ``prefix`` to identify which snapshots it created.
|
||||
# (second, optional) minute hour day-of-month month day-of-week
|
||||
# This example takes snapshots daily at 3:00.
|
||||
cron: "0 3 * * *"
|
||||
# Timestamp format that is used as snapshot suffix.
|
||||
# Can be any of "dense" (default), "human", "iso-8601", "unix-seconds" or a custom Go time format (see https://go.dev/src/time/format.go)
|
||||
timestamp_format: dense
|
||||
# Specifies in which time zone the snapshot suffix is generated, optional, defaults to UTC, used only if time zone information is part of timestamp_format.
|
||||
# Can be "UTC" (default), "Local" (time zone information from the OS) or any of the IANA Time Zone names (see https://nodatime.org/TimeZones)
|
||||
timestamp_location: UTC
|
||||
pruning: ...
|
||||
|
||||
In ``cron`` mode, the snapshotter takes snaphots at fixed points in time.
|
||||
@@ -98,6 +111,7 @@ See https://en.wikipedia.org/wiki/Cron for details on the syntax.
|
||||
zrepl uses the ``the github.com/robfig/cron/v3`` Go package for parsing.
|
||||
An optional field for "seconds" is supported to take snapshots at sub-minute frequencies.
|
||||
|
||||
|
||||
``manual`` Snapshotting
|
||||
-----------------------
|
||||
|
||||
@@ -116,6 +130,33 @@ See :ref:`this quickstart guide <quickstart-backup-to-external-disk>` for an exa
|
||||
|
||||
To trigger replication after taking snapshots, use the ``zrepl signal wakeup JOB`` command.
|
||||
|
||||
.. _job-snapshotting-timestamp_format:
|
||||
|
||||
Timestamp Format
|
||||
----------------
|
||||
|
||||
The ``cron`` and ``periodic`` snapshotter support configuring a custom timestamp format that is used as suffix for the snapshot name.
|
||||
|
||||
By default, the current time is converted to UTC and then formatted using the ``dense`` format.
|
||||
|
||||
Both time zone and format can be customized by setting ``timestamp_format`` and/or ``timestamp_location``.
|
||||
|
||||
``timestamp_location`` is fed verbatim into `time.LoadLocation <https://pkg.go.dev/time#LoadLocation>`_.
|
||||
|
||||
``timestamp_format`` supports the following values (case-insensitive).
|
||||
|
||||
* ``dense`` => Go format string ``20060102_150405_000``
|
||||
* ``human`` => Go format string ``2006-01-02_15:04:05``
|
||||
* ``iso-8601`` => Go format string ``2006-01-02T15:04:05.000Z07:00``
|
||||
* ``unix-seconds`` => Unix seconds since the epoch, formatted as a decimal string (`time.Time.Unix <https://pkg.go.dev/time#Time.Unix>`_)
|
||||
* Any custom Go time format accepted by `time.Time#Format <https://go.dev/src/time/format.go>`_.
|
||||
|
||||
The ``dense``, ``human``, and ``unix-seconds`` formats require the ``timestamp_location`` to be ``UTC`` because they do not contain timezone information.
|
||||
|
||||
The ``+`` character is `not allowed in ZFS snapshot names <https://github.com/openzfs/zfs/blob/1d3ba0bf01020f5459b1c28db3979129088924c0/module/zcommon/zfs_namecheck.c#L334-L351>`_.
|
||||
Format strings are disallowed to contain the ``+`` character (it's not a character that is interpreted by ``time.Time.Format``, so there's no reason to use it).
|
||||
If a format _produces_ a ``+``, that ``+`` is replaced by an `_`` character.
|
||||
|
||||
.. _job-snapshotting-hooks:
|
||||
|
||||
Pre- and Post-Snapshot Hooks
|
||||
@@ -152,7 +193,7 @@ Most hook types take additional parameters, please refer to the respective subse
|
||||
* - ``mysql-lock-tables``
|
||||
- :ref:`Details <job-hook-type-mysql-lock-tables>`
|
||||
- Flush and read-Lock MySQL tables while taking the snapshot.
|
||||
|
||||
|
||||
.. _job-hook-type-command:
|
||||
|
||||
``command`` Hooks
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
.. |connect-transport| replace:: :ref:`connect specification<transport>`
|
||||
.. |send-options| replace:: :ref:`send options<job-send-options>`, e.g. for encrypted sends
|
||||
.. |recv-options| replace:: :ref:`recv options<job-recv-options>`
|
||||
.. |replication-options| replace:: :ref:`replication options<replication-options>`
|
||||
.. |conflict-resolution-options| replace:: :ref:`conflict resolution options<conflict_resolution-options>`
|
||||
.. |snapshotting-spec| replace:: :ref:`snapshotting specification <job-snapshotting-spec>`
|
||||
.. |pruning-spec| replace:: :ref:`pruning specification <prune>`
|
||||
.. |filter-spec| replace:: :ref:`filter specification<pattern-filter>`
|
||||
|
||||
@@ -11,10 +11,9 @@ Installation
|
||||
|
||||
.. toctree::
|
||||
|
||||
installation/user-privileges
|
||||
installation/packages
|
||||
installation/apt-repos
|
||||
installation/rpm-repos
|
||||
installation/compile-from-source
|
||||
installation/user-privileges
|
||||
installation/freebsd-jail-with-iocage
|
||||
installation/what-next
|
||||
|
||||
@@ -27,7 +27,7 @@ Please open an issue in on GitHub if you encounter any issues with the repositor
|
||||
ARCH="$(dpkg --print-architecture)"
|
||||
CODENAME="$(lsb_release -i -s | tr '[:upper:]' '[:lower:]') $(lsb_release -c -s | tr '[:upper:]' '[:lower:]')"
|
||||
echo "Using Distro and Codename: $CODENAME"
|
||||
echo "deb [arch=$ARCH signed-by=$zrepl_apt_key_dst] https://zrepl.cschwarz.com/apt/$CODENAME main" | sudo tee /etc/apt/sources.list.d/zrepl.list
|
||||
echo "deb [arch=$ARCH signed-by=$zrepl_apt_key_dst] https://zrepl.cschwarz.com/apt/$CODENAME main" | sudo tee "$zrepl_apt_repo_file" > /dev/null
|
||||
|
||||
# Update apt repos.
|
||||
sudo apt update
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
.. _binary releases: https://github.com/zrepl/zrepl/releases
|
||||
|
||||
.. _installation-compile-from-source:
|
||||
|
||||
Compile From Source
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Producing a release requires **Go 1.11** or newer and **Python 3** + **pip3** + ``docs/requirements.txt`` for the Sphinx documentation.
|
||||
A tutorial to install Go is available over at `golang.org <https://golang.org/doc/install>`_.
|
||||
Python and pip3 should probably be installed via your distro's package manager.
|
||||
|
||||
::
|
||||
cd to/your/zrepl/checkout
|
||||
python3 -m venv3
|
||||
source venv3/bin/activate
|
||||
./lazy.sh devsetup
|
||||
make release
|
||||
# build artifacts are available in ./artifacts/release
|
||||
|
||||
The Python venv is used for the documentation build dependencies.
|
||||
If you just want to build the zrepl binary, leave it out and use `./lazy.sh godep` instead.
|
||||
|
||||
Alternatively, you can use the Docker build process:
|
||||
it is used to produce the official zrepl `binary releases`_
|
||||
and serves as a reference for build dependencies and procedure:
|
||||
|
||||
::
|
||||
|
||||
cd to/your/zrepl/checkout
|
||||
# make sure your user has access to the docker socket
|
||||
make release-docker
|
||||
# if you want .deb or .rpm packages, invoke the follwoing
|
||||
# targets _after_ you invoked release-docker
|
||||
make deb-docker
|
||||
make rpm-docker
|
||||
# build artifacts are available in ./artifacts/release
|
||||
# packages are available in ./artifacts
|
||||
|
||||
|
||||
.. NOTE::
|
||||
|
||||
It is your job to install the built binary in the zrepl users's ``$PATH``, e.g. ``/usr/local/bin/zrepl``.
|
||||
Otherwise, the examples in the :ref:`quick-start guides <quickstart-toc>` may need to be adjusted.
|
||||
@@ -16,10 +16,13 @@ The following list may be incomplete, feel free to submit a PR with an update:
|
||||
* - OS / Distro
|
||||
- Install Command
|
||||
- Link
|
||||
* - any
|
||||
- Statically linked binaries.
|
||||
- `Official GitHub releases <binary releases_>`_
|
||||
* - FreeBSD
|
||||
- ``pkg install zrepl``
|
||||
- `<https://www.freshports.org/sysutils/zrepl/>`_
|
||||
|
||||
|
||||
:ref:`installation-freebsd-jail-with-iocage`
|
||||
* - FreeNAS
|
||||
-
|
||||
@@ -30,7 +33,7 @@ The following list may be incomplete, feel free to submit a PR with an update:
|
||||
* - Arch Linux
|
||||
- ``yay install zrepl``
|
||||
- Available on `AUR <https://aur.archlinux.org/packages/zrepl>`_
|
||||
* - Fedora, CentOS, RHEL, OpenSUSE
|
||||
* - Fedora / RHEL / OpenSUSE
|
||||
- ``dnf install zrepl``
|
||||
- :ref:`RPM repository config <installation-rpm-repos>`
|
||||
* - Debian + Ubuntu
|
||||
@@ -42,6 +45,6 @@ The following list may be incomplete, feel free to submit a PR with an update:
|
||||
* - Void Linux
|
||||
- ``xbps-install zrepl``
|
||||
- Available since `a88a2a4 <https://github.com/void-linux/void-packages/commit/a88a2a4d7bf56072dadf61ab56b8424e39155890>`_
|
||||
* - Others
|
||||
-
|
||||
- Use `binary releases`_ or build from source.
|
||||
* - any
|
||||
- Build from source
|
||||
- :repomasterlink:`README.md`.
|
||||
|
||||
@@ -15,3 +15,5 @@ Talks & Presentations
|
||||
`Event <https://wiki.freebsd.org/DevSummit/201709>`__
|
||||
)
|
||||
|
||||
* Note: The remarks on ``keep_bookmarks`` are irrelevant as of zrepl 0.1 which introduced the zrepl-managed replication cursor bookmark.
|
||||
Read the `Overview <overview-how-replication-works>`_ section to learn more.
|
||||
|
||||
+20
-18
@@ -3,7 +3,8 @@ set -euo pipefail
|
||||
|
||||
NON_INTERACTIVE=false
|
||||
DO_CLONE=false
|
||||
while getopts "ca" arg; do
|
||||
PUSH=false
|
||||
while getopts "caP" arg; do
|
||||
case "$arg" in
|
||||
"a")
|
||||
NON_INTERACTIVE=true
|
||||
@@ -11,6 +12,9 @@ while getopts "ca" arg; do
|
||||
"c")
|
||||
DO_CLONE=true
|
||||
;;
|
||||
"P")
|
||||
PUSH=true
|
||||
;;
|
||||
*)
|
||||
echo "invalid option '-$arg'"
|
||||
exit 1
|
||||
@@ -26,8 +30,8 @@ checkout_repo_msg() {
|
||||
echo "clone ${GHPAGESREPO} to ${PUBLICDIR}:"
|
||||
}
|
||||
|
||||
if ! type sphinx-versioning >/dev/null; then
|
||||
echo "install sphinx-versioning and come back"
|
||||
if ! type sphinx-multiversion >/dev/null; then
|
||||
echo "install sphinx-multiversion and come back"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -49,11 +53,11 @@ else
|
||||
read -r
|
||||
fi
|
||||
|
||||
pushd "$PUBLICDIR"
|
||||
pushd "$PUBLICDIR"
|
||||
|
||||
echo "verify we're in the GitHub pages repo..."
|
||||
git remote get-url origin | grep -E "^${GHPAGESREPO}\$"
|
||||
if [ "$?" -ne "0" ] ;then
|
||||
if [ "$?" -ne "0" ] ;then
|
||||
checkout_repo_msg
|
||||
echo "finished checkout, please run again"
|
||||
exit 1
|
||||
@@ -73,22 +77,15 @@ popd
|
||||
|
||||
echo "building site"
|
||||
|
||||
flags="$(python3 gen-sphinx-versioning-flags.py)"
|
||||
set -e
|
||||
sphinx-versioning build \
|
||||
$flags \
|
||||
docs ./public_git \
|
||||
-- -c sphinxconf # older conf.py throw errors because they used
|
||||
# version = subprocess.show_output(["git", "describe"])
|
||||
# which fails when building with sphinxcontrib-versioning
|
||||
set +e
|
||||
python3 run-sphinx-multiversion.py . ./public_git
|
||||
|
||||
|
||||
CURRENT_COMMIT=$(git rev-parse HEAD)
|
||||
git status --porcelain
|
||||
if [[ "$(git status --porcelain)" != "" ]]; then
|
||||
CURRENT_COMMIT="${CURRENT_COMMIT}(dirty)"
|
||||
CURRENT_COMMIT="${CURRENT_COMMIT}(dirty)"
|
||||
fi
|
||||
COMMIT_MSG="sphinx-versioning render from publish.sh - $(date -u) - ${CURRENT_COMMIT}"
|
||||
COMMIT_MSG="render from publish.sh - $(date -u) - ${CURRENT_COMMIT}"
|
||||
|
||||
pushd "$PUBLICDIR"
|
||||
|
||||
@@ -100,6 +97,11 @@ if [ "$(git status --porcelain)" != "" ]; then
|
||||
else
|
||||
echo "nothing to commit"
|
||||
fi
|
||||
echo "pushing to GitHub pages repo"
|
||||
git push origin master
|
||||
|
||||
if $PUSH; then
|
||||
echo "pushing to GitHub pages repo"
|
||||
git push origin master
|
||||
else
|
||||
echo "not pushing to GitHub pages repo, set -P flag to push"
|
||||
fi
|
||||
|
||||
|
||||
@@ -31,6 +31,19 @@ A few additional requirements:
|
||||
The following config snippet implements the setup described above.
|
||||
You will likely want to customize some aspects mentioned in the top comment in the file.
|
||||
|
||||
.. literalinclude:: ../../config/samples/quickstart_backup_to_external_disk.yml
|
||||
.. literalinclude:: ../../internal/config/samples/quickstart_backup_to_external_disk.yml
|
||||
|
||||
:ref:`Click here <quickstart-apply-config>` to go back to the quickstart guide.
|
||||
|
||||
Offline Backups with two (or more) External Disks
|
||||
-------------------------------------------------
|
||||
|
||||
It can be desirable to have multiple disk-based backups of the same machine.
|
||||
To accomplish this,
|
||||
|
||||
* create one zpool per external HDD, each with a unique name, and
|
||||
* define a pair of ``push`` and ``sink`` job **for each** of these zpools, each with a unique ``name``, ``listener_name``, and ``root_fs``.
|
||||
|
||||
The unique names ensure that the jobs don't step on each others' toes when managing :ref:`zrepl's ZFS abstractions <zrepl-zfs-abstractions>` .
|
||||
|
||||
|
||||
:ref:`Click here <quickstart-apply-config>` to go back to the quickstart guide.
|
||||
|
||||
@@ -77,7 +77,7 @@ Configure server ``prod``
|
||||
|
||||
We define a **push job** named ``prod_to_backups`` in ``/etc/zrepl/zrepl.yml`` on host ``prod`` :
|
||||
|
||||
.. literalinclude:: ../../config/samples/quickstart_continuous_server_backup_sender.yml
|
||||
.. literalinclude:: ../../internal/config/samples/quickstart_continuous_server_backup_sender.yml
|
||||
|
||||
.. _tutorial-configure-prod:
|
||||
|
||||
@@ -86,7 +86,7 @@ Configure server ``backups``
|
||||
|
||||
We define a corresponding **sink job** named ``sink`` in ``/etc/zrepl/zrepl.yml`` on host ``backups`` :
|
||||
|
||||
.. literalinclude:: ../../config/samples/quickstart_continuous_server_backup_receiver.yml
|
||||
.. literalinclude:: ../../internal/config/samples/quickstart_continuous_server_backup_receiver.yml
|
||||
|
||||
Go Back To Quickstart Guide
|
||||
---------------------------
|
||||
|
||||
@@ -80,12 +80,12 @@ Mutual TLS via the :ref:`TLS client authentication transport <transport-tcp+tlsc
|
||||
Configure source server A
|
||||
-------------------------
|
||||
|
||||
.. literalinclude:: ../../config/samples/quickstart_fan_out_replication_source.yml
|
||||
.. literalinclude:: ../../internal/config/samples/quickstart_fan_out_replication_source.yml
|
||||
|
||||
Configure each target server
|
||||
----------------------------
|
||||
|
||||
.. literalinclude:: ../../config/samples/quickstart_fan_out_replication_target.yml
|
||||
.. literalinclude:: ../../internal/config/samples/quickstart_fan_out_replication_target.yml
|
||||
|
||||
Go Back To Quickstart Guide
|
||||
---------------------------
|
||||
|
||||
+23
-29
@@ -1,30 +1,24 @@
|
||||
alabaster==0.7.12
|
||||
attrs==19.1.0
|
||||
Babel==2.7.0
|
||||
certifi==2019.6.16
|
||||
chardet==3.0.4
|
||||
Click==7.0
|
||||
colorclass==2.2.0
|
||||
docutils==0.15.2
|
||||
idna==2.8
|
||||
imagesize==1.1.0
|
||||
Jinja2==2.10.1
|
||||
MarkupSafe==1.1.1
|
||||
packaging==19.1
|
||||
Pygments==2.4.2
|
||||
pyparsing==2.4.2
|
||||
pytz==2019.2
|
||||
requests==2.22.0
|
||||
six==1.12.0
|
||||
snowballstemmer==1.9.1
|
||||
Sphinx==1.8.5
|
||||
sphinx-rtd-theme==0.4.3
|
||||
sphinxcontrib-applehelp==1.0.1
|
||||
sphinxcontrib-devhelp==1.0.1
|
||||
sphinxcontrib-htmlhelp==1.0.2
|
||||
alabaster==0.7.13
|
||||
Babel==2.12.1
|
||||
certifi==2023.7.22
|
||||
charset-normalizer==3.2.0
|
||||
docutils==0.18.1
|
||||
idna==3.4
|
||||
imagesize==1.4.1
|
||||
Jinja2==3.1.2
|
||||
MarkupSafe==2.1.3
|
||||
packaging==23.1
|
||||
Pygments==2.16.1
|
||||
requests==2.31.0
|
||||
snowballstemmer==2.2.0
|
||||
Sphinx==7.2.5
|
||||
sphinx-multiversion @ git+https://github.com/zrepl/sphinx-multiversion/@52c915d7ad898d9641ec48c8bbccb7d4f079db93
|
||||
sphinx-rtd-theme==1.3.0
|
||||
sphinxcontrib-applehelp==1.0.7
|
||||
sphinxcontrib-devhelp==1.0.5
|
||||
sphinxcontrib-htmlhelp==2.0.4
|
||||
sphinxcontrib-jquery==4.1
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
sphinxcontrib-qthelp==1.0.2
|
||||
sphinxcontrib-serializinghtml==1.1.3
|
||||
git+https://github.com/rwblair/sphinxcontrib-versioning.git@7e3885a389a809e17ea55261316b7b0e98dbf98f#egg=sphinxcontrib-versioning
|
||||
sphinxcontrib-websupport==1.1.2
|
||||
urllib3==1.25.3
|
||||
sphinxcontrib-qthelp==1.0.6
|
||||
sphinxcontrib-serializinghtml==1.1.9
|
||||
urllib3==2.0.4
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import re
|
||||
import argparse
|
||||
import distutils
|
||||
|
||||
argparser = argparse.ArgumentParser()
|
||||
argparser.add_argument("docsroot")
|
||||
argparser.add_argument("outdir")
|
||||
args = argparser.parse_args()
|
||||
|
||||
output = subprocess.run(["git", "tag", "-l"], capture_output=True, check=True, text=True)
|
||||
tagRE = re.compile(r"^v(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(-rc(?P<rc>\d+))?$")
|
||||
@@ -27,8 +35,8 @@ for line in output.stdout.split("\n"):
|
||||
|
||||
t = Tag()
|
||||
t.orig = line
|
||||
t.major = int(m["major"])
|
||||
t.minor = int(m["minor"])
|
||||
t.major = int(m["major"])
|
||||
t.minor = int(m["minor"])
|
||||
t.patch = int(m["patch"])
|
||||
t.rc = int(m["rc"] if m["rc"] is not None else 0)
|
||||
|
||||
@@ -49,26 +57,16 @@ for (mm, l) in by_major_minor.items():
|
||||
latest_by_major_minor.append(l[-1])
|
||||
latest_by_major_minor.sort(key=lambda tag: (tag.major, tag.minor))
|
||||
|
||||
# print(by_major_minor)
|
||||
# print(latest_by_major_minor)
|
||||
|
||||
cmdline = []
|
||||
|
||||
for latest_patch in latest_by_major_minor:
|
||||
cmdline.append("--whitelist-tags")
|
||||
cmdline.append(f"^{re.escape(latest_patch.orig)}$")
|
||||
|
||||
# we want flexibility to update docs for the latest stable release
|
||||
# => we have a branch for that, called `stable` which we move manually
|
||||
# TODO: in the future, have f"stable-{latest_by_major_minor[-1]}"
|
||||
default_version = "stable"
|
||||
cmdline.extend(["--whitelist-branches", default_version])
|
||||
|
||||
cmdline.extend(["--root-ref", f"{default_version}"])
|
||||
cmdline.extend(["--banner-main-ref", f"{default_version}"])
|
||||
cmdline.extend(["--show-banner"])
|
||||
cmdline.extend(["--sort", "semver"])
|
||||
|
||||
cmdline.extend(["--whitelist-branches", "master"])
|
||||
|
||||
print(" ".join(cmdline))
|
||||
cmdline = [
|
||||
"sphinx-multiversion",
|
||||
"-D", "smv_tag_whitelist=^({})$".format("|".join([re.escape(tag.orig) for tag in latest_by_major_minor])),
|
||||
"-D", "smv_branch_whitelist=^(master|stable)$",
|
||||
"-D", "smv_remote_whitelist=^.*$",
|
||||
"-D", "smv_latest_version=stable",
|
||||
"-D", r"smv_released_pattern=^refs/(tags|heads|remotes/[^/]+)/(?!master).*$", # treat everything except master as released, that way, the banner message makes sense
|
||||
# "--dump-metadata", # for debugging
|
||||
args.docsroot,
|
||||
args.outdir,
|
||||
]
|
||||
print(cmdline)
|
||||
subprocess.run(cmdline, check=True)
|
||||
@@ -1,182 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# zrepl documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Nov 8 22:28:10 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['sphinx.ext.todo',
|
||||
'sphinx.ext.githubpages',
|
||||
'sphinx.ext.extlinks']
|
||||
|
||||
suppress_warnings = ['image.nonlocal_uri']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['../_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'zrepl'
|
||||
copyright = '2017-2019, Christian Schwarz'
|
||||
author = 'Christian Schwarz'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
#version = set by sphinxcontrib-versioning
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
#release = version
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['../_static']
|
||||
|
||||
|
||||
html_logo = '../_static/zrepl.svg'
|
||||
|
||||
html_context = {
|
||||
# https://github.com/rtfd/sphinx_rtd_theme/issues/205
|
||||
# Add 'Edit on Github' link instead of 'View page source'
|
||||
"display_github": True,
|
||||
"github_user": "zrepl",
|
||||
"github_repo": "zrepl",
|
||||
"github_version": "master",
|
||||
"conf_py_path": "/docs/",
|
||||
"source_suffix": source_suffix,
|
||||
}
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'zrepldoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'zrepl.tex', 'zrepl Documentation',
|
||||
'Christian Schwarz', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'zrepl', 'zrepl Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'zrepl', 'zrepl Documentation',
|
||||
author, 'zrepl', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for the extlinks extension -----------------------------------
|
||||
# http://www.sphinx-doc.org/en/stable/ext/extlinks.html
|
||||
extlinks = {
|
||||
'issue':('https://github.com/zrepl/zrepl/issues/%s', 'issue #'),
|
||||
'repomasterlink':('https://github.com/zrepl/zrepl/blob/master/%s', ''),
|
||||
'sampleconf':('https://github.com/zrepl/zrepl/blob/master/config/samples%s', 'config/samples'),
|
||||
'commit':('https://github.com/zrepl/zrepl/commit/%s', 'commit '),
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ We would like to thank the following people and organizations for supporting zre
|
||||
|
||||
<div class="fa fa-code" style="width: 1em;"></div>
|
||||
|
||||
* |supporter-std| `Max Christian Pohle <https://coderonline.de>`_
|
||||
* |supporter-gold| Prominic.NET, Inc.
|
||||
* |supporter-std| Torsten Blum
|
||||
* |supporter-gold| Cyberiada GmbH
|
||||
|
||||
@@ -1,51 +1,86 @@
|
||||
module github.com/zrepl/zrepl
|
||||
|
||||
go 1.12
|
||||
go 1.22.7
|
||||
|
||||
toolchain go1.23.1
|
||||
|
||||
require (
|
||||
github.com/bits-and-blooms/bitset v1.14.3
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/gdamore/tcell v1.2.0
|
||||
github.com/gdamore/tcell/v2 v2.2.0
|
||||
github.com/gdamore/tcell/v2 v2.7.4
|
||||
github.com/gitchander/permutation v0.0.0-20181107151852-9e56b92e9909
|
||||
github.com/go-logfmt/logfmt v0.4.0
|
||||
github.com/go-logfmt/logfmt v0.5.1
|
||||
github.com/go-playground/validator v9.31.0+incompatible
|
||||
github.com/go-playground/validator/v10 v10.4.1
|
||||
github.com/go-sql-driver/mysql v1.4.1-0.20190907122137-b2c03bcae3d4
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jinzhu/copier v0.0.0-20170922082739-db4671f3a9b8
|
||||
github.com/juju/ratelimit v1.0.1
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
|
||||
github.com/kr/pretty v0.1.0
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/kr/pretty v0.3.1
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/mattn/go-colorable v0.1.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.8
|
||||
github.com/montanaflynn/stats v0.5.0
|
||||
github.com/onsi/ginkgo v1.10.2 // indirect
|
||||
github.com/onsi/gomega v1.7.0 // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/profile v1.2.1
|
||||
github.com/problame/go-netssh v0.0.0-20200601114649-26439f9f0dc5
|
||||
github.com/prometheus/client_golang v1.2.1
|
||||
github.com/prometheus/common v0.7.0
|
||||
github.com/prometheus/client_golang v1.20.3
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44 // indirect; go1.12 thinks it needs this
|
||||
github.com/spf13/cobra v0.0.2
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/willf/bitset v1.1.10
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d
|
||||
github.com/zrepl/yaml-config v0.0.0-20191220194647-cbb6b0cf4bdd
|
||||
golang.org/x/net v0.28.0
|
||||
golang.org/x/sync v0.8.0
|
||||
golang.org/x/sys v0.24.0
|
||||
golang.org/x/tools v0.24.0
|
||||
google.golang.org/grpc v1.66.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
)
|
||||
|
||||
require (
|
||||
code.rocketnine.space/tslocum/cbind v0.1.5 // indirect
|
||||
github.com/golang/protobuf v1.5.0 // indirect
|
||||
github.com/hpcloud/tail v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/gomega v1.34.2 // indirect
|
||||
github.com/prometheus/common v0.59.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/ftrvxmtrx/fd v0.0.0-20150925145434-c6d800382fff // indirect
|
||||
github.com/gdamore/encoding v1.0.0 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.4 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/onsi/ginkgo v1.10.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44 // indirect; go1.12 thinks it needs this
|
||||
github.com/theckman/goconstraint v1.11.0 // indirect
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect; go1.12 thinks it needs this
|
||||
github.com/yudai/pp v2.0.1+incompatible // indirect
|
||||
github.com/zrepl/yaml-config v0.0.0-20191220194647-cbb6b0cf4bdd
|
||||
gitlab.com/tslocum/cview v1.5.3
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/term v0.23.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
google.golang.org/appengine v1.4.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210122163508-8081c04a3579 // indirect
|
||||
google.golang.org/grpc v1.35.0
|
||||
google.golang.org/protobuf v1.25.0
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,49 +1,37 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
code.rocketnine.space/tslocum/cbind v0.1.5 h1:i6NkeLLNPNMS4NWNi3302Ay3zSU6MrqOT+yJskiodxE=
|
||||
code.rocketnine.space/tslocum/cbind v0.1.5/go.mod h1:LtfqJTzM7qhg88nAvNhx+VnTjZ0SXBJtxBObbfBWo/M=
|
||||
code.rocketnine.space/tslocum/cview v1.5.9 h1:PcBoqb+S0H4MhiMVt+u06l6Zm3NAK2DGoWsIxkSAKSI=
|
||||
code.rocketnine.space/tslocum/cview v1.5.9/go.mod h1:nraCJ41xU9AOAP/pJDV5t2fOelYp8CRGBZr8ZbEzw0w=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.14.3 h1:Gd2c8lSNf9pKXom5JtD7AaKO8o7fGQ2LtFj1436qilA=
|
||||
github.com/bits-and-blooms/bitset v1.14.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
|
||||
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ftrvxmtrx/fd v0.0.0-20150925145434-c6d800382fff h1:zk1wwii7uXmI0znwU+lqg+wFL9G5+vm5I+9rv2let60=
|
||||
github.com/ftrvxmtrx/fd v0.0.0-20150925145434-c6d800382fff/go.mod h1:yUhRXHewUVJ1k89wHKP68xfzk7kwXUx/DV1nx4EBMbw=
|
||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.2.0 h1:ikixzsxc8K8o3V2/CEmyoEW8mJZaNYQQ3NP3VIQdUe4=
|
||||
github.com/gdamore/tcell v1.2.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||
github.com/gdamore/tcell/v2 v2.0.0-dev/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.1.1-0.20201225194624-29bb185874fd/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U4=
|
||||
github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
|
||||
github.com/gdamore/tcell/v2 v2.7.0/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8=
|
||||
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
|
||||
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
|
||||
github.com/gitchander/permutation v0.0.0-20181107151852-9e56b92e9909 h1:9NC8seTx6/zRmMTAdsHj/uOMi0EGHGQtjyLafBjk77Q=
|
||||
github.com/gitchander/permutation v0.0.0-20181107151852-9e56b92e9909/go.mod h1:lP+DW8LR6Rw3ru9Vo2/y/3iiLaLWmofYql/va+7zJOk=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
@@ -56,12 +44,9 @@ github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7a
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-sql-driver/mysql v1.4.1-0.20190907122137-b2c03bcae3d4 h1:0suja/iKSDbEIYLbrS/8C7iArJiWpgCNcR+zwAHu7Ig=
|
||||
github.com/go-sql-driver/mysql v1.4.1-0.20190907122137-b2c03bcae3d4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
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.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
@@ -69,72 +54,57 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/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/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jinzhu/copier v0.0.0-20170922082739-db4671f3a9b8 h1:+dKzeuiDYbD/Cfi/sEkkNrs6z4/WZ8ZIR8dAbUpjXbU=
|
||||
github.com/jinzhu/copier v0.0.0-20170922082739-db4671f3a9b8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=
|
||||
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
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/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk=
|
||||
github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE=
|
||||
@@ -143,113 +113,129 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/problame/go-netssh v0.0.0-20200601114649-26439f9f0dc5 h1:1eSrO2WAeSXjMol8WRKW9LekL1252VIMaKQwWkmEdvs=
|
||||
github.com/problame/go-netssh v0.0.0-20200601114649-26439f9f0dc5/go.mod h1:Ba6RaFpK1+IHWs1wLZ6sCBuXkt4iAVLeOG5GinXHusM=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
|
||||
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
|
||||
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0=
|
||||
github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592 h1:YIJ+B1hePP6AgynC5TcqpO0H9k3SSoZa2BGyL6vDUzM=
|
||||
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg=
|
||||
github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44 h1:tB9NOR21++IjLyVx3/PCPhWMwqGNCMQEH96A6dMZ/gc=
|
||||
github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE=
|
||||
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/theckman/goconstraint v1.11.0 h1:oBUwN5wpE4dwyPhRGraEgJsFTr+JtLWiDnaJZJeeXI0=
|
||||
github.com/theckman/goconstraint v1.11.0/go.mod h1:zkCR/f2kOULTk/h1ujgyB9BlCNLaqlQ6GN2Zl4mg81g=
|
||||
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d h1:yJIizrfO599ot2kQ6Af1enICnwBD3XoxgX3MrMwot2M=
|
||||
github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||
github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
|
||||
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zrepl/yaml-config v0.0.0-20191220194647-cbb6b0cf4bdd h1:SSo67WLS+99QESvbW8Meibz7zCrxshP71U9dH5KOCXM=
|
||||
github.com/zrepl/yaml-config v0.0.0-20191220194647-cbb6b0cf4bdd/go.mod h1:JmNwisZzOvW4GfpfLvhZ+gtyKLsIiA+WC+wNKJGJaFg=
|
||||
gitlab.com/tslocum/cbind v0.1.4 h1:cbZXPPcieXspk8cShoT6efz7HAT8yMNQcofYWNizis4=
|
||||
gitlab.com/tslocum/cbind v0.1.4/go.mod h1:RvwYE3auSjBNlCmWeGspzn+jdLUVQ8C2QGC+0nP9ChI=
|
||||
gitlab.com/tslocum/cview v1.5.3 h1:6OTCtIUp1EkfGeLqQFRHtW8ynMJ66BhoBwuW8oZ84AQ=
|
||||
gitlab.com/tslocum/cview v1.5.3/go.mod h1:k/eLWRIF3B26VLDgtRRPkjLUXmcCsy+YCSPEAtNQgIY=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
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.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
@@ -261,35 +247,32 @@ google.golang.org/genproto v0.0.0-20210122163508-8081c04a3579 h1:Iwh0ba2kTgq2Q6m
|
||||
google.golang.org/genproto v0.0.0-20210122163508-8081c04a3579/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
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.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||
"github.com/zrepl/zrepl/internal/daemon/logging/trace"
|
||||
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
)
|
||||
|
||||
var rootArgs struct {
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/zrepl/yaml-config"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/daemon/job"
|
||||
"github.com/zrepl/zrepl/daemon/logging"
|
||||
"github.com/zrepl/zrepl/logger"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
||||
"github.com/zrepl/zrepl/internal/logger"
|
||||
)
|
||||
|
||||
var configcheckArgs struct {
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/daemon/job"
|
||||
"github.com/zrepl/zrepl/endpoint"
|
||||
"github.com/zrepl/zrepl/zfs"
|
||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
||||
"github.com/zrepl/zrepl/internal/endpoint"
|
||||
"github.com/zrepl/zrepl/internal/zfs"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -1,6 +1,6 @@
|
||||
package client
|
||||
|
||||
import "github.com/zrepl/zrepl/cli"
|
||||
import "github.com/zrepl/zrepl/internal/cli"
|
||||
|
||||
var PprofCmd = &cli.Subcommand{
|
||||
Use: "pprof",
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
)
|
||||
|
||||
var pprofActivityTraceCmd = &cli.Subcommand{
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/daemon"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
"github.com/zrepl/zrepl/internal/daemon"
|
||||
)
|
||||
|
||||
var pprofListenCmd struct {
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/daemon"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
"github.com/zrepl/zrepl/internal/daemon"
|
||||
)
|
||||
|
||||
var SignalCmd = &cli.Subcommand{
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/zrepl/zrepl/daemon"
|
||||
"github.com/zrepl/zrepl/internal/daemon"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/client/status/client"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/daemon"
|
||||
"github.com/zrepl/zrepl/util/choices"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/client/status/client"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
"github.com/zrepl/zrepl/internal/daemon"
|
||||
"github.com/zrepl/zrepl/internal/util/choices"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/zrepl/zrepl/client/status/viewmodel"
|
||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel"
|
||||
)
|
||||
|
||||
func dump(c Client, job string) error {
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
tview "gitlab.com/tslocum/cview"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/zrepl/zrepl/client/status/viewmodel"
|
||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel"
|
||||
)
|
||||
|
||||
func interactive(c Client, flag statusFlags) error {
|
||||
@@ -29,7 +29,6 @@ func interactive(c Client, flag statusFlags) error {
|
||||
jobMenuRoot.SetSelectable(true)
|
||||
jobMenu.SetRoot(jobMenuRoot)
|
||||
jobMenu.SetCurrentNode(jobMenuRoot)
|
||||
jobMenu.SetSelectedTextColor(tcell.ColorGreen)
|
||||
jobTextDetail := tview.NewTextView()
|
||||
jobTextDetail.SetWrap(false)
|
||||
|
||||
@@ -110,10 +109,8 @@ func interactive(c Client, flag statusFlags) error {
|
||||
}
|
||||
app.SetRoot(toolbarSplit, true)
|
||||
app.SetFocus(preModalFocus)
|
||||
app.Draw()
|
||||
})
|
||||
app.SetRoot(m, true)
|
||||
app.Draw()
|
||||
}
|
||||
|
||||
app.SetRoot(toolbarSplit, true)
|
||||
@@ -170,12 +167,14 @@ func interactive(c Client, flag statusFlags) error {
|
||||
redrawJobsList = true
|
||||
}
|
||||
if redrawJobsList {
|
||||
selectedTextStyle := tcell.StyleDefault.Bold(true)
|
||||
selectedJobN = nil
|
||||
children := make([]*tview.TreeNode, len(jobs))
|
||||
for i := range jobs {
|
||||
jobN := tview.NewTreeNode(jobs[i].JobTreeTitle())
|
||||
jobN.SetReference(jobs[i])
|
||||
jobN.SetSelectable(true)
|
||||
jobN.SetSelectedTextStyle(selectedTextStyle)
|
||||
children[i] = jobN
|
||||
jobN.SetSelectedFunc(func() {
|
||||
viewmodelupdate(func(p *viewmodel.Params) {
|
||||
@@ -187,6 +186,7 @@ func interactive(c Client, flag statusFlags) error {
|
||||
}
|
||||
}
|
||||
jobMenuRoot.SetChildren(children)
|
||||
jobMenuRoot.SetSelectedTextStyle(selectedTextStyle)
|
||||
}
|
||||
|
||||
if selectedJobN != nil && jobMenu.GetCurrentNode() != selectedJobN {
|
||||
@@ -207,9 +207,6 @@ func interactive(c Client, flag statusFlags) error {
|
||||
bottombar.ResizeItem(bottombarDateView, len(bottombardatestring), 0)
|
||||
|
||||
bottomBarStatus.SetText(m.BottomBarStatus())
|
||||
|
||||
app.Draw()
|
||||
|
||||
}
|
||||
|
||||
go func() {
|
||||
@@ -252,6 +249,7 @@ func interactive(c Client, flag statusFlags) error {
|
||||
|
||||
app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
||||
if e.Key() == tcell.KeyTab {
|
||||
// TODO: only if there's no modal showing (long-time bug in zrepl status)
|
||||
tabbableCycle()
|
||||
return nil
|
||||
}
|
||||
@@ -284,9 +282,8 @@ func interactive(c Client, flag statusFlags) error {
|
||||
signals := []string{"wakeup", "reset"}
|
||||
clientFuncs := []func(job string) error{c.SignalWakeup, c.SignalReset}
|
||||
sigMod := tview.NewModal()
|
||||
sigMod.SetBackgroundColor(tcell.ColorDefault)
|
||||
sigMod.SetBorder(true)
|
||||
sigMod.GetForm().SetButtonTextColorFocused(tcell.ColorGreen)
|
||||
sigMod.SetButtonActivatedStyle(tcell.StyleDefault.Bold(true).Reverse(true))
|
||||
sigMod.AddButtons(signals)
|
||||
sigMod.SetText(fmt.Sprintf("Send a signal to job %q", job.Name()))
|
||||
showModal(sigMod, func(idx int, _ string) {
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/pkg/errors"
|
||||
tview "gitlab.com/tslocum/cview"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/zrepl/zrepl/client/status/viewmodel"
|
||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel"
|
||||
)
|
||||
|
||||
func legacy(c Client, flag statusFlags) error {
|
||||
@@ -28,7 +28,7 @@ func legacy(c Client, flag statusFlags) error {
|
||||
textView := tview.NewTextView()
|
||||
textView.SetWrap(true)
|
||||
textView.SetScrollable(true) // so that it allows us to set scroll position
|
||||
textView.SetScrollBarVisibility(tview.ScrollBarNever)
|
||||
// textView.SetScrollBarVisibility(tview.ScrollBarNever)
|
||||
|
||||
app.SetRoot(textView, true)
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
"github.com/go-playground/validator/v10"
|
||||
yaml "github.com/zrepl/yaml-config"
|
||||
|
||||
"github.com/zrepl/zrepl/client/status/viewmodel/stringbuilder"
|
||||
"github.com/zrepl/zrepl/daemon"
|
||||
"github.com/zrepl/zrepl/daemon/job"
|
||||
"github.com/zrepl/zrepl/daemon/pruner"
|
||||
"github.com/zrepl/zrepl/daemon/snapper"
|
||||
"github.com/zrepl/zrepl/replication/report"
|
||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel/stringbuilder"
|
||||
"github.com/zrepl/zrepl/internal/daemon"
|
||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
||||
"github.com/zrepl/zrepl/internal/daemon/pruner"
|
||||
"github.com/zrepl/zrepl/internal/daemon/snapper"
|
||||
"github.com/zrepl/zrepl/internal/replication/report"
|
||||
)
|
||||
|
||||
type M struct {
|
||||
@@ -374,13 +374,15 @@ func renderReplicationReport(t *stringbuilder.B, rep *report.Report, history *by
|
||||
eta = time.Duration((float64(expected)-float64(replicated))/float64(rate)) * time.Second
|
||||
}
|
||||
|
||||
t.Write("Progress: ")
|
||||
t.DrawBar(50, replicated, expected, changeCount)
|
||||
t.Write(fmt.Sprintf(" %s / %s @ %s/s", ByteCountBinaryUint(replicated), ByteCountBinaryUint(expected), ByteCountBinary(rate)))
|
||||
if eta != 0 {
|
||||
t.Write(fmt.Sprintf(" (%s remaining)", humanizeDuration(eta)))
|
||||
if !latest.State.IsTerminal() {
|
||||
t.Write("Progress: ")
|
||||
t.DrawBar(50, replicated, expected, changeCount)
|
||||
t.Write(fmt.Sprintf(" %s / %s @ %s/s", ByteCountBinaryUint(replicated), ByteCountBinaryUint(expected), ByteCountBinary(rate)))
|
||||
if eta != 0 {
|
||||
t.Write(fmt.Sprintf(" (%s remaining)", humanizeDuration(eta)))
|
||||
}
|
||||
t.Newline()
|
||||
}
|
||||
t.Newline()
|
||||
if containsInvalidSizeEstimates {
|
||||
t.Write("NOTE: not all steps could be size-estimated, total estimate is likely imprecise!")
|
||||
t.Newline()
|
||||
@@ -493,15 +495,17 @@ func renderPrunerReport(t *stringbuilder.B, r *pruner.Report, fsfilter FilterFun
|
||||
}
|
||||
|
||||
// global progress bar
|
||||
progress := int(math.Round(80 * float64(completedDestroyCount) / float64(totalDestroyCount)))
|
||||
t.Write("Progress: ")
|
||||
t.Write("[")
|
||||
t.Write(stringbuilder.Times("=", progress))
|
||||
t.Write(">")
|
||||
t.Write(stringbuilder.Times("-", 80-progress))
|
||||
t.Write("]")
|
||||
t.Printf(" %d/%d snapshots", completedDestroyCount, totalDestroyCount)
|
||||
t.Newline()
|
||||
if !state.IsTerminal() {
|
||||
progress := int(math.Round(80 * float64(completedDestroyCount) / float64(totalDestroyCount)))
|
||||
t.Write("Progress: ")
|
||||
t.Write("[")
|
||||
t.Write(stringbuilder.Times("=", progress))
|
||||
t.Write(">")
|
||||
t.Write(stringbuilder.Times("-", 80-progress))
|
||||
t.Write("]")
|
||||
t.Printf(" %d/%d snapshots", completedDestroyCount, totalDestroyCount)
|
||||
t.Newline()
|
||||
}
|
||||
|
||||
sort.SliceStable(all, func(i, j int) bool {
|
||||
return strings.Compare(all[i].Filesystem, all[j].Filesystem) == -1
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/problame/go-netssh"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
|
||||
"context"
|
||||
"errors"
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/daemon/filters"
|
||||
"github.com/zrepl/zrepl/zfs"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
||||
"github.com/zrepl/zrepl/internal/zfs"
|
||||
)
|
||||
|
||||
var TestCmd = &cli.Subcommand{
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
"github.com/zrepl/zrepl/daemon"
|
||||
"github.com/zrepl/zrepl/version"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/config"
|
||||
"github.com/zrepl/zrepl/internal/daemon"
|
||||
"github.com/zrepl/zrepl/internal/version"
|
||||
)
|
||||
|
||||
var versionArgs struct {
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/daemon/filters"
|
||||
"github.com/zrepl/zrepl/endpoint"
|
||||
"github.com/zrepl/zrepl/zfs"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
||||
"github.com/zrepl/zrepl/internal/endpoint"
|
||||
"github.com/zrepl/zrepl/internal/zfs"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -57,7 +57,7 @@ func (f *zabsFilterFlags) registerZabsFilterFlags(s *pflag.FlagSet, verb string)
|
||||
for v := range endpoint.AbstractionTypesAll {
|
||||
variants = append(variants, string(v))
|
||||
}
|
||||
variants = sort.StringSlice(variants)
|
||||
sort.Strings(variants)
|
||||
variantsJoined := strings.Join(variants, "|")
|
||||
s.Var(&f.Types, "type", fmt.Sprintf("only %s holds of the specified type [default: all] [comma-separated list of %s]", verb, variantsJoined))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package client
|
||||
|
||||
import "github.com/zrepl/zrepl/cli"
|
||||
import "github.com/zrepl/zrepl/internal/cli"
|
||||
|
||||
var zabsCmdCreate = &cli.Subcommand{
|
||||
Use: "create",
|
||||
+3
-3
@@ -7,9 +7,9 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/endpoint"
|
||||
"github.com/zrepl/zrepl/zfs"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/endpoint"
|
||||
"github.com/zrepl/zrepl/internal/zfs"
|
||||
)
|
||||
|
||||
var zabsCreateStepHoldFlags struct {
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/endpoint"
|
||||
"github.com/zrepl/zrepl/util/chainlock"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/endpoint"
|
||||
"github.com/zrepl/zrepl/internal/util/chainlock"
|
||||
)
|
||||
|
||||
var zabsListFlags struct {
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/endpoint"
|
||||
"github.com/zrepl/zrepl/internal/cli"
|
||||
"github.com/zrepl/zrepl/internal/endpoint"
|
||||
)
|
||||
|
||||
// shared between release-all and release-step
|
||||
@@ -2,20 +2,16 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log/syslog"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/zrepl/yaml-config"
|
||||
|
||||
"github.com/zrepl/zrepl/util/datasizeunit"
|
||||
zfsprop "github.com/zrepl/zrepl/zfs/property"
|
||||
"github.com/zrepl/zrepl/internal/util/datasizeunit"
|
||||
zfsprop "github.com/zrepl/zrepl/internal/zfs/property"
|
||||
)
|
||||
|
||||
type ParseFlags uint
|
||||
@@ -26,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Jobs []JobEnum `yaml:"jobs"`
|
||||
Jobs []JobEnum `yaml:"jobs,optional"`
|
||||
Global *Global `yaml:"global,optional,fromdefaults"`
|
||||
}
|
||||
|
||||
@@ -67,7 +63,6 @@ type ActiveJob struct {
|
||||
Name string `yaml:"name"`
|
||||
Connect ConnectEnum `yaml:"connect"`
|
||||
Pruning PruningSenderReceiver `yaml:"pruning"`
|
||||
Debug JobDebugSettings `yaml:"debug,optional"`
|
||||
Replication *Replication `yaml:"replication,optional,fromdefaults"`
|
||||
ConflictResolution *ConflictResolution `yaml:"conflict_resolution,optional,fromdefaults"`
|
||||
}
|
||||
@@ -77,17 +72,15 @@ type ConflictResolution struct {
|
||||
}
|
||||
|
||||
type PassiveJob struct {
|
||||
Type string `yaml:"type"`
|
||||
Name string `yaml:"name"`
|
||||
Serve ServeEnum `yaml:"serve"`
|
||||
Debug JobDebugSettings `yaml:"debug,optional"`
|
||||
Type string `yaml:"type"`
|
||||
Name string `yaml:"name"`
|
||||
Serve ServeEnum `yaml:"serve"`
|
||||
}
|
||||
|
||||
type SnapJob struct {
|
||||
Type string `yaml:"type"`
|
||||
Name string `yaml:"name"`
|
||||
Pruning PruningLocal `yaml:"pruning"`
|
||||
Debug JobDebugSettings `yaml:"debug,optional"`
|
||||
Snapshotting SnapshottingEnum `yaml:"snapshotting"`
|
||||
Filesystems FilesystemsFilter `yaml:"filesystems"`
|
||||
}
|
||||
@@ -190,13 +183,10 @@ func (i *PositiveDurationOrManual) UnmarshalYAML(u func(interface{}, bool) error
|
||||
return fmt.Errorf("value must not be empty")
|
||||
default:
|
||||
i.Manual = false
|
||||
i.Interval, err = time.ParseDuration(s)
|
||||
i.Interval, err = parsePositiveDuration(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if i.Interval <= 0 {
|
||||
return fmt.Errorf("value must be a positive duration, got %q", s)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -228,10 +218,16 @@ type SnapshottingEnum struct {
|
||||
}
|
||||
|
||||
type SnapshottingPeriodic struct {
|
||||
Type string `yaml:"type"`
|
||||
Prefix string `yaml:"prefix"`
|
||||
Interval time.Duration `yaml:"interval,positive"`
|
||||
Hooks HookList `yaml:"hooks,optional"`
|
||||
Type string `yaml:"type"`
|
||||
Prefix string `yaml:"prefix"`
|
||||
Interval *PositiveDuration `yaml:"interval"`
|
||||
Hooks HookList `yaml:"hooks,optional"`
|
||||
TimestampFormattingSpec `yaml:",inline"`
|
||||
}
|
||||
|
||||
type TimestampFormattingSpec struct {
|
||||
TimestampFormat string `yaml:"timestamp_format,optional,default=dense"`
|
||||
TimestampLocation string `yaml:"timestamp_location,optional,default=UTC"`
|
||||
}
|
||||
|
||||
type CronSpec struct {
|
||||
@@ -260,10 +256,11 @@ func (s *CronSpec) UnmarshalYAML(unmarshal func(v interface{}, not_strict bool)
|
||||
}
|
||||
|
||||
type SnapshottingCron struct {
|
||||
Type string `yaml:"type"`
|
||||
Prefix string `yaml:"prefix"`
|
||||
Cron CronSpec `yaml:"cron"`
|
||||
Hooks HookList `yaml:"hooks,optional"`
|
||||
Type string `yaml:"type"`
|
||||
Prefix string `yaml:"prefix"`
|
||||
Cron CronSpec `yaml:"cron"`
|
||||
Hooks HookList `yaml:"hooks,optional"`
|
||||
TimestampFormattingSpec `yaml:",inline"`
|
||||
}
|
||||
|
||||
type SnapshottingManual struct {
|
||||
@@ -305,18 +302,6 @@ type Global struct {
|
||||
Serve *GlobalServe `yaml:"serve,optional,fromdefaults"`
|
||||
}
|
||||
|
||||
func Default(i interface{}) {
|
||||
v := reflect.ValueOf(i)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
panic(v)
|
||||
}
|
||||
y := `{}`
|
||||
err := yaml.Unmarshal([]byte(y), v.Interface())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type ConnectEnum struct {
|
||||
Ret interface{}
|
||||
}
|
||||
@@ -483,14 +468,6 @@ type GlobalStdinServer struct {
|
||||
SockDir string `yaml:"sockdir,default=/var/run/zrepl/stdinserver"`
|
||||
}
|
||||
|
||||
type JobDebugSettings struct {
|
||||
Conn *struct {
|
||||
ReadDump string `yaml:"read_dump"`
|
||||
WriteDump string `yaml:"write_dump"`
|
||||
} `yaml:"conn,optional"`
|
||||
RPCLog bool `yaml:"rpc_log,optional,default=false"`
|
||||
}
|
||||
|
||||
type HookList []HookEnum
|
||||
|
||||
type HookEnum struct {
|
||||
@@ -698,7 +675,7 @@ func ParseConfig(path string) (i *Config, err error) {
|
||||
|
||||
var bytes []byte
|
||||
|
||||
if bytes, err = ioutil.ReadFile(path); err != nil {
|
||||
if bytes, err = os.ReadFile(path); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -710,46 +687,16 @@ func ParseConfigBytes(bytes []byte) (*Config, error) {
|
||||
if err := yaml.UnmarshalStrict(bytes, &c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c != nil {
|
||||
return c, nil
|
||||
}
|
||||
// There was no yaml document in the file, deserialize from default.
|
||||
// => See TestFromdefaultsEmptyDoc in yaml-config package.
|
||||
if err := yaml.UnmarshalStrict([]byte("{}"), &c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c == nil {
|
||||
return nil, fmt.Errorf("config is empty or only consists of comments")
|
||||
panic("the fallback to deserialize from `{}` should work")
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
var durationStringRegex *regexp.Regexp = regexp.MustCompile(`^\s*(\d+)\s*(s|m|h|d|w)\s*$`)
|
||||
|
||||
func parsePositiveDuration(e string) (d time.Duration, err error) {
|
||||
comps := durationStringRegex.FindStringSubmatch(e)
|
||||
if len(comps) != 3 {
|
||||
err = fmt.Errorf("does not match regex: %s %#v", e, comps)
|
||||
return
|
||||
}
|
||||
|
||||
durationFactor, err := strconv.ParseInt(comps[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if durationFactor <= 0 {
|
||||
return 0, errors.New("duration must be positive integer")
|
||||
}
|
||||
|
||||
var durationUnit time.Duration
|
||||
switch comps[2] {
|
||||
case "s":
|
||||
durationUnit = time.Second
|
||||
case "m":
|
||||
durationUnit = time.Minute
|
||||
case "h":
|
||||
durationUnit = time.Hour
|
||||
case "d":
|
||||
durationUnit = 24 * time.Hour
|
||||
case "w":
|
||||
durationUnit = 24 * 7 * time.Hour
|
||||
default:
|
||||
err = fmt.Errorf("contains unknown time unit '%s'", comps[2])
|
||||
return
|
||||
}
|
||||
|
||||
d = time.Duration(durationFactor) * durationUnit
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"github.com/zrepl/yaml-config"
|
||||
)
|
||||
|
||||
type Duration struct{ d time.Duration }
|
||||
|
||||
func (d Duration) Duration() time.Duration { return d.d }
|
||||
|
||||
var _ yaml.Unmarshaler = &Duration{}
|
||||
|
||||
func (d *Duration) UnmarshalYAML(unmarshal func(v interface{}, not_strict bool) error) error {
|
||||
var s string
|
||||
err := unmarshal(&s, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.d, err = parseDuration(s)
|
||||
if err != nil {
|
||||
d.d = 0
|
||||
return &yaml.TypeError{Errors: []string{fmt.Sprintf("cannot parse value %q: %s", s, err)}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PositiveDuration struct{ d Duration }
|
||||
|
||||
var _ yaml.Unmarshaler = &PositiveDuration{}
|
||||
|
||||
func (d PositiveDuration) Duration() time.Duration { return d.d.Duration() }
|
||||
|
||||
func (d *PositiveDuration) UnmarshalYAML(unmarshal func(v interface{}, not_strict bool) error) error {
|
||||
err := d.d.UnmarshalYAML(unmarshal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.d.Duration() <= 0 {
|
||||
return fmt.Errorf("duration must be positive, got %s", d.d.Duration())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parsePositiveDuration(e string) (time.Duration, error) {
|
||||
d, err := parseDuration(e)
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
if d <= 0 {
|
||||
return 0, errors.New("duration must be positive integer")
|
||||
}
|
||||
return d, err
|
||||
}
|
||||
|
||||
var durationStringRegex *regexp.Regexp = regexp.MustCompile(`^\s*([\+-]?\d+)\s*(|s|m|h|d|w)\s*$`)
|
||||
|
||||
func parseDuration(e string) (d time.Duration, err error) {
|
||||
comps := durationStringRegex.FindStringSubmatch(e)
|
||||
if comps == nil {
|
||||
err = fmt.Errorf("must match %s", durationStringRegex)
|
||||
return
|
||||
}
|
||||
if len(comps) != 3 {
|
||||
panic(pretty.Sprint(comps))
|
||||
}
|
||||
|
||||
durationFactor, err := strconv.ParseInt(comps[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var durationUnit time.Duration
|
||||
switch comps[2] {
|
||||
case "":
|
||||
if durationFactor != 0 {
|
||||
err = fmt.Errorf("missing time unit")
|
||||
return
|
||||
} else {
|
||||
// It's the case where user specified '0'.
|
||||
// We want to allow this, just like time.ParseDuration.
|
||||
}
|
||||
case "s":
|
||||
durationUnit = time.Second
|
||||
case "m":
|
||||
durationUnit = time.Minute
|
||||
case "h":
|
||||
durationUnit = time.Hour
|
||||
case "d":
|
||||
durationUnit = 24 * time.Hour
|
||||
case "w":
|
||||
durationUnit = 24 * 7 * time.Hour
|
||||
default:
|
||||
err = fmt.Errorf("contains unknown time unit '%s'", comps[2])
|
||||
return
|
||||
}
|
||||
|
||||
d = time.Duration(durationFactor) * durationUnit
|
||||
return
|
||||
}
|
||||
@@ -2,16 +2,8 @@ package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConfigEmptyFails(t *testing.T) {
|
||||
conf, err := testConfig(t, "\n")
|
||||
assert.Nil(t, conf)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestJobsOnlyWorks(t *testing.T) {
|
||||
testValidConfig(t, `
|
||||
jobs:
|
||||
@@ -34,7 +26,7 @@ jobs:
|
||||
keep_sender:
|
||||
- type: not_replicated
|
||||
keep_receiver:
|
||||
- type: last_n
|
||||
- type: last_n
|
||||
count: 1
|
||||
`)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
zfsprop "github.com/zrepl/zrepl/zfs/property"
|
||||
zfsprop "github.com/zrepl/zrepl/internal/zfs/property"
|
||||
)
|
||||
|
||||
func TestRecvOptions(t *testing.T) {
|
||||
@@ -0,0 +1,178 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSnapshotting(t *testing.T) {
|
||||
tmpl := `
|
||||
jobs:
|
||||
- name: foo
|
||||
type: push
|
||||
connect:
|
||||
type: local
|
||||
listener_name: foo
|
||||
client_identity: bar
|
||||
filesystems: {"<": true}
|
||||
%s
|
||||
pruning:
|
||||
keep_sender:
|
||||
- type: last_n
|
||||
count: 10
|
||||
keep_receiver:
|
||||
- type: last_n
|
||||
count: 10
|
||||
`
|
||||
manual := `
|
||||
snapshotting:
|
||||
type: manual
|
||||
`
|
||||
periodic := `
|
||||
snapshotting:
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
timestamp_format: dense
|
||||
interval: 10m
|
||||
`
|
||||
cron := `
|
||||
snapshotting:
|
||||
type: cron
|
||||
prefix: zrepl_
|
||||
timestamp_format: human
|
||||
cron: "10 * * * *"
|
||||
`
|
||||
|
||||
periodicDaily := `
|
||||
snapshotting:
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 1d
|
||||
`
|
||||
|
||||
hooks := `
|
||||
snapshotting:
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 10m
|
||||
hooks:
|
||||
- type: command
|
||||
path: /tmp/path/to/command
|
||||
- type: command
|
||||
path: /tmp/path/to/command
|
||||
filesystems: { "zroot<": true, "<": false }
|
||||
- type: postgres-checkpoint
|
||||
dsn: "host=localhost port=5432 user=postgres sslmode=disable"
|
||||
filesystems: {
|
||||
"tank/postgres/data11": true
|
||||
}
|
||||
- type: mysql-lock-tables
|
||||
dsn: "root@tcp(localhost)/"
|
||||
filesystems: {
|
||||
"tank/mysql": true
|
||||
}
|
||||
`
|
||||
|
||||
fillSnapshotting := func(s string) string { return fmt.Sprintf(tmpl, s) }
|
||||
var c *Config
|
||||
|
||||
t.Run("manual", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(manual))
|
||||
snm := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingManual)
|
||||
assert.Equal(t, "manual", snm.Type)
|
||||
})
|
||||
|
||||
t.Run("periodic", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(periodic))
|
||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingPeriodic)
|
||||
assert.Equal(t, "periodic", snp.Type)
|
||||
assert.Equal(t, 10*time.Minute, snp.Interval.Duration())
|
||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||
})
|
||||
|
||||
t.Run("periodicDaily", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(periodicDaily))
|
||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingPeriodic)
|
||||
assert.Equal(t, "periodic", snp.Type)
|
||||
assert.Equal(t, 24*time.Hour, snp.Interval.Duration())
|
||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||
assert.Equal(t, "dense", snp.TimestampFormat)
|
||||
})
|
||||
|
||||
t.Run("cron", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(cron))
|
||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingCron)
|
||||
assert.Equal(t, "cron", snp.Type)
|
||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||
assert.Equal(t, "human", snp.TimestampFormat)
|
||||
})
|
||||
|
||||
t.Run("hooks", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(hooks))
|
||||
hs := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingPeriodic).Hooks
|
||||
assert.Equal(t, hs[0].Ret.(*HookCommand).Filesystems["<"], true)
|
||||
assert.Equal(t, hs[1].Ret.(*HookCommand).Filesystems["zroot<"], true)
|
||||
assert.Equal(t, hs[2].Ret.(*HookPostgresCheckpoint).Filesystems["tank/postgres/data11"], true)
|
||||
assert.Equal(t, hs[3].Ret.(*HookMySQLLockTables).Filesystems["tank/mysql"], true)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestSnapshottingTimestampDefaults(t *testing.T) {
|
||||
tmpl := `
|
||||
jobs:
|
||||
- name: foo
|
||||
type: push
|
||||
connect:
|
||||
type: local
|
||||
listener_name: foo
|
||||
client_identity: bar
|
||||
filesystems: {"<": true}
|
||||
%s
|
||||
pruning:
|
||||
keep_sender:
|
||||
- type: last_n
|
||||
count: 10
|
||||
keep_receiver:
|
||||
- type: last_n
|
||||
count: 10
|
||||
`
|
||||
|
||||
periodic := `
|
||||
snapshotting:
|
||||
type: periodic
|
||||
prefix: zrepl_
|
||||
interval: 10m
|
||||
`
|
||||
cron := `
|
||||
snapshotting:
|
||||
type: cron
|
||||
prefix: zrepl_
|
||||
cron: "10 * * * *"
|
||||
`
|
||||
|
||||
fillSnapshotting := func(s string) string { return fmt.Sprintf(tmpl, s) }
|
||||
var c *Config
|
||||
|
||||
t.Run("periodic", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(periodic))
|
||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingPeriodic)
|
||||
assert.Equal(t, "periodic", snp.Type)
|
||||
assert.Equal(t, 10*time.Minute, snp.Interval.Duration())
|
||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||
assert.Equal(t, snp.TimestampFormat, "dense")
|
||||
assert.Equal(t, snp.TimestampLocation, "UTC")
|
||||
})
|
||||
|
||||
t.Run("cron", func(t *testing.T) {
|
||||
c = testValidConfig(t, fillSnapshotting(cron))
|
||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingCron)
|
||||
assert.Equal(t, "cron", snp.Type)
|
||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||
assert.Equal(t, snp.TimestampFormat, "dense")
|
||||
assert.Equal(t, snp.TimestampLocation, "UTC")
|
||||
})
|
||||
}
|
||||
@@ -22,6 +22,8 @@ func TestSampleConfigsAreParsedWithoutErrors(t *testing.T) {
|
||||
t.Errorf("glob failed: %+v", err)
|
||||
}
|
||||
|
||||
paths = append(paths, "../../packaging/systemd-default-zrepl.yml")
|
||||
|
||||
for _, p := range paths {
|
||||
|
||||
if path.Ext(p) != ".yml" {
|
||||
@@ -44,7 +46,8 @@ func TestSampleConfigsAreParsedWithoutErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
// template must be a template/text template with a single '{{ . }}' as placeholder for val
|
||||
//nolint[:deadcode,unused]
|
||||
//
|
||||
//nolint:deadcode,unused
|
||||
func testValidConfigTemplate(t *testing.T, tmpl string, val string) *Config {
|
||||
tmp, err := template.New("master").Parse(tmpl)
|
||||
if err != nil {
|
||||
@@ -83,7 +86,7 @@ func trimSpaceEachLineAndPad(s, pad string) string {
|
||||
func TestTrimSpaceEachLineAndPad(t *testing.T) {
|
||||
foo := `
|
||||
foo
|
||||
bar baz
|
||||
bar baz
|
||||
`
|
||||
assert.Equal(t, " \n foo\n bar baz\n \n", trimSpaceEachLineAndPad(foo, " "))
|
||||
}
|
||||
@@ -137,3 +140,18 @@ func TestCronSpec(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestEmptyConfig(t *testing.T) {
|
||||
cases := []string{
|
||||
"",
|
||||
"\n",
|
||||
"---",
|
||||
"---\n",
|
||||
}
|
||||
for _, input := range cases {
|
||||
config := testValidConfig(t, input)
|
||||
require.NotNil(t, config)
|
||||
require.NotNil(t, config.Global)
|
||||
require.Empty(t, config.Jobs)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user