Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| beecb4b93d | |||
| c8afaf83ab | |||
| b0caa2d151 |
+45
-41
@@ -1,8 +1,8 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
orbs:
|
orbs:
|
||||||
# NB: this is not the Go version, but the Orb version
|
# NB: 1.7.2 is not the Go version, but the Orb version
|
||||||
# https://circleci.com/developer/orbs/orb/circleci/go#usage-go-modules-cache
|
# https://circleci.com/developer/orbs/orb/circleci/go#usage-go-modules-cache
|
||||||
go: circleci/go@1.11.0
|
go: circleci/go@1.7.2
|
||||||
commands:
|
commands:
|
||||||
setup-home-local-bin:
|
setup-home-local-bin:
|
||||||
steps:
|
steps:
|
||||||
@@ -15,6 +15,16 @@ commands:
|
|||||||
echo "$line" >> $BASH_ENV
|
echo "$line" >> $BASH_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
invoke-lazy-sh:
|
||||||
|
parameters:
|
||||||
|
subcommand:
|
||||||
|
type: string
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
environment:
|
||||||
|
TERM: xterm
|
||||||
|
command: ./lazy.sh <<parameters.subcommand>>
|
||||||
|
|
||||||
apt-update-and-install-common-deps:
|
apt-update-and-install-common-deps:
|
||||||
steps:
|
steps:
|
||||||
- run: sudo apt-get update
|
- run: sudo apt-get update
|
||||||
@@ -24,12 +34,18 @@ commands:
|
|||||||
# The need for this was required for cimg/go:1.12, but let's future proof this here and now.
|
# 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
|
- run: sudo apt-get install -y git ca-certificates
|
||||||
|
|
||||||
|
install-godep:
|
||||||
|
steps:
|
||||||
|
- apt-update-and-install-common-deps
|
||||||
|
- invoke-lazy-sh:
|
||||||
|
subcommand: godep
|
||||||
|
|
||||||
install-docdep:
|
install-docdep:
|
||||||
steps:
|
steps:
|
||||||
- apt-update-and-install-common-deps
|
- apt-update-and-install-common-deps
|
||||||
- run: sudo apt install python3 python3-pip libgirepository1.0-dev
|
- run: sudo apt install python3 python3-pip libgirepository1.0-dev
|
||||||
- run: pip3 install -r docs/requirements.txt
|
- invoke-lazy-sh:
|
||||||
|
subcommand: docdep
|
||||||
|
|
||||||
docs-publish-sh:
|
docs-publish-sh:
|
||||||
parameters:
|
parameters:
|
||||||
@@ -83,6 +99,10 @@ parameters:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
|
release_docker_baseimage_tag:
|
||||||
|
type: string
|
||||||
|
default: "1.21"
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
@@ -90,20 +110,20 @@ workflows:
|
|||||||
when: << pipeline.parameters.do_ci >>
|
when: << pipeline.parameters.do_ci >>
|
||||||
jobs:
|
jobs:
|
||||||
- quickcheck-docs
|
- quickcheck-docs
|
||||||
- quickcheck-go:
|
- quickcheck-go: &quickcheck-go-smoketest
|
||||||
name: quickcheck-go-amd64-linux-1.23.1
|
name: quickcheck-go-amd64-linux-1.21
|
||||||
goversion: &latest-go-release "1.23.1"
|
goversion: &latest-go-release "1.21"
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
- test-go:
|
- test-go-on-latest-go-release:
|
||||||
goversion: *latest-go-release
|
goversion: *latest-go-release
|
||||||
- quickcheck-go:
|
- quickcheck-go:
|
||||||
requires:
|
requires:
|
||||||
- quickcheck-go-amd64-linux-1.23.1 #quickcheck-go-smoketest.name
|
- quickcheck-go-amd64-linux-1.21 #quickcheck-go-smoketest.name
|
||||||
matrix:
|
matrix: &quickcheck-go-matrix
|
||||||
alias: quickcheck-go-matrix
|
alias: quickcheck-go-matrix
|
||||||
parameters:
|
parameters:
|
||||||
goversion: [*latest-go-release, "1.22.7"]
|
goversion: [*latest-go-release, "1.20"]
|
||||||
goos: ["linux", "freebsd"]
|
goos: ["linux", "freebsd"]
|
||||||
goarch: ["amd64", "arm64"]
|
goarch: ["amd64", "arm64"]
|
||||||
exclude:
|
exclude:
|
||||||
@@ -118,7 +138,6 @@ workflows:
|
|||||||
goos: ["linux"]
|
goos: ["linux"]
|
||||||
goarch: ["amd64"]
|
goarch: ["amd64"]
|
||||||
requires:
|
requires:
|
||||||
- test-go
|
|
||||||
- quickcheck-go-<< matrix.goarch >>-<< matrix.goos >>-<< matrix.goversion >>
|
- quickcheck-go-<< matrix.goarch >>-<< matrix.goos >>-<< matrix.goversion >>
|
||||||
|
|
||||||
release:
|
release:
|
||||||
@@ -148,7 +167,7 @@ workflows:
|
|||||||
jobs:
|
jobs:
|
||||||
quickcheck-docs:
|
quickcheck-docs:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/base:2024.09
|
- image: cimg/base:2023.09
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- install-docdep
|
- install-docdep
|
||||||
@@ -167,41 +186,29 @@ jobs:
|
|||||||
goarch:
|
goarch:
|
||||||
type: string
|
type: string
|
||||||
docker:
|
docker:
|
||||||
# any toolchain >= 1.22 will auto-download GOTOOLCHAIN
|
- image: cimg/go:<<parameters.goversion>>
|
||||||
- image: &cimg_with_modern_go cimg/go:1.22
|
|
||||||
environment:
|
environment:
|
||||||
GOOS: <<parameters.goos>>
|
GOOS: <<parameters.goos>>
|
||||||
GOARCH: <<parameters.goarch>>
|
GOARCH: <<parameters.goarch>>
|
||||||
GOTOOLCHAIN: "go<<parameters.goversion>>"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
|
|
||||||
- go/load-cache:
|
- go/load-cache:
|
||||||
key: quickcheck-<<parameters.goversion>>
|
key: quickcheck-<<parameters.goversion>>
|
||||||
- run: make build/install
|
- install-godep
|
||||||
- run: go mod download
|
- run: go mod download
|
||||||
- run: cd build && go mod download
|
- run: cd build && go mod download
|
||||||
- go/save-cache:
|
- go/save-cache:
|
||||||
key: quickcheck-<<parameters.goversion>>
|
key: quickcheck-<<parameters.goversion>>
|
||||||
|
|
||||||
# ensure all code has been generated
|
- run: make formatcheck
|
||||||
- run: make generate
|
- run: make generate-platform-test-list
|
||||||
- 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 zrepl-bin test-platform-bin
|
||||||
- run: make vet
|
- run: make vet
|
||||||
- run: make lint
|
- run: make lint
|
||||||
|
|
||||||
|
- run: rm -f artifacts/generate-platform-test-list
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: artifacts
|
path: artifacts
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
@@ -230,14 +237,12 @@ jobs:
|
|||||||
- run: sudo zfs version
|
- run: sudo zfs version
|
||||||
- run: sudo make test-platform GOOS="$GOOS" GOARCH="$GOARCH"
|
- run: sudo make test-platform GOOS="$GOOS" GOARCH="$GOARCH"
|
||||||
|
|
||||||
test-go:
|
test-go-on-latest-go-release:
|
||||||
parameters:
|
parameters:
|
||||||
goversion:
|
goversion:
|
||||||
type: string
|
type: string
|
||||||
docker:
|
docker:
|
||||||
- image: *cimg_with_modern_go
|
- image: cimg/go:<<parameters.goversion>>
|
||||||
environment:
|
|
||||||
GOTOOLCHAIN: "go<<parameters.goversion>>"
|
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- go/load-cache:
|
- go/load-cache:
|
||||||
@@ -248,17 +253,16 @@ jobs:
|
|||||||
|
|
||||||
release-build:
|
release-build:
|
||||||
machine:
|
machine:
|
||||||
image: &release-vm-image "ubuntu-2404:current"
|
image: ubuntu-2004:202201-02
|
||||||
resource_class: large
|
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: make release-docker
|
- run: make release-docker RELEASE_DOCKER_BASEIMAGE_TAG=<<pipeline.parameters.release_docker_baseimage_tag>>
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths: [.]
|
paths: [.]
|
||||||
release-deb:
|
release-deb:
|
||||||
machine:
|
machine:
|
||||||
image: *release-vm-image
|
image: ubuntu-2004:202201-02
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: .
|
at: .
|
||||||
@@ -270,7 +274,7 @@ jobs:
|
|||||||
|
|
||||||
release-rpm:
|
release-rpm:
|
||||||
machine:
|
machine:
|
||||||
image: *release-vm-image
|
image: ubuntu-2004:202201-02
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: .
|
at: .
|
||||||
@@ -282,17 +286,17 @@ jobs:
|
|||||||
|
|
||||||
release-upload:
|
release-upload:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/base:2024.09
|
- image: cimg/base:2020.08
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: .
|
at: .
|
||||||
- run: make wrapup-and-checksum
|
- run: make wrapup-and-checksum
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: artifacts/release
|
path: artifacts
|
||||||
|
|
||||||
publish-zrepl-github-io:
|
publish-zrepl-github-io:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/base:2024.09
|
- image: cimg/base:2023.09
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- install-docdep
|
- install-docdep
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
#!/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"'" }}'
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
# Docs use Python only for static site generation.
|
|
||||||
- package-ecosystem: "pip"
|
|
||||||
directory: /docs
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
ignore:
|
|
||||||
- dependency-name: "*"
|
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- goimports
|
- goimports
|
||||||
- revive
|
|
||||||
|
|
||||||
linters-settings:
|
|
||||||
goimports:
|
|
||||||
local-prefixes: github.com/zrepl/zrepl
|
|
||||||
revive:
|
|
||||||
rules:
|
|
||||||
- name: time-equal
|
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
|
|||||||
@@ -22,17 +22,16 @@ GOARCH ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOARCH"')
|
|||||||
GOARM ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOARM"')
|
GOARM ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOARM"')
|
||||||
GOHOSTOS ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOHOSTOS"')
|
GOHOSTOS ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOHOSTOS"')
|
||||||
GOHOSTARCH ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOHOSTARCH"')
|
GOHOSTARCH ?= $(shell bash -c 'source <($(GO) env) && echo "$$GOHOSTARCH"')
|
||||||
GO_ENV_VARS := CGO_ENABLED=0
|
GO_ENV_VARS := GO111MODULE=on CGO_ENABLED=0
|
||||||
GO_LDFLAGS := "-X github.com/zrepl/zrepl/version.zreplVersion=$(_ZREPL_VERSION)"
|
GO_LDFLAGS := "-X github.com/zrepl/zrepl/version.zreplVersion=$(_ZREPL_VERSION)"
|
||||||
GO_MOD_READONLY := -mod=readonly
|
GO_MOD_READONLY := -mod=readonly
|
||||||
GO_EXTRA_BUILDFLAGS :=
|
GO_EXTRA_BUILDFLAGS :=
|
||||||
GO_BUILDFLAGS := $(GO_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)
|
GO_BUILD := $(GO_ENV_VARS) $(GO) build $(GO_BUILDFLAGS) -ldflags $(GO_LDFLAGS)
|
||||||
|
GOLANGCI_LINT := golangci-lint
|
||||||
GOCOVMERGE := gocovmerge
|
GOCOVMERGE := gocovmerge
|
||||||
RELEASE_GOVERSION ?= go1.23.1
|
RELEASE_DOCKER_BASEIMAGE_TAG ?= 1.21
|
||||||
STRIPPED_GOVERSION := $(subst go,,$(RELEASE_GOVERSION))
|
RELEASE_DOCKER_BASEIMAGE ?= golang:$(RELEASE_DOCKER_BASEIMAGE_TAG)
|
||||||
RELEASE_DOCKER_BASEIMAGE ?= golang:$(STRIPPED_GOVERSION)
|
|
||||||
RELEASE_DOCKER_CACHEMOUNT :=
|
|
||||||
|
|
||||||
ifneq ($(GOARM),)
|
ifneq ($(GOARM),)
|
||||||
ZREPL_TARGET_TUPLE := $(GOOS)-$(GOARCH)v$(GOARM)
|
ZREPL_TARGET_TUPLE := $(GOOS)-$(GOARCH)v$(GOARM)
|
||||||
@@ -40,46 +39,33 @@ else
|
|||||||
ZREPL_TARGET_TUPLE := $(GOOS)-$(GOARCH)
|
ZREPL_TARGET_TUPLE := $(GOOS)-$(GOARCH)
|
||||||
endif
|
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 #############
|
##################### PRODUCING A RELEASE #############
|
||||||
.PHONY: release wrapup-and-checksum check-git-clean sign clean ensure-release-toolchain
|
.PHONY: release wrapup-and-checksum check-git-clean sign clean
|
||||||
|
|
||||||
ensure-release-toolchain:
|
release: clean
|
||||||
# ensure the toolchain is actually the one we expect
|
# no cross-platform support for target test
|
||||||
test $(RELEASE_GOVERSION) = "$$($(GO_ENV_VARS) $(GO) env GOVERSION)"
|
$(MAKE) test-go
|
||||||
|
|
||||||
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="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="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="zrepl-bin"
|
||||||
$(MAKE) _run_make_foreach_target_tuple RUN_MAKE_FOREACH_TARGET_TUPLE_ARG="test-platform-bin"
|
$(MAKE) _run_make_foreach_target_tuple RUN_MAKE_FOREACH_TARGET_TUPLE_ARG="test-platform-bin"
|
||||||
$(MAKE) noarch
|
$(MAKE) noarch
|
||||||
|
|
||||||
release-docker: $(ARTIFACTDIR) release-docker-mkcachemount
|
release-docker: $(ARTIFACTDIR)
|
||||||
sed 's/FROM.*!SUBSTITUTED_BY_MAKEFILE/FROM $(RELEASE_DOCKER_BASEIMAGE)/' build/build.Dockerfile > $(ARTIFACTDIR)/build.Dockerfile
|
sed 's/FROM.*!SUBSTITUTED_BY_MAKEFILE/FROM $(RELEASE_DOCKER_BASEIMAGE)/' build.Dockerfile > artifacts/release-docker.Dockerfile
|
||||||
docker build -t zrepl_release --pull -f $(ARTIFACTDIR)/build.Dockerfile .
|
docker build -t zrepl_release --pull -f artifacts/release-docker.Dockerfile .
|
||||||
docker run --rm -i \
|
docker run --rm -i -v $(CURDIR):/src -u $$(id -u):$$(id -g) \
|
||||||
$(_RELEASE_DOCKER_CACHEMOUNT) \
|
|
||||||
-v $(CURDIR):/src -u $$(id -u):$$(id -g) \
|
|
||||||
zrepl_release \
|
zrepl_release \
|
||||||
make release \
|
make release \
|
||||||
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
|
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
|
||||||
ZREPL_VERSION=$(ZREPL_VERSION) ZREPL_PACKAGE_RELEASE=$(ZREPL_PACKAGE_RELEASE) \
|
ZREPL_VERSION=$(ZREPL_VERSION) ZREPL_PACKAGE_RELEASE=$(ZREPL_PACKAGE_RELEASE)
|
||||||
RELEASE_GOVERSION=$(RELEASE_GOVERSION)
|
|
||||||
|
|
||||||
debs-docker:
|
debs-docker:
|
||||||
$(MAKE) _debs_or_rpms_docker _DEB_OR_RPM=deb
|
$(MAKE) _debs_or_rpms_docker _DEB_OR_RPM=deb
|
||||||
@@ -176,14 +162,14 @@ wrapup-and-checksum:
|
|||||||
tar --mtime='1970-01-01' --sort=name \
|
tar --mtime='1970-01-01' --sort=name \
|
||||||
--transform 's/$(ARTIFACTDIR)/zrepl-$(_ZREPL_VERSION)-noarch/' \
|
--transform 's/$(ARTIFACTDIR)/zrepl-$(_ZREPL_VERSION)-noarch/' \
|
||||||
--transform 's#dist#zrepl-$(_ZREPL_VERSION)-noarch/dist#' \
|
--transform 's#dist#zrepl-$(_ZREPL_VERSION)-noarch/dist#' \
|
||||||
--transform 's#internal/config/samples#zrepl-$(_ZREPL_VERSION)-noarch/config#' \
|
--transform 's#config/samples#zrepl-$(_ZREPL_VERSION)-noarch/config#' \
|
||||||
-acf $(NOARCH_TARBALL) \
|
-acf $(NOARCH_TARBALL) \
|
||||||
$(ARTIFACTDIR)/docs/html \
|
$(ARTIFACTDIR)/docs/html \
|
||||||
$(ARTIFACTDIR)/bash_completion \
|
$(ARTIFACTDIR)/bash_completion \
|
||||||
$(ARTIFACTDIR)/_zrepl.zsh_completion \
|
$(ARTIFACTDIR)/_zrepl.zsh_completion \
|
||||||
$(ARTIFACTDIR)/go_env.txt \
|
$(ARTIFACTDIR)/go_env.txt \
|
||||||
dist \
|
dist \
|
||||||
internal/config/samples
|
config/samples
|
||||||
rm -rf "$(ARTIFACTDIR)/release"
|
rm -rf "$(ARTIFACTDIR)/release"
|
||||||
mkdir -p "$(ARTIFACTDIR)/release"
|
mkdir -p "$(ARTIFACTDIR)/release"
|
||||||
cp -l $(ARTIFACTDIR)/zrepl* \
|
cp -l $(ARTIFACTDIR)/zrepl* \
|
||||||
@@ -241,10 +227,10 @@ _run_make_foreach_target_tuple:
|
|||||||
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=illumos GOARCH=amd64
|
$(MAKE) $(RUN_MAKE_FOREACH_TARGET_TUPLE_ARG) GOOS=illumos GOARCH=amd64
|
||||||
|
|
||||||
##################### REGULAR TARGETS #####################
|
##################### REGULAR TARGETS #####################
|
||||||
.PHONY: lint test-go test-platform cover-merge cover-html vet zrepl-bin test-platform-bin
|
.PHONY: lint test-go test-platform cover-merge cover-html vet zrepl-bin test-platform-bin generate-platform-test-list
|
||||||
|
|
||||||
lint: build/install
|
lint:
|
||||||
$(GO_ENV_VARS) build/install/gobin/golangci-lint run ./...
|
$(GO_ENV_VARS) $(GOLANGCI_LINT) run ./...
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
$(GO_ENV_VARS) $(GO) vet $(GO_BUILDFLAGS) ./...
|
$(GO_ENV_VARS) $(GO) vet $(GO_BUILDFLAGS) ./...
|
||||||
@@ -265,6 +251,9 @@ endif
|
|||||||
zrepl-bin:
|
zrepl-bin:
|
||||||
$(GO_BUILD) -o "$(ARTIFACTDIR)/zrepl-$(ZREPL_TARGET_TUPLE)"
|
$(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_PATH := $(ARTIFACTDIR)/platformtest-cover-$(ZREPL_TARGET_TUPLE)
|
||||||
cover-platform-bin:
|
cover-platform-bin:
|
||||||
$(GO_ENV_VARS) $(GO) test $(GO_BUILDFLAGS) \
|
$(GO_ENV_VARS) $(GO) test $(GO_BUILDFLAGS) \
|
||||||
@@ -281,7 +270,7 @@ cover-platform:
|
|||||||
|
|
||||||
TEST_PLATFORM_BIN_PATH := $(ARTIFACTDIR)/platformtest-$(ZREPL_TARGET_TUPLE)
|
TEST_PLATFORM_BIN_PATH := $(ARTIFACTDIR)/platformtest-$(ZREPL_TARGET_TUPLE)
|
||||||
test-platform-bin:
|
test-platform-bin:
|
||||||
$(GO_BUILD) -o "$(TEST_PLATFORM_BIN_PATH)" ./internal/platformtest/harness
|
$(GO_BUILD) -o "$(TEST_PLATFORM_BIN_PATH)" ./platformtest/harness
|
||||||
test-platform:
|
test-platform:
|
||||||
export _TEST_PLATFORM_CMD="\"$(TEST_PLATFORM_BIN_PATH)\""; \
|
export _TEST_PLATFORM_CMD="\"$(TEST_PLATFORM_BIN_PATH)\""; \
|
||||||
$(MAKE) _test-or-cover-platform-impl
|
$(MAKE) _test-or-cover-platform-impl
|
||||||
@@ -298,7 +287,7 @@ ifndef _TEST_PLATFORM_CMD
|
|||||||
endif
|
endif
|
||||||
rm -f "$(ZREPL_PLATFORMTEST_ZFS_LOG)"
|
rm -f "$(ZREPL_PLATFORMTEST_ZFS_LOG)"
|
||||||
rm -f "$(ARTIFACTDIR)/platformtest.cover"
|
rm -f "$(ARTIFACTDIR)/platformtest.cover"
|
||||||
internal/platformtest/logmockzfs/logzfsenv "$(ZREPL_PLATFORMTEST_ZFS_LOG)" `which zfs` \
|
platformtest/logmockzfs/logzfsenv "$(ZREPL_PLATFORMTEST_ZFS_LOG)" `which zfs` \
|
||||||
$(_TEST_PLATFORM_CMD) \
|
$(_TEST_PLATFORM_CMD) \
|
||||||
-poolname "$(ZREPL_PLATFORMTEST_POOLNAME)" \
|
-poolname "$(ZREPL_PLATFORMTEST_POOLNAME)" \
|
||||||
-imagepath "$(ZREPL_PLATFORMTEST_IMAGEPATH)" \
|
-imagepath "$(ZREPL_PLATFORMTEST_IMAGEPATH)" \
|
||||||
@@ -320,34 +309,23 @@ cover-full:
|
|||||||
|
|
||||||
##################### DEV TARGETS #####################
|
##################### DEV TARGETS #####################
|
||||||
# not part of the build, must do that manually
|
# not part of the build, must do that manually
|
||||||
.PHONY: generate format
|
.PHONY: generate formatcheck format
|
||||||
|
|
||||||
build/install:
|
generate: generate-platform-test-list
|
||||||
rm -rf build/install.tmp
|
protoc -I=replication/logic/pdu --go_out=replication/logic/pdu --go-grpc_out=replication/logic/pdu replication/logic/pdu/pdu.proto
|
||||||
mkdir build/install.tmp
|
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 ./...
|
||||||
-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'
|
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'
|
||||||
|
|
||||||
format: build/install
|
formatcheck:
|
||||||
@ 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')
|
@# 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))
|
||||||
|
|
||||||
##################### NOARCH #####################
|
##################### NOARCH #####################
|
||||||
.PHONY: noarch $(ARTIFACTDIR)/bash_completion $(ARTIFACTDIR)/_zrepl.zsh_completion $(ARTIFACTDIR)/go_env.txt docs docs-clean
|
.PHONY: noarch $(ARTIFACTDIR)/bash_completion $(ARTIFACTDIR)/_zrepl.zsh_completion $(ARTIFACTDIR)/go_env.txt docs docs-clean
|
||||||
|
|||||||
@@ -26,40 +26,24 @@ zrepl is a one-stop ZFS backup & replication solution.
|
|||||||
If so, think of an expressive configuration example.
|
If so, think of an expressive configuration example.
|
||||||
2. Think of at least one use case that generalizes from your concrete application.
|
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.
|
3. Open an issue on GitHub with example conf & use case attached.
|
||||||
4. **Optional**: [Contact Christian Schwarz](https://cschwarz.com) for contract work.
|
4. **Optional**: [Post a bounty](https://www.bountysource.com/teams/zrepl) on the issue, or [contact Christian Schwarz](https://cschwarz.com) for contract work.
|
||||||
|
|
||||||
The above does not apply if you already implemented everything.
|
The above does not apply if you already implemented everything.
|
||||||
Check out the *Coding Workflow* section below for details.
|
Check out the *Coding Workflow* section below for details.
|
||||||
|
|
||||||
## Development
|
## 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
|
||||||
|
|
||||||
zrepl is written in [Go](https://golang.org) and uses [Go modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
|
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.
|
The documentation is written in [ReStructured Text](http://docutils.sourceforge.net/rst.html) using the [Sphinx](https://www.sphinx-doc.org) framework.
|
||||||
|
|
||||||
### Building
|
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).
|
||||||
#### Go Code
|
If you just want to install the Go dependencies, run `./lazy.sh godep`.
|
||||||
|
|
||||||
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`).
|
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`.
|
Platform tests run on their own pool with the name `zreplplatformtest`, which is created using the file vdev in `/tmp`.
|
||||||
@@ -67,28 +51,33 @@ 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`.
|
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`.
|
An HTML report can be generated using `make cover-html`.
|
||||||
|
|
||||||
### Circle CI
|
**Code generation** is triggered by `make generate`. Generated code is committed to the source tree.
|
||||||
|
|
||||||
We use CircleCI for automated build & test pre- and post-merge.
|
### Build & Release Process
|
||||||
|
|
||||||
|
**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:
|
There are two workflows:
|
||||||
|
|
||||||
* `ci` runs for every commit / branch / tag pushed to GitHub.
|
* `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 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.
|
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
|
* `release` runs
|
||||||
* on manual triggers through the CircleCI API (in order to produce a release)
|
* on manual triggers through the CircleCI API (in order to produce a release)
|
||||||
* periodically on `master`
|
* periodically on `master`
|
||||||
|
Artifacts are published to minio.cschwarz.com (see GitHub Commit Status).
|
||||||
|
|
||||||
Artifacts are stored in CircleCI.
|
**Releases** are issued via Git tags + GitHub Releases feature.
|
||||||
|
|
||||||
### 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:
|
The procedure to issue a release is as follows:
|
||||||
* Issue the source release:
|
* Issue the source release:
|
||||||
* Git tag the release on the `master` branch.
|
* Git tag the release on the `master` branch.
|
||||||
@@ -99,34 +88,14 @@ The procedure to issue a release is as follows:
|
|||||||
* Download the artifacts to the release manager's machine.
|
* 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.
|
* Create a GitHub release, edit the changelog, upload all the release artifacts, including .rpm and .deb files.
|
||||||
* Issue the GitHub release.
|
* Issue the GitHub release.
|
||||||
* Add the .rpm and .deb files to the official zrepl repos.
|
* Add the .rpm and .deb files to the official zrepl repos, publish those.
|
||||||
* Code for management of these repos: https://github.com/zrepl/package-repo-ops (private repo at this time)
|
|
||||||
|
|
||||||
#### Patch releases, Go toolchain updates, APT/RPM Package rebuilds
|
**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.
|
||||||
|
|
||||||
`vMAJOR.MINOR.0` is typically a tagged commit on `master`, because development velocity isn't high
|
### Additional Notes to Distro Package Maintainers
|
||||||
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.
|
* 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 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.
|
* Ship a service manager file and _please_ try to upstream it to this repository.
|
||||||
@@ -136,3 +105,31 @@ Control via the `ZREPL_PACKAGE_RELEASE` Makefile variable, see `origin/releases/
|
|||||||
This is how `zrepl version` knows what version number to show.
|
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.
|
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.
|
* 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.
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
FROM !SUBSTITUTED_BY_MAKEFILE
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
python3-pip \
|
||||||
|
python3-venv \
|
||||||
|
unzip \
|
||||||
|
gawk
|
||||||
|
|
||||||
|
ADD build.installprotoc.bash ./
|
||||||
|
RUN bash build.installprotoc.bash
|
||||||
|
|
||||||
|
# setup venv
|
||||||
|
ENV VIRTUAL_ENV=/opt/venv
|
||||||
|
RUN python3 -m venv $VIRTUAL_ENV
|
||||||
|
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/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"
|
||||||
@@ -1 +0,0 @@
|
|||||||
install/
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#!/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"
|
|
||||||
+30
-184
@@ -1,194 +1,40 @@
|
|||||||
module github.com/zrepl/zrepl/build
|
module github.com/zrepl/zrepl/build
|
||||||
|
|
||||||
go 1.22.7
|
go 1.12
|
||||||
toolchain go1.23.1
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alvaroloes/enumer v1.1.2
|
github.com/alvaroloes/enumer v1.1.1
|
||||||
github.com/golangci/golangci-lint v1.60.3
|
github.com/breml/bidichk v0.2.6 // indirect
|
||||||
github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad
|
github.com/breml/errchkjson v0.3.5 // indirect
|
||||||
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/chavacava/garif v0.1.0 // indirect
|
||||||
github.com/ckaznocha/intrange v0.1.2 // indirect
|
github.com/daixiang0/gci v0.11.1 // indirect
|
||||||
github.com/curioswitch/go-reassign v0.2.0 // indirect
|
github.com/golangci/golangci-lint v1.54.2
|
||||||
github.com/daixiang0/gci v0.13.5 // indirect
|
github.com/golangci/revgrep v0.5.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/denis-tingaikin/go-header v0.5.0 // indirect
|
github.com/jgautheron/goconst v1.6.0 // indirect
|
||||||
github.com/ettle/strcase v0.2.0 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/fatih/structtag v1.2.0 // indirect
|
github.com/mgechev/revive v1.3.3 // indirect
|
||||||
github.com/firefart/nonamedreturns v1.0.5 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/polyfloyd/go-errorlint v1.4.5 // indirect
|
||||||
github.com/fzipp/gocyclo v0.6.0 // indirect
|
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||||
github.com/ghostiam/protogetter v0.3.6 // indirect
|
github.com/prometheus/common v0.44.0 // indirect
|
||||||
github.com/go-critic/go-critic v0.11.4 // indirect
|
github.com/prometheus/procfs v0.11.1 // indirect
|
||||||
github.com/go-toolsmith/astcast v1.1.0 // indirect
|
github.com/rivo/uniseg v0.4.4 // 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/ryanrolds/sqlclosecheck v0.5.1 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
github.com/spf13/viper v1.16.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/stretchr/objx v0.5.1 // 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/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/tdakkota/asciicheck v0.2.0 // indirect
|
github.com/tetafro/godot v1.4.15 // indirect
|
||||||
github.com/tetafro/godot v1.4.17 // indirect
|
github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad
|
||||||
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/xen0n/gosmopolitan v1.2.2 // indirect
|
||||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
gitlab.com/bosi/decorder v0.4.1 // 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/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.25.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/exp/typeparams v0.0.0-20240904232852-e7e105dedf7e // indirect
|
golang.org/x/exp/typeparams v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/tools v0.13.0
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
|
||||||
golang.org/x/sys v0.25.0 // indirect
|
google.golang.org/protobuf v1.31.0
|
||||||
golang.org/x/text v0.18.0 // indirect
|
mvdan.cc/unparam v0.0.0-20230815095028-f7c6fb1088f0 // 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
|
|
||||||
)
|
)
|
||||||
|
|||||||
+2251
-266
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
|||||||
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?
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/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 '{}'
|
|
||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging/trace"
|
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rootArgs struct {
|
var rootArgs struct {
|
||||||
@@ -11,11 +11,11 @@ import (
|
|||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"github.com/zrepl/yaml-config"
|
"github.com/zrepl/yaml-config"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
"github.com/zrepl/zrepl/daemon/job"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
"github.com/zrepl/zrepl/daemon/logging"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configcheckArgs struct {
|
var configcheckArgs struct {
|
||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
"github.com/zrepl/zrepl/daemon/job"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import "github.com/zrepl/zrepl/internal/cli"
|
import "github.com/zrepl/zrepl/cli"
|
||||||
|
|
||||||
var PprofCmd = &cli.Subcommand{
|
var PprofCmd = &cli.Subcommand{
|
||||||
Use: "pprof",
|
Use: "pprof",
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pprofActivityTraceCmd = &cli.Subcommand{
|
var pprofActivityTraceCmd = &cli.Subcommand{
|
||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon"
|
"github.com/zrepl/zrepl/daemon"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pprofListenCmd struct {
|
var pprofListenCmd struct {
|
||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon"
|
"github.com/zrepl/zrepl/daemon"
|
||||||
)
|
)
|
||||||
|
|
||||||
var SignalCmd = &cli.Subcommand{
|
var SignalCmd = &cli.Subcommand{
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon"
|
"github.com/zrepl/zrepl/daemon"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@@ -9,11 +9,11 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/client/status/client"
|
"github.com/zrepl/zrepl/client/status/client"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon"
|
"github.com/zrepl/zrepl/daemon"
|
||||||
"github.com/zrepl/zrepl/internal/util/choices"
|
"github.com/zrepl/zrepl/util/choices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel"
|
"github.com/zrepl/zrepl/client/status/viewmodel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dump(c Client, job string) error {
|
func dump(c Client, job string) error {
|
||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/rivo/tview"
|
tview "gitlab.com/tslocum/cview"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel"
|
"github.com/zrepl/zrepl/client/status/viewmodel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func interactive(c Client, flag statusFlags) error {
|
func interactive(c Client, flag statusFlags) error {
|
||||||
@@ -29,6 +29,7 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
jobMenuRoot.SetSelectable(true)
|
jobMenuRoot.SetSelectable(true)
|
||||||
jobMenu.SetRoot(jobMenuRoot)
|
jobMenu.SetRoot(jobMenuRoot)
|
||||||
jobMenu.SetCurrentNode(jobMenuRoot)
|
jobMenu.SetCurrentNode(jobMenuRoot)
|
||||||
|
jobMenu.SetSelectedTextColor(tcell.ColorGreen)
|
||||||
jobTextDetail := tview.NewTextView()
|
jobTextDetail := tview.NewTextView()
|
||||||
jobTextDetail.SetWrap(false)
|
jobTextDetail.SetWrap(false)
|
||||||
|
|
||||||
@@ -109,8 +110,10 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
}
|
}
|
||||||
app.SetRoot(toolbarSplit, true)
|
app.SetRoot(toolbarSplit, true)
|
||||||
app.SetFocus(preModalFocus)
|
app.SetFocus(preModalFocus)
|
||||||
|
app.Draw()
|
||||||
})
|
})
|
||||||
app.SetRoot(m, true)
|
app.SetRoot(m, true)
|
||||||
|
app.Draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
app.SetRoot(toolbarSplit, true)
|
app.SetRoot(toolbarSplit, true)
|
||||||
@@ -167,14 +170,12 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
redrawJobsList = true
|
redrawJobsList = true
|
||||||
}
|
}
|
||||||
if redrawJobsList {
|
if redrawJobsList {
|
||||||
selectedTextStyle := tcell.StyleDefault.Bold(true)
|
|
||||||
selectedJobN = nil
|
selectedJobN = nil
|
||||||
children := make([]*tview.TreeNode, len(jobs))
|
children := make([]*tview.TreeNode, len(jobs))
|
||||||
for i := range jobs {
|
for i := range jobs {
|
||||||
jobN := tview.NewTreeNode(jobs[i].JobTreeTitle())
|
jobN := tview.NewTreeNode(jobs[i].JobTreeTitle())
|
||||||
jobN.SetReference(jobs[i])
|
jobN.SetReference(jobs[i])
|
||||||
jobN.SetSelectable(true)
|
jobN.SetSelectable(true)
|
||||||
jobN.SetSelectedTextStyle(selectedTextStyle)
|
|
||||||
children[i] = jobN
|
children[i] = jobN
|
||||||
jobN.SetSelectedFunc(func() {
|
jobN.SetSelectedFunc(func() {
|
||||||
viewmodelupdate(func(p *viewmodel.Params) {
|
viewmodelupdate(func(p *viewmodel.Params) {
|
||||||
@@ -186,7 +187,6 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
jobMenuRoot.SetChildren(children)
|
jobMenuRoot.SetChildren(children)
|
||||||
jobMenuRoot.SetSelectedTextStyle(selectedTextStyle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if selectedJobN != nil && jobMenu.GetCurrentNode() != selectedJobN {
|
if selectedJobN != nil && jobMenu.GetCurrentNode() != selectedJobN {
|
||||||
@@ -207,6 +207,9 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
bottombar.ResizeItem(bottombarDateView, len(bottombardatestring), 0)
|
bottombar.ResizeItem(bottombarDateView, len(bottombardatestring), 0)
|
||||||
|
|
||||||
bottomBarStatus.SetText(m.BottomBarStatus())
|
bottomBarStatus.SetText(m.BottomBarStatus())
|
||||||
|
|
||||||
|
app.Draw()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -249,7 +252,6 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
|
|
||||||
app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
||||||
if e.Key() == tcell.KeyTab {
|
if e.Key() == tcell.KeyTab {
|
||||||
// TODO: only if there's no modal showing (long-time bug in zrepl status)
|
|
||||||
tabbableCycle()
|
tabbableCycle()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -282,8 +284,9 @@ func interactive(c Client, flag statusFlags) error {
|
|||||||
signals := []string{"wakeup", "reset"}
|
signals := []string{"wakeup", "reset"}
|
||||||
clientFuncs := []func(job string) error{c.SignalWakeup, c.SignalReset}
|
clientFuncs := []func(job string) error{c.SignalWakeup, c.SignalReset}
|
||||||
sigMod := tview.NewModal()
|
sigMod := tview.NewModal()
|
||||||
|
sigMod.SetBackgroundColor(tcell.ColorDefault)
|
||||||
sigMod.SetBorder(true)
|
sigMod.SetBorder(true)
|
||||||
sigMod.SetButtonActivatedStyle(tcell.StyleDefault.Bold(true).Reverse(true))
|
sigMod.GetForm().SetButtonTextColorFocused(tcell.ColorGreen)
|
||||||
sigMod.AddButtons(signals)
|
sigMod.AddButtons(signals)
|
||||||
sigMod.SetText(fmt.Sprintf("Send a signal to job %q", job.Name()))
|
sigMod.SetText(fmt.Sprintf("Send a signal to job %q", job.Name()))
|
||||||
showModal(sigMod, func(idx int, _ string) {
|
showModal(sigMod, func(idx int, _ string) {
|
||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rivo/tview"
|
tview "gitlab.com/tslocum/cview"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel"
|
"github.com/zrepl/zrepl/client/status/viewmodel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func legacy(c Client, flag statusFlags) error {
|
func legacy(c Client, flag statusFlags) error {
|
||||||
@@ -28,7 +28,7 @@ func legacy(c Client, flag statusFlags) error {
|
|||||||
textView := tview.NewTextView()
|
textView := tview.NewTextView()
|
||||||
textView.SetWrap(true)
|
textView.SetWrap(true)
|
||||||
textView.SetScrollable(true) // so that it allows us to set scroll position
|
textView.SetScrollable(true) // so that it allows us to set scroll position
|
||||||
// textView.SetScrollBarVisibility(tview.ScrollBarNever)
|
textView.SetScrollBarVisibility(tview.ScrollBarNever)
|
||||||
|
|
||||||
app.SetRoot(textView, true)
|
app.SetRoot(textView, true)
|
||||||
|
|
||||||
@@ -10,12 +10,12 @@ import (
|
|||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
yaml "github.com/zrepl/yaml-config"
|
yaml "github.com/zrepl/yaml-config"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/client/status/viewmodel/stringbuilder"
|
"github.com/zrepl/zrepl/client/status/viewmodel/stringbuilder"
|
||||||
"github.com/zrepl/zrepl/internal/daemon"
|
"github.com/zrepl/zrepl/daemon"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
"github.com/zrepl/zrepl/daemon/job"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/pruner"
|
"github.com/zrepl/zrepl/daemon/pruner"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/snapper"
|
"github.com/zrepl/zrepl/daemon/snapper"
|
||||||
"github.com/zrepl/zrepl/internal/replication/report"
|
"github.com/zrepl/zrepl/replication/report"
|
||||||
)
|
)
|
||||||
|
|
||||||
type M struct {
|
type M struct {
|
||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
|
|
||||||
"github.com/problame/go-netssh"
|
"github.com/problame/go-netssh"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var TestCmd = &cli.Subcommand{
|
var TestCmd = &cli.Subcommand{
|
||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon"
|
"github.com/zrepl/zrepl/daemon"
|
||||||
"github.com/zrepl/zrepl/internal/version"
|
"github.com/zrepl/zrepl/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var versionArgs struct {
|
var versionArgs struct {
|
||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import "github.com/zrepl/zrepl/internal/cli"
|
import "github.com/zrepl/zrepl/cli"
|
||||||
|
|
||||||
var zabsCmdCreate = &cli.Subcommand{
|
var zabsCmdCreate = &cli.Subcommand{
|
||||||
Use: "create",
|
Use: "create",
|
||||||
+3
-3
@@ -7,9 +7,9 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var zabsCreateStepHoldFlags struct {
|
var zabsCreateStepHoldFlags struct {
|
||||||
@@ -11,9 +11,9 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/util/chainlock"
|
"github.com/zrepl/zrepl/util/chainlock"
|
||||||
)
|
)
|
||||||
|
|
||||||
var zabsListFlags struct {
|
var zabsListFlags struct {
|
||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
)
|
)
|
||||||
|
|
||||||
// shared between release-all and release-step
|
// shared between release-all and release-step
|
||||||
@@ -2,16 +2,18 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
"github.com/zrepl/yaml-config"
|
"github.com/zrepl/yaml-config"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/util/datasizeunit"
|
"github.com/zrepl/zrepl/util/datasizeunit"
|
||||||
zfsprop "github.com/zrepl/zrepl/internal/zfs/property"
|
zfsprop "github.com/zrepl/zrepl/zfs/property"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ParseFlags uint
|
type ParseFlags uint
|
||||||
@@ -22,7 +24,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Jobs []JobEnum `yaml:"jobs,optional"`
|
Jobs []JobEnum `yaml:"jobs"`
|
||||||
Global *Global `yaml:"global,optional,fromdefaults"`
|
Global *Global `yaml:"global,optional,fromdefaults"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +121,7 @@ type BandwidthLimit struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Replication struct {
|
type Replication struct {
|
||||||
|
Triggers []*ReplicationTriggerEnum
|
||||||
Protection *ReplicationOptionsProtection `yaml:"protection,optional,fromdefaults"`
|
Protection *ReplicationOptionsProtection `yaml:"protection,optional,fromdefaults"`
|
||||||
Concurrency *ReplicationOptionsConcurrency `yaml:"concurrency,optional,fromdefaults"`
|
Concurrency *ReplicationOptionsConcurrency `yaml:"concurrency,optional,fromdefaults"`
|
||||||
}
|
}
|
||||||
@@ -133,6 +136,32 @@ type ReplicationOptionsConcurrency struct {
|
|||||||
SizeEstimates int `yaml:"size_estimates,optional,default=4"`
|
SizeEstimates int `yaml:"size_estimates,optional,default=4"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ReplicationTriggerEnum struct {
|
||||||
|
Ret interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ReplicationTriggerEnum) UnmarshalYAML(u func(interface{}, bool) error) (err error) {
|
||||||
|
t.Ret, err = enumUnmarshal(u, map[string]interface{}{
|
||||||
|
"manual": &ReplicationTriggerManual{},
|
||||||
|
"periodic": &ReplicationTriggerPeriodic{},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReplicationTriggerManual struct {
|
||||||
|
Type string `yaml:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReplicationTriggerPeriodic struct {
|
||||||
|
Type string `yaml:"type"`
|
||||||
|
Interval *PositiveDuration `yaml:"interval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReplicationTriggerCron struct {
|
||||||
|
Type string `yaml:"type"`
|
||||||
|
Cron CronSpec `yaml:"cron"`
|
||||||
|
}
|
||||||
|
|
||||||
type PropertyRecvOptions struct {
|
type PropertyRecvOptions struct {
|
||||||
Inherit []zfsprop.Property `yaml:"inherit,optional"`
|
Inherit []zfsprop.Property `yaml:"inherit,optional"`
|
||||||
Override map[zfsprop.Property]string `yaml:"override,optional"`
|
Override map[zfsprop.Property]string `yaml:"override,optional"`
|
||||||
@@ -155,7 +184,6 @@ func (j *PushJob) GetSendOptions() *SendOptions { return j.Send }
|
|||||||
type PullJob struct {
|
type PullJob struct {
|
||||||
ActiveJob `yaml:",inline"`
|
ActiveJob `yaml:",inline"`
|
||||||
RootFS string `yaml:"root_fs"`
|
RootFS string `yaml:"root_fs"`
|
||||||
Interval PositiveDurationOrManual `yaml:"interval"`
|
|
||||||
Recv *RecvOptions `yaml:"recv,fromdefaults,optional"`
|
Recv *RecvOptions `yaml:"recv,fromdefaults,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,16 +246,11 @@ type SnapshottingEnum struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SnapshottingPeriodic struct {
|
type SnapshottingPeriodic struct {
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
Prefix string `yaml:"prefix"`
|
Prefix string `yaml:"prefix"`
|
||||||
Interval *PositiveDuration `yaml:"interval"`
|
Interval *PositiveDuration `yaml:"interval"`
|
||||||
Hooks HookList `yaml:"hooks,optional"`
|
Hooks HookList `yaml:"hooks,optional"`
|
||||||
TimestampFormattingSpec `yaml:",inline"`
|
TimestampFormat string `yaml:"timestamp_format,optional,default=dense"`
|
||||||
}
|
|
||||||
|
|
||||||
type TimestampFormattingSpec struct {
|
|
||||||
TimestampFormat string `yaml:"timestamp_format,optional,default=dense"`
|
|
||||||
TimestampLocation string `yaml:"timestamp_location,optional,default=UTC"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CronSpec struct {
|
type CronSpec struct {
|
||||||
@@ -256,11 +279,11 @@ func (s *CronSpec) UnmarshalYAML(unmarshal func(v interface{}, not_strict bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SnapshottingCron struct {
|
type SnapshottingCron struct {
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
Prefix string `yaml:"prefix"`
|
Prefix string `yaml:"prefix"`
|
||||||
Cron CronSpec `yaml:"cron"`
|
Cron CronSpec `yaml:"cron"`
|
||||||
Hooks HookList `yaml:"hooks,optional"`
|
Hooks HookList `yaml:"hooks,optional"`
|
||||||
TimestampFormattingSpec `yaml:",inline"`
|
TimestampFormat string `yaml:"timestamp_format,optional,default=dense"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SnapshottingManual struct {
|
type SnapshottingManual struct {
|
||||||
@@ -302,6 +325,18 @@ type Global struct {
|
|||||||
Serve *GlobalServe `yaml:"serve,optional,fromdefaults"`
|
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 {
|
type ConnectEnum struct {
|
||||||
Ret interface{}
|
Ret interface{}
|
||||||
}
|
}
|
||||||
@@ -675,7 +710,7 @@ func ParseConfig(path string) (i *Config, err error) {
|
|||||||
|
|
||||||
var bytes []byte
|
var bytes []byte
|
||||||
|
|
||||||
if bytes, err = os.ReadFile(path); err != nil {
|
if bytes, err = ioutil.ReadFile(path); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,16 +722,8 @@ func ParseConfigBytes(bytes []byte) (*Config, error) {
|
|||||||
if err := yaml.UnmarshalStrict(bytes, &c); err != nil {
|
if err := yaml.UnmarshalStrict(bytes, &c); err != nil {
|
||||||
return nil, err
|
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 {
|
if c == nil {
|
||||||
panic("the fallback to deserialize from `{}` should work")
|
return nil, fmt.Errorf("config is empty or only consists of comments")
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,16 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"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) {
|
func TestJobsOnlyWorks(t *testing.T) {
|
||||||
testValidConfig(t, `
|
testValidConfig(t, `
|
||||||
jobs:
|
jobs:
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
zfsprop "github.com/zrepl/zrepl/internal/zfs/property"
|
zfsprop "github.com/zrepl/zrepl/zfs/property"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRecvOptions(t *testing.T) {
|
func TestRecvOptions(t *testing.T) {
|
||||||
@@ -163,8 +163,7 @@ jobs:
|
|||||||
assert.Equal(t, "periodic", snp.Type)
|
assert.Equal(t, "periodic", snp.Type)
|
||||||
assert.Equal(t, 10*time.Minute, snp.Interval.Duration())
|
assert.Equal(t, 10*time.Minute, snp.Interval.Duration())
|
||||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||||
assert.Equal(t, snp.TimestampFormat, "dense")
|
assert.Equal(t, "dense", snp.TimestampFormat) // default was set correctly
|
||||||
assert.Equal(t, snp.TimestampLocation, "UTC")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("cron", func(t *testing.T) {
|
t.Run("cron", func(t *testing.T) {
|
||||||
@@ -172,7 +171,6 @@ jobs:
|
|||||||
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingCron)
|
snp := c.Jobs[0].Ret.(*PushJob).Snapshotting.Ret.(*SnapshottingCron)
|
||||||
assert.Equal(t, "cron", snp.Type)
|
assert.Equal(t, "cron", snp.Type)
|
||||||
assert.Equal(t, "zrepl_", snp.Prefix)
|
assert.Equal(t, "zrepl_", snp.Prefix)
|
||||||
assert.Equal(t, snp.TimestampFormat, "dense")
|
assert.Equal(t, "dense", snp.TimestampFormat) // default was set correctly
|
||||||
assert.Equal(t, snp.TimestampLocation, "UTC")
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -22,8 +22,6 @@ func TestSampleConfigsAreParsedWithoutErrors(t *testing.T) {
|
|||||||
t.Errorf("glob failed: %+v", err)
|
t.Errorf("glob failed: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paths = append(paths, "../../packaging/systemd-default-zrepl.yml")
|
|
||||||
|
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
|
|
||||||
if path.Ext(p) != ".yml" {
|
if path.Ext(p) != ".yml" {
|
||||||
@@ -140,18 +138,3 @@ 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,14 +14,14 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
"github.com/zrepl/zrepl/daemon/job"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/nethelpers"
|
"github.com/zrepl/zrepl/daemon/nethelpers"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
"github.com/zrepl/zrepl/internal/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
"github.com/zrepl/zrepl/internal/version"
|
"github.com/zrepl/zrepl/version"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
"github.com/zrepl/zrepl/internal/zfs/zfscmd"
|
"github.com/zrepl/zrepl/zfs/zfscmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type controlJob struct {
|
type controlJob struct {
|
||||||
@@ -3,6 +3,7 @@ package daemon
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -13,18 +14,18 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging/trace"
|
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job"
|
"github.com/zrepl/zrepl/daemon/job"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job/reset"
|
"github.com/zrepl/zrepl/daemon/job/reset"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job/wakeup"
|
"github.com/zrepl/zrepl/daemon/job/wakeup"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
"github.com/zrepl/zrepl/daemon/logging"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
"github.com/zrepl/zrepl/internal/version"
|
"github.com/zrepl/zrepl/version"
|
||||||
"github.com/zrepl/zrepl/internal/zfs/zfscmd"
|
"github.com/zrepl/zrepl/zfs/zfscmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx context.Context, conf *config.Config) error {
|
func Run(ctx context.Context, conf *config.Config) error {
|
||||||
@@ -38,6 +39,12 @@ func Run(ctx context.Context, conf *config.Config) error {
|
|||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// The math/rand package is used presently for generating trace IDs, we
|
||||||
|
// seed it with the current time and pid so that the IDs are mostly
|
||||||
|
// unique.
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
rand.Seed(int64(os.Getpid()))
|
||||||
|
|
||||||
outlets, err := logging.OutletsFromConfig(*conf.Global.Logging)
|
outlets, err := logging.OutletsFromConfig(*conf.Global.Logging)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "cannot build logging from config")
|
return errors.Wrap(err, "cannot build logging from config")
|
||||||
@@ -69,7 +76,7 @@ func Run(ctx context.Context, conf *config.Config) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs := newJobs(prometheus.DefaultRegisterer)
|
jobs := newJobs()
|
||||||
|
|
||||||
// start control socket
|
// start control socket
|
||||||
controlJob, err := newControlJob(conf.Global.Control.SockPath, jobs)
|
controlJob, err := newControlJob(conf.Global.Control.SockPath, jobs)
|
||||||
@@ -123,8 +130,6 @@ func Run(ctx context.Context, conf *config.Config) error {
|
|||||||
type jobs struct {
|
type jobs struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
metrics metrics
|
|
||||||
|
|
||||||
// m protects all fields below it
|
// m protects all fields below it
|
||||||
m sync.RWMutex
|
m sync.RWMutex
|
||||||
wakeups map[string]wakeup.Func // by Job.Name
|
wakeups map[string]wakeup.Func // by Job.Name
|
||||||
@@ -132,32 +137,12 @@ type jobs struct {
|
|||||||
jobs map[string]job.Job
|
jobs map[string]job.Job
|
||||||
}
|
}
|
||||||
|
|
||||||
type metrics struct {
|
func newJobs() *jobs {
|
||||||
running *prometheus.GaugeVec
|
return &jobs{
|
||||||
}
|
|
||||||
|
|
||||||
func newJobs(registry prometheus.Registerer) *jobs {
|
|
||||||
jobs := &jobs{
|
|
||||||
metrics: metrics{
|
|
||||||
running: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
|
||||||
Namespace: "zrepl",
|
|
||||||
Subsystem: "daemon",
|
|
||||||
Name: "job_up",
|
|
||||||
Help: `Each zrepl-level job starts its life with this metric =1.
|
|
||||||
It reamins =1 until the job leaves its Run() function.
|
|
||||||
The purpose of this metric is primarily for Prometheus to be aware of all job names.
|
|
||||||
The value will only transition to 0 during zrepl daemon shutdown or panics.
|
|
||||||
`,
|
|
||||||
}, []string{"zrepl_job", "internal"}),
|
|
||||||
},
|
|
||||||
wakeups: make(map[string]wakeup.Func),
|
wakeups: make(map[string]wakeup.Func),
|
||||||
resets: make(map[string]reset.Func),
|
resets: make(map[string]reset.Func),
|
||||||
jobs: make(map[string]job.Job),
|
jobs: make(map[string]job.Job),
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.MustRegister(jobs.metrics.running)
|
|
||||||
|
|
||||||
return jobs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *jobs) wait() <-chan struct{} {
|
func (s *jobs) wait() <-chan struct{} {
|
||||||
@@ -264,10 +249,7 @@ func (s *jobs) start(ctx context.Context, j job.Job, internal bool) {
|
|||||||
s.resets[jobName] = resetFunc
|
s.resets[jobName] = resetFunc
|
||||||
|
|
||||||
s.wg.Add(1)
|
s.wg.Add(1)
|
||||||
runningJobsGauge := s.metrics.running.WithLabelValues(jobName, fmt.Sprintf("%v", internal))
|
|
||||||
runningJobsGauge.Inc()
|
|
||||||
go func() {
|
go func() {
|
||||||
defer runningJobsGauge.Dec()
|
|
||||||
defer s.wg.Done()
|
defer s.wg.Done()
|
||||||
job.GetLogger(ctx).Info("starting job")
|
job.GetLogger(ctx).Info("starting job")
|
||||||
defer job.GetLogger(ctx).Info("job exited")
|
defer job.GetLogger(ctx).Info("job exited")
|
||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DatasetMapFilter struct {
|
type DatasetMapFilter struct {
|
||||||
@@ -3,7 +3,7 @@ package filters
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDatasetMapFilter(t *testing.T) {
|
func TestDatasetMapFilter(t *testing.T) {
|
||||||
@@ -3,8 +3,8 @@ package hooks
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type List []Hook
|
type List []Hook
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Re-export type here so that
|
// Re-export type here so that
|
||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
"github.com/zrepl/zrepl/daemon/logging"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
"github.com/zrepl/zrepl/internal/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Logger = logger.Logger
|
type Logger = logger.Logger
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HookJobCallback func(ctx context.Context) error
|
type HookJobCallback func(ctx context.Context) error
|
||||||
@@ -12,11 +12,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
"github.com/zrepl/zrepl/internal/util/circlog"
|
"github.com/zrepl/zrepl/util/circlog"
|
||||||
"github.com/zrepl/zrepl/internal/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HookEnvVar string
|
type HookEnvVar string
|
||||||
+3
-3
@@ -12,9 +12,9 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hook to implement the following recommmendation from MySQL docs
|
// Hook to implement the following recommmendation from MySQL docs
|
||||||
+3
-3
@@ -10,9 +10,9 @@ import (
|
|||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PgChkptHook struct {
|
type PgChkptHook struct {
|
||||||
@@ -11,13 +11,13 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging/trace"
|
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/hooks"
|
"github.com/zrepl/zrepl/daemon/hooks"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
"github.com/zrepl/zrepl/daemon/logging"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type comparisonAssertionFunc func(require.TestingT, interface{}, interface{}, ...interface{})
|
type comparisonAssertionFunc func(require.TestingT, interface{}, interface{}, ...interface{})
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
// Code generated by "enumer -type=StepStatus -trimprefix=Step"; DO NOT EDIT.
|
// Code generated by "enumer -type=StepStatus -trimprefix=Step"; DO NOT EDIT.
|
||||||
|
|
||||||
|
//
|
||||||
package hooks
|
package hooks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,24 +8,26 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/common/log"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging/trace"
|
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||||
"github.com/zrepl/zrepl/internal/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job/reset"
|
"github.com/zrepl/zrepl/daemon/job/reset"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/job/wakeup"
|
"github.com/zrepl/zrepl/daemon/job/trigger"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/pruner"
|
"github.com/zrepl/zrepl/daemon/job/wakeup"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/snapper"
|
"github.com/zrepl/zrepl/daemon/pruner"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/daemon/snapper"
|
||||||
"github.com/zrepl/zrepl/internal/replication"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/replication/driver"
|
"github.com/zrepl/zrepl/replication"
|
||||||
"github.com/zrepl/zrepl/internal/replication/logic"
|
"github.com/zrepl/zrepl/replication/driver"
|
||||||
"github.com/zrepl/zrepl/internal/replication/report"
|
"github.com/zrepl/zrepl/replication/logic"
|
||||||
"github.com/zrepl/zrepl/internal/rpc"
|
"github.com/zrepl/zrepl/replication/report"
|
||||||
"github.com/zrepl/zrepl/internal/transport"
|
"github.com/zrepl/zrepl/rpc"
|
||||||
"github.com/zrepl/zrepl/internal/transport/fromconfig"
|
"github.com/zrepl/zrepl/transport"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/transport/fromconfig"
|
||||||
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActiveSide struct {
|
type ActiveSide struct {
|
||||||
@@ -43,6 +45,8 @@ type ActiveSide struct {
|
|||||||
promReplicationErrors prometheus.Gauge
|
promReplicationErrors prometheus.Gauge
|
||||||
promLastSuccessful prometheus.Gauge
|
promLastSuccessful prometheus.Gauge
|
||||||
|
|
||||||
|
triggers *trigger.Triggers
|
||||||
|
|
||||||
tasksMtx sync.Mutex
|
tasksMtx sync.Mutex
|
||||||
tasks activeSideTasks
|
tasks activeSideTasks
|
||||||
}
|
}
|
||||||
@@ -89,7 +93,7 @@ type activeMode interface {
|
|||||||
SenderReceiver() (logic.Sender, logic.Receiver)
|
SenderReceiver() (logic.Sender, logic.Receiver)
|
||||||
Type() Type
|
Type() Type
|
||||||
PlannerPolicy() logic.PlannerPolicy
|
PlannerPolicy() logic.PlannerPolicy
|
||||||
RunPeriodic(ctx context.Context, wakeUpCommon chan<- struct{})
|
RunPeriodic(ctx context.Context, wakeReplication *trigger.Manual)
|
||||||
SnapperReport() *snapper.Report
|
SnapperReport() *snapper.Report
|
||||||
ResetConnectBackoff()
|
ResetConnectBackoff()
|
||||||
}
|
}
|
||||||
@@ -131,8 +135,8 @@ func (m *modePush) Type() Type { return TypePush }
|
|||||||
|
|
||||||
func (m *modePush) PlannerPolicy() logic.PlannerPolicy { return *m.plannerPolicy }
|
func (m *modePush) PlannerPolicy() logic.PlannerPolicy { return *m.plannerPolicy }
|
||||||
|
|
||||||
func (m *modePush) RunPeriodic(ctx context.Context, wakeUpCommon chan<- struct{}) {
|
func (m *modePush) RunPeriodic(ctx context.Context, trigger *trigger.Manual) {
|
||||||
m.snapper.Run(ctx, wakeUpCommon)
|
m.snapper.Run(ctx, trigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modePush) SnapperReport() *snapper.Report {
|
func (m *modePush) SnapperReport() *snapper.Report {
|
||||||
@@ -220,7 +224,7 @@ func (*modePull) Type() Type { return TypePull }
|
|||||||
|
|
||||||
func (m *modePull) PlannerPolicy() logic.PlannerPolicy { return *m.plannerPolicy }
|
func (m *modePull) PlannerPolicy() logic.PlannerPolicy { return *m.plannerPolicy }
|
||||||
|
|
||||||
func (m *modePull) RunPeriodic(ctx context.Context, wakeUpCommon chan<- struct{}) {
|
func (m *modePull) RunPeriodic(ctx context.Context, wakeReplication *trigger.Manual) {
|
||||||
if m.interval.Manual {
|
if m.interval.Manual {
|
||||||
GetLogger(ctx).Info("manual pull configured, periodic pull disabled")
|
GetLogger(ctx).Info("manual pull configured, periodic pull disabled")
|
||||||
// "waiting for wakeups" is printed in common ActiveSide.do
|
// "waiting for wakeups" is printed in common ActiveSide.do
|
||||||
@@ -231,14 +235,7 @@ func (m *modePull) RunPeriodic(ctx context.Context, wakeUpCommon chan<- struct{}
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
select {
|
wakeReplication.Fire()
|
||||||
case wakeUpCommon <- struct{}{}:
|
|
||||||
default:
|
|
||||||
GetLogger(ctx).
|
|
||||||
WithField("pull_interval", m.interval).
|
|
||||||
Warn("pull job took longer than pull interval")
|
|
||||||
wakeUpCommon <- struct{}{} // block anyways, to queue up the wakeup
|
|
||||||
}
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -369,6 +366,11 @@ func activeSide(g *config.Global, in *config.ActiveJob, configJob interface{}, p
|
|||||||
return nil, errors.Wrap(err, "cannot build replication driver config")
|
return nil, errors.Wrap(err, "cannot build replication driver config")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
j.triggers, err = trigger.FromConfig(in.Replication.Triggers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot build triggers")
|
||||||
|
}
|
||||||
|
|
||||||
return j, nil
|
return j, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,12 +445,17 @@ func (j *ActiveSide) Run(ctx context.Context) {
|
|||||||
|
|
||||||
defer log.Info("job exiting")
|
defer log.Info("job exiting")
|
||||||
|
|
||||||
periodicDone := make(chan struct{})
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
periodicCtx, endTask := trace.WithTask(ctx, "periodic")
|
|
||||||
|
periodCtx, endTask := trace.WithTask(ctx, "periodic")
|
||||||
|
defer endTask()
|
||||||
|
go j.mode.RunPeriodic(periodCtx, periodicTrigger)
|
||||||
|
|
||||||
|
wakeupTrigger := wakeup.Trigger(ctx)
|
||||||
|
|
||||||
|
triggered, endTask := j.triggers.Spawn(ctx, []*trigger.Trigger{periodicTrigger, wakeupTrigger})
|
||||||
defer endTask()
|
defer endTask()
|
||||||
go j.mode.RunPeriodic(periodicCtx, periodicDone)
|
|
||||||
|
|
||||||
invocationCount := 0
|
invocationCount := 0
|
||||||
outer:
|
outer:
|
||||||
@@ -458,10 +465,15 @@ outer:
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.WithError(ctx.Err()).Info("context")
|
log.WithError(ctx.Err()).Info("context")
|
||||||
break outer
|
break outer
|
||||||
|
case trigger := <-triggered:
|
||||||
case <-wakeup.Wait(ctx):
|
log :=
|
||||||
j.mode.ResetConnectBackoff()
|
log.WithField("trigger_id", trigger.ID())
|
||||||
case <-periodicDone:
|
log.Info("triggered")
|
||||||
|
switch trigger {
|
||||||
|
case wakeupTrigger:
|
||||||
|
log.Info("trigger is wakeup command, resetting connection backoff")
|
||||||
|
j.mode.ResetConnectBackoff()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
invocationCount++
|
invocationCount++
|
||||||
invocationCtx, endSpan := trace.WithSpan(ctx, fmt.Sprintf("invocation-%d", invocationCount))
|
invocationCtx, endSpan := trace.WithSpan(ctx, fmt.Sprintf("invocation-%d", invocationCount))
|
||||||
@@ -481,7 +493,7 @@ func (j *ActiveSide) do(ctx context.Context) {
|
|||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-reset.Wait(ctx):
|
case <-reset.Wait(ctx):
|
||||||
GetLogger(ctx).Info("reset received, cancelling current invocation")
|
log.Info("reset received, cancelling current invocation")
|
||||||
cancelThisRun()
|
cancelThisRun()
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/transport"
|
"github.com/zrepl/zrepl/transport"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFakeActiveSideDirectMethodInvocationClientIdentityDoesNotPassValidityTest(t *testing.T) {
|
func TestFakeActiveSideDirectMethodInvocationClientIdentityDoesNotPassValidityTest(t *testing.T) {
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
// Code generated by "enumer -type=ActiveSideState"; DO NOT EDIT.
|
// Code generated by "enumer -type=ActiveSideState"; DO NOT EDIT.
|
||||||
|
|
||||||
|
//
|
||||||
package job
|
package job
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/util/bandwidthlimit"
|
"github.com/zrepl/zrepl/util/bandwidthlimit"
|
||||||
)
|
)
|
||||||
|
|
||||||
func JobsFromConfig(c *config.Config, parseFlags config.ParseFlags) ([]Job, error) {
|
func JobsFromConfig(c *config.Config, parseFlags config.ParseFlags) ([]Job, error) {
|
||||||
+5
-5
@@ -3,11 +3,11 @@ package job
|
|||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/filters"
|
"github.com/zrepl/zrepl/daemon/filters"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/util/nodefault"
|
"github.com/zrepl/zrepl/util/nodefault"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SendingJobConfig interface {
|
type SendingJobConfig interface {
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidateReceivingSidesDoNotOverlap(t *testing.T) {
|
func TestValidateReceivingSidesDoNotOverlap(t *testing.T) {
|
||||||
@@ -113,7 +113,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSampleConfigsAreBuiltWithoutErrors(t *testing.T) {
|
func TestSampleConfigsAreBuiltWithoutErrors(t *testing.T) {
|
||||||
paths, err := filepath.Glob("../../../internal/config/samples/*")
|
paths, err := filepath.Glob("../../config/samples/*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("glob failed: %+v", err)
|
t.Errorf("glob failed: %+v", err)
|
||||||
}
|
}
|
||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
"github.com/zrepl/zrepl/daemon/logging"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/logger"
|
"github.com/zrepl/zrepl/logger"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Logger = logger.Logger
|
type Logger = logger.Logger
|
||||||
@@ -7,16 +7,16 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging/trace"
|
"github.com/zrepl/zrepl/daemon/logging/trace"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/internal/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/logging"
|
"github.com/zrepl/zrepl/daemon/logging"
|
||||||
"github.com/zrepl/zrepl/internal/daemon/snapper"
|
"github.com/zrepl/zrepl/daemon/snapper"
|
||||||
"github.com/zrepl/zrepl/internal/endpoint"
|
"github.com/zrepl/zrepl/endpoint"
|
||||||
"github.com/zrepl/zrepl/internal/rpc"
|
"github.com/zrepl/zrepl/rpc"
|
||||||
"github.com/zrepl/zrepl/internal/transport"
|
"github.com/zrepl/zrepl/transport"
|
||||||
"github.com/zrepl/zrepl/internal/transport/fromconfig"
|
"github.com/zrepl/zrepl/transport/fromconfig"
|
||||||
"github.com/zrepl/zrepl/internal/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PassiveSide struct {
|
type PassiveSide struct {
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user