mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 00:13:52 +01:00
'zrepl version' and 'zrepl control version' subcommand + maintainer README
Version is autodetected on build using git If it cannot be detected with git, an override must be provided. For tracability of distros, the distroy packagers should override as well, which is why I added a README entry for package mainatiners. refs #35
This commit is contained in:
parent
d59426a8cc
commit
896f31bbf3
17
Makefile
17
Makefile
@ -8,13 +8,23 @@ _TESTPKGS := $(ROOT) $(foreach p,$(SUBPKGS),$(ROOT)/$(p))
|
||||
|
||||
ARTIFACTDIR := artifacts
|
||||
|
||||
ifndef ZREPL_VERSION
|
||||
ZREPL_VERSION := $(shell git describe --dirty 2>/dev/null || echo "ZREPL_BUILD_INVALID_VERSION" )
|
||||
ifeq ($(ZREPL_VERSION),ZREPL_BUILD_INVALID_VERSION) # can't use .SHELLSTATUS because Debian Stretch is still on gmake 4.1
|
||||
$(error cannot infer variable ZREPL_VERSION using git and variable is not overriden by make invocation)
|
||||
endif
|
||||
endif
|
||||
GO_LDFLAGS := "-X github.com/zrepl/zrepl/cmd.zreplVersion=$(ZREPL_VERSION)"
|
||||
|
||||
GO_BUILD := go build -ldflags $(GO_LDFLAGS)
|
||||
|
||||
generate: #not part of the build, must do that manually
|
||||
@for pkg in $(_TESTPKGS); do\
|
||||
go generate "$$pkg" || exit 1; \
|
||||
done;
|
||||
|
||||
build:
|
||||
go build -o $(ARTIFACTDIR)/zrepl
|
||||
$(GO_BUILD) -o "$(ARTIFACTDIR)/zrepl"
|
||||
|
||||
test:
|
||||
@for pkg in $(_TESTPKGS); do \
|
||||
@ -54,10 +64,11 @@ docs-clean:
|
||||
BUILDDIR=../artifacts/docs
|
||||
|
||||
release-bins: $(ARTIFACTDIR) vet test
|
||||
GOOS=linux GOARCH=amd64 go build -o "$(ARTIFACTDIR)/zrepl-linux-amd64"
|
||||
GOOS=freebsd GOARCH=amd64 go build -o "$(ARTIFACTDIR)/zrepl-freebsd-amd64"
|
||||
GOOS=linux GOARCH=amd64 $(GO_BUILD) -o "$(ARTIFACTDIR)/zrepl-linux-amd64"
|
||||
GOOS=freebsd GOARCH=amd64 $(GO_BUILD) -o "$(ARTIFACTDIR)/zrepl-freebsd-amd64"
|
||||
|
||||
release: release-bins docs
|
||||
|
||||
|
||||
clean: docs-clean
|
||||
rm -rf "$(ARTIFACTDIR)"
|
||||
|
10
README.md
10
README.md
@ -20,6 +20,16 @@ zrepl is a ZFS filesystem backup & replication solution written in Go.
|
||||
The above does not apply if you already implemented everything.
|
||||
Check out the *Coding Workflow* section below for details.
|
||||
|
||||
## Package Maintainer Information
|
||||
|
||||
* Follow the steps in `docs/installation.rst -> Compiling from Source` and read the Makefile / shell scripts used in this process.
|
||||
* Make sure your distro is compatible with the paths in `docs/installation.rst`.
|
||||
* 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.
|
||||
* Use `make release ZREPL_VERSION='mydistro-1.2.3_1'`
|
||||
* Your distro's name and any versioning supplemental to zrepl's (e.g. package revesion) should be in this string
|
||||
* Make sure you are informed about new zrepl versions, e.g. by subscribing to GitHub's release RSS feed.
|
||||
|
||||
## Developer Documentation
|
||||
|
||||
First, use `./lazy.sh devesetup` to install build dependencies and read `docs/installation.rst -> Compiling from Source`.
|
||||
|
@ -1,8 +1,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
@ -29,8 +32,20 @@ func (j *ControlJob) JobName() string {
|
||||
return j.Name
|
||||
}
|
||||
|
||||
func (j *ControlJob) EndpointVersion(w http.ResponseWriter, r *http.Request) {
|
||||
var buf bytes.Buffer
|
||||
err := json.NewEncoder(&buf).Encode(NewZreplVersionInformation())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
io.WriteString(w, err.Error())
|
||||
} else {
|
||||
io.Copy(w, &buf)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
ControlJobEndpointProfile string = "/debug/pprof/profile"
|
||||
ControlJobEndpointVersion string = "/version"
|
||||
)
|
||||
|
||||
func (j *ControlJob) JobStart(ctx context.Context) {
|
||||
@ -46,6 +61,7 @@ func (j *ControlJob) JobStart(ctx context.Context) {
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(ControlJobEndpointProfile, requestLogger{log, pprof.Profile})
|
||||
mux.Handle(ControlJobEndpointVersion, requestLogger{log, j.EndpointVersion})
|
||||
server := http.Server{Handler: mux}
|
||||
|
||||
outer:
|
||||
|
@ -1,7 +1,9 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
@ -26,10 +28,33 @@ var pprofCmdArgs struct {
|
||||
seconds int64
|
||||
}
|
||||
|
||||
var controlVersionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "print version of running zrepl daemon",
|
||||
Run: doControLVersionCmd,
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(controlCmd)
|
||||
controlCmd.AddCommand(pprofCmd)
|
||||
pprofCmd.Flags().Int64Var(&pprofCmdArgs.seconds, "seconds", 30, "seconds to profile")
|
||||
controlCmd.AddCommand(controlVersionCmd)
|
||||
}
|
||||
|
||||
func controlHttpClient() (client http.Client, err error) {
|
||||
|
||||
conf, err := ParseConfig(rootArgs.configFile)
|
||||
if err != nil {
|
||||
return http.Client{}, err
|
||||
}
|
||||
|
||||
return http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.Dial("unix", conf.Global.Control.Sockpath)
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func doControlPProf(cmd *cobra.Command, args []string) {
|
||||
@ -41,12 +66,6 @@ func doControlPProf(cmd *cobra.Command, args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
conf, err := ParseConfig(rootArgs.configFile)
|
||||
if err != nil {
|
||||
log.Printf("error parsing config: %s", err)
|
||||
die()
|
||||
}
|
||||
|
||||
if cmd.Flags().Arg(0) != "cpu" {
|
||||
log.Printf("only CPU profiles are supported")
|
||||
log.Printf("%s", cmd.UsageString())
|
||||
@ -60,6 +79,7 @@ func doControlPProf(cmd *cobra.Command, args []string) {
|
||||
die()
|
||||
}
|
||||
var out io.Writer
|
||||
var err error
|
||||
if outfn == "-" {
|
||||
out = os.Stdout
|
||||
} else {
|
||||
@ -71,12 +91,10 @@ func doControlPProf(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
log.Printf("connecting to daemon")
|
||||
httpc := http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.Dial("unix", conf.Global.Control.Sockpath)
|
||||
},
|
||||
},
|
||||
httpc, err := controlHttpClient()
|
||||
if err != nil {
|
||||
log.Printf("error parsing config: %s", err)
|
||||
die()
|
||||
}
|
||||
|
||||
log.Printf("profiling...")
|
||||
@ -98,3 +116,40 @@ func doControlPProf(cmd *cobra.Command, args []string) {
|
||||
log.Printf("finished")
|
||||
|
||||
}
|
||||
|
||||
func doControLVersionCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
log := golog.New(os.Stderr, "", 0)
|
||||
|
||||
die := func() {
|
||||
log.Printf("exiting after error")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
httpc, err := controlHttpClient()
|
||||
if err != nil {
|
||||
log.Printf("could not connect to daemon: %s", err)
|
||||
die()
|
||||
}
|
||||
|
||||
resp, err := httpc.Get("http://unix" + ControlJobEndpointVersion)
|
||||
if err != nil {
|
||||
log.Printf("error: %s", err)
|
||||
die()
|
||||
} else if resp.StatusCode != http.StatusOK {
|
||||
var msg bytes.Buffer
|
||||
io.CopyN(&msg, resp.Body, 4096)
|
||||
log.Printf("error: %s", msg.String())
|
||||
die()
|
||||
}
|
||||
|
||||
var info ZreplVersionInformation
|
||||
err = json.NewDecoder(resp.Body).Decode(&info)
|
||||
if err != nil {
|
||||
log.Printf("error unmarshaling response: %s", err)
|
||||
die()
|
||||
}
|
||||
|
||||
fmt.Println(info.String())
|
||||
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ func doDaemon(cmd *cobra.Command, args []string) {
|
||||
|
||||
log := logger.NewLogger(conf.Global.logging.Outlets, 1*time.Second)
|
||||
|
||||
log.Info(NewZreplVersionInformation().String())
|
||||
log.Debug("starting daemon")
|
||||
ctx := context.WithValue(context.Background(), contextKeyLog, log)
|
||||
ctx = context.WithValue(ctx, contextKeyLog, log)
|
||||
|
@ -20,6 +20,10 @@ import (
|
||||
// Printf(format string, v ...interface{})
|
||||
//}
|
||||
|
||||
var (
|
||||
zreplVersion string // set by build infrastructure
|
||||
)
|
||||
|
||||
type Logger = *logger.Logger
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
|
42
cmd/version.go
Normal file
42
cmd/version.go
Normal file
@ -0,0 +1,42 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "print version of zrepl binary (for running daemon 'zrepl control version' command)",
|
||||
Run: doVersion,
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
func doVersion(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(NewZreplVersionInformation().String())
|
||||
}
|
||||
|
||||
type ZreplVersionInformation struct {
|
||||
Version string
|
||||
RuntimeGOOS string
|
||||
RuntimeGOARCH string
|
||||
RUNTIMECompiler string
|
||||
}
|
||||
|
||||
func NewZreplVersionInformation() *ZreplVersionInformation {
|
||||
return &ZreplVersionInformation{
|
||||
Version: zreplVersion,
|
||||
RuntimeGOOS: runtime.GOOS,
|
||||
RuntimeGOARCH: runtime.GOARCH,
|
||||
RUNTIMECompiler: runtime.Compiler,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ZreplVersionInformation) String() string {
|
||||
return fmt.Sprintf("zrepl version=%s GOOS=%s GOARCH=%s Compiler=%s",
|
||||
i.Version, i.RuntimeGOOS, i.RuntimeGOARCH, i.RUNTIMECompiler)
|
||||
}
|
Loading…
Reference in New Issue
Block a user