diff --git a/.etcd.metadata b/.etcd.metadata index 040093c..3dd8982 100644 --- a/.etcd.metadata +++ b/.etcd.metadata @@ -1,2 +1 @@ -80b405fd01527eea6668fde0186ca6b119c1185c SOURCES/etcd-0.4.6.tar.gz -924668c26a30bfe65ac88971965b1dad819be630 SOURCES/etcdctl-0.4.6.tar.gz +5b748244d62c8aa0578831fedcb39fd9f57449aa SOURCES/etcd-8a03d2e.tar.gz diff --git a/SOURCES/0001-Convert-int-to-string-using-strconv.Itoa.patch b/SOURCES/0001-Convert-int-to-string-using-strconv.Itoa.patch new file mode 100644 index 0000000..a2178d7 --- /dev/null +++ b/SOURCES/0001-Convert-int-to-string-using-strconv.Itoa.patch @@ -0,0 +1,61 @@ +From 80c8dfe084f44eb660aa1af5b5d49e27e1dfd11e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Robert-Andr=C3=A9=20Mauchin?= +Date: Mon, 10 Aug 2020 15:09:08 +0200 +Subject: [PATCH] Convert int to string using strconv.Itoa +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +See https://github.com/golang/go/issues/32479 + +Signed-off-by: Robert-André Mauchin +--- + etcdserver/api/v2store/store_test.go | 3 ++- + wal/wal_test.go | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/etcdserver/api/v2store/store_test.go b/etcdserver/api/v2store/store_test.go +index 76ec02d4e..0b1e9dad1 100644 +--- a/etcdserver/api/v2store/store_test.go ++++ b/etcdserver/api/v2store/store_test.go +@@ -15,6 +15,7 @@ + package v2store_test + + import ( ++ "strconv" + "testing" + "time" + +@@ -844,7 +845,7 @@ func TestStoreWatchSlowConsumer(t *testing.T) { + s.Watch("/foo", true, true, 0) // stream must be true + // Fill watch channel with 100 events + for i := 1; i <= 100; i++ { +- s.Set("/foo", false, string(i), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) // ok ++ s.Set("/foo", false, strconv.Itoa(i), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) // ok + } + // testutil.AssertEqual(t, s.WatcherHub.count, int64(1)) + s.Set("/foo", false, "101", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) // ok +diff --git a/wal/wal_test.go b/wal/wal_test.go +index f457dbf3c..8e8a252a0 100644 +--- a/wal/wal_test.go ++++ b/wal/wal_test.go +@@ -25,6 +25,7 @@ import ( + "path/filepath" + "reflect" + "regexp" ++ "strconv" + "testing" + + "go.etcd.io/etcd/pkg/fileutil" +@@ -239,7 +240,7 @@ func TestVerify(t *testing.T) { + + // make 5 separate files + for i := 0; i < 5; i++ { +- es := []raftpb.Entry{{Index: uint64(i), Data: []byte("waldata" + string(i+1))}} ++ es := []raftpb.Entry{{Index: uint64(i), Data: []byte("waldata" + strconv.Itoa(i+1))}} + if err = w.Save(raftpb.HardState{}, es); err != nil { + t.Fatal(err) + } +-- +2.26.2 + diff --git a/SOURCES/0001-hack-etcdmain-to-generate-etcd.1.patch b/SOURCES/0001-hack-etcdmain-to-generate-etcd.1.patch new file mode 100644 index 0000000..6c715d7 --- /dev/null +++ b/SOURCES/0001-hack-etcdmain-to-generate-etcd.1.patch @@ -0,0 +1,265 @@ +diff -up etcd-3.4.13/etcdmain/config.go.orig etcd-3.4.13/etcdmain/config.go +--- etcd-3.4.13/etcdmain/config.go.orig 2020-08-24 21:11:28.000000000 +0200 ++++ etcd-3.4.13/etcdmain/config.go 2020-09-04 00:12:28.424764763 +0200 +@@ -123,14 +123,15 @@ func newConfig() *config { + ), + } + +- fs := cfg.cf.flagSet +- fs.Usage = func() { ++ fs := InitFlagSet(cfg.cf.flagSet) ++ cfg.cf.flagSet.Usage = func() { + fmt.Fprintln(os.Stderr, usageline) + } + + fs.StringVar(&cfg.configFile, "config-file", "", "Path to the server configuration file. Note that if a configuration file is provided, other command line flags and environment variables will be ignored.") + + // member ++ fs.AddGroup("member") + fs.StringVar(&cfg.ec.Dir, "data-dir", cfg.ec.Dir, "Path to the data directory.") + fs.StringVar(&cfg.ec.WalDir, "wal-dir", cfg.ec.WalDir, "Path to the dedicated wal directory.") + fs.Var( +@@ -163,7 +164,7 @@ func newConfig() *config { + fs.DurationVar(&cfg.ec.GRPCKeepAliveInterval, "grpc-keepalive-interval", cfg.ec.GRPCKeepAliveInterval, "Frequency duration of server-to-client ping to check if a connection is alive (0 to disable).") + fs.DurationVar(&cfg.ec.GRPCKeepAliveTimeout, "grpc-keepalive-timeout", cfg.ec.GRPCKeepAliveTimeout, "Additional duration of wait before closing a non-responsive connection (0 to disable).") + +- // clustering ++ fs.AddGroup("clustering") + fs.Var( + flags.NewUniqueURLsWithExceptions(embed.DefaultInitialAdvertisePeerURLs, ""), + "initial-advertise-peer-urls", +@@ -188,7 +189,7 @@ func newConfig() *config { + fs.BoolVar(&cfg.ec.EnableV2, "enable-v2", cfg.ec.EnableV2, "Accept etcd V2 client requests.") + fs.BoolVar(&cfg.ec.PreVote, "pre-vote", cfg.ec.PreVote, "Enable to run an additional Raft election phase.") + +- // proxy ++ fs.AddGroup("proxy") + fs.Var(cfg.cf.proxy, "proxy", fmt.Sprintf("Valid values include %q", cfg.cf.proxy.Valids())) + fs.UintVar(&cfg.cp.ProxyFailureWaitMs, "proxy-failure-wait", cfg.cp.ProxyFailureWaitMs, "Time (in milliseconds) an endpoint will be held in a failed state.") + fs.UintVar(&cfg.cp.ProxyRefreshIntervalMs, "proxy-refresh-interval", cfg.cp.ProxyRefreshIntervalMs, "Time (in milliseconds) of the endpoints refresh interval.") +@@ -196,7 +197,7 @@ func newConfig() *config { + fs.UintVar(&cfg.cp.ProxyWriteTimeoutMs, "proxy-write-timeout", cfg.cp.ProxyWriteTimeoutMs, "Time (in milliseconds) for a write to timeout.") + fs.UintVar(&cfg.cp.ProxyReadTimeoutMs, "proxy-read-timeout", cfg.cp.ProxyReadTimeoutMs, "Time (in milliseconds) for a read to timeout.") + +- // security ++ fs.AddGroup("security") + fs.StringVar(&cfg.ec.ClientTLSInfo.CertFile, "cert-file", "", "Path to the client server TLS cert file.") + fs.StringVar(&cfg.ec.ClientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.") + fs.BoolVar(&cfg.ec.ClientTLSInfo.ClientCertAuth, "client-cert-auth", false, "Enable client cert authentication.") +@@ -222,7 +223,7 @@ func newConfig() *config { + ) + fs.Var(flags.NewUniqueStringsValue("*"), "host-whitelist", "Comma-separated acceptable hostnames from HTTP client requests, if server is not secure (empty means allow all).") + +- // logging ++ fs.AddGroup("logging") + fs.StringVar(&cfg.ec.Logger, "logger", "capnslog", "Specify 'zap' for structured logging or 'capnslog'. WARN: 'capnslog' is being deprecated in v3.5.") + fs.Var(flags.NewUniqueStringsValue(embed.DefaultLogOutput), "log-output", "[TO BE DEPRECATED IN v3.5] use '--log-outputs'.") + fs.Var(flags.NewUniqueStringsValue(embed.DefaultLogOutput), "log-outputs", "Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd, or list of comma separated output targets.") +@@ -230,27 +231,27 @@ func newConfig() *config { + fs.StringVar(&cfg.ec.LogLevel, "log-level", logutil.DefaultLogLevel, "Configures log level. Only supports debug, info, warn, error, panic, or fatal. Default 'info'.") + fs.StringVar(&cfg.ec.LogPkgLevels, "log-package-levels", "", "[TO BE DEPRECATED IN v3.5] Specify a particular log level for each etcd package (eg: 'etcdmain=CRITICAL,etcdserver=DEBUG').") + +- // version ++ fs.AddGroup("version") + fs.BoolVar(&cfg.printVersion, "version", false, "Print the version and exit.") + + fs.StringVar(&cfg.ec.AutoCompactionRetention, "auto-compaction-retention", "0", "Auto compaction retention for mvcc key value store. 0 means disable auto compaction.") + fs.StringVar(&cfg.ec.AutoCompactionMode, "auto-compaction-mode", "periodic", "interpret 'auto-compaction-retention' one of: periodic|revision. 'periodic' for duration based retention, defaulting to hours if no time unit is provided (e.g. '5m'). 'revision' for revision number based retention.") + +- // pprof profiler via HTTP ++ fs.AddGroup("profiling") + fs.BoolVar(&cfg.ec.EnablePprof, "enable-pprof", false, "Enable runtime profiling data via HTTP server. Address is at client URL + \"/debug/pprof/\"") + + // additional metrics + fs.StringVar(&cfg.ec.Metrics, "metrics", cfg.ec.Metrics, "Set level of detail for exported metrics, specify 'extensive' to include histogram metrics") + +- // auth ++ fs.AddGroup("auth") + fs.StringVar(&cfg.ec.AuthToken, "auth-token", cfg.ec.AuthToken, "Specify auth token specific options.") + fs.UintVar(&cfg.ec.BcryptCost, "bcrypt-cost", cfg.ec.BcryptCost, "Specify bcrypt algorithm cost factor for auth password hashing.") + fs.UintVar(&cfg.ec.AuthTokenTTL, "auth-token-ttl", cfg.ec.AuthTokenTTL, "The lifetime in seconds of the auth token.") + +- // gateway ++ fs.AddGroup("gateway") + fs.BoolVar(&cfg.ec.EnableGRPCGateway, "enable-grpc-gateway", true, "Enable GRPC gateway.") + +- // experimental ++ fs.AddGroup("experimental") + fs.BoolVar(&cfg.ec.ExperimentalInitialCorruptCheck, "experimental-initial-corrupt-check", cfg.ec.ExperimentalInitialCorruptCheck, "Enable to check data corruption before serving any client/peer traffic.") + fs.DurationVar(&cfg.ec.ExperimentalCorruptCheckTime, "experimental-corrupt-check-time", cfg.ec.ExperimentalCorruptCheckTime, "Duration of time between cluster corruption check passes.") + fs.StringVar(&cfg.ec.ExperimentalEnableV2V3, "experimental-enable-v2v3", cfg.ec.ExperimentalEnableV2V3, "v3 prefix for serving emulated v2 state.") +@@ -259,9 +260,12 @@ func newConfig() *config { + fs.IntVar(&cfg.ec.ExperimentalCompactionBatchLimit, "experimental-compaction-batch-limit", cfg.ec.ExperimentalCompactionBatchLimit, "Sets the maximum revisions deleted in each compaction batch.") + fs.DurationVar(&cfg.ec.ExperimentalWatchProgressNotifyInterval, "experimental-watch-progress-notify-interval", cfg.ec.ExperimentalWatchProgressNotifyInterval, "Duration of periodic watch progress notifications.") + +- // unsafe ++ fs.AddGroup("unsafe") + fs.BoolVar(&cfg.ec.UnsafeNoFsync, "unsafe-no-fsync", false, "Disables fsync, unsafe, will cause data loss.") + fs.BoolVar(&cfg.ec.ForceNewCluster, "force-new-cluster", false, "Force to create a new one member cluster.") ++ ++ fs.GenMan() ++ os.Exit(0) + + // ignored + for _, f := range cfg.ignored { +diff -up etcd-3.4.13/etcdmain/fake_flagset.go.orig etcd-3.4.13/etcdmain/fake_flagset.go +--- etcd-3.4.13/etcdmain/fake_flagset.go.orig 2020-09-04 00:10:11.223684457 +0200 ++++ etcd-3.4.13/etcdmain/fake_flagset.go 2020-09-04 00:10:11.223684457 +0200 +@@ -0,0 +1,157 @@ ++package etcdmain ++ ++import ( ++ "flag" ++ "fmt" ++ "strconv" ++ "strings" ++ "time" ++) ++ ++type flagInfo struct { ++ value fmt.Stringer ++ name string ++ usage string ++} ++ ++type stringValue string ++ ++func (s *stringValue) String() string { return string(*s) } ++ ++type uintValue uint ++ ++func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) } ++ ++type uint64Value uint64 ++ ++func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) } ++ ++type int64Value int64 ++ ++func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) } ++ ++type durationValue time.Duration ++ ++func (d *durationValue) String() string { return (*time.Duration)(d).String() } ++ ++type boolValue bool ++ ++func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) } ++ ++type FakeFlagSet struct { ++ fs *flag.FlagSet ++ flags map[string][]flagInfo ++ groups []string ++ lastGroup string ++} ++ ++func InitFlagSet(fs *flag.FlagSet) *FakeFlagSet { ++ return &FakeFlagSet{ ++ fs: fs, ++ flags: make(map[string][]flagInfo), ++ } ++} ++ ++func (fs *FakeFlagSet) AddGroup(name string) { ++ fs.flags[name] = nil ++ fs.groups = append(fs.groups, name) ++ fs.lastGroup = name ++} ++ ++func (fs *FakeFlagSet) Var(value flag.Value, name string, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: value, ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.Var(value, name, usage) ++} ++ ++func (fs *FakeFlagSet) StringVar(p *string, name string, value string, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*stringValue)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.StringVar(p, name, value, usage) ++} ++ ++// -- int Value ++type intValue int ++ ++func (i *intValue) String() string { return strconv.Itoa(int(*i)) } ++ ++func (fs *FakeFlagSet) UintVar(p *uint, name string, value uint, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*uintValue)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.UintVar(p, name, value, usage) ++} ++ ++func (fs *FakeFlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*uint64Value)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.Uint64Var(p, name, value, usage) ++} ++ ++func (fs *FakeFlagSet) IntVar(p *int, name string, value int, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*intValue)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.IntVar(p, name, value, usage) ++} ++ ++func (fs *FakeFlagSet) Int64Var(p *int64, name string, value int64, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*int64Value)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.Int64Var(p, name, value, usage) ++} ++ ++func (fs *FakeFlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*durationValue)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.DurationVar(p, name, value, usage) ++} ++ ++func (fs *FakeFlagSet) BoolVar(p *bool, name string, value bool, usage string) { ++ fs.flags[fs.lastGroup] = append(fs.flags[fs.lastGroup], flagInfo{ ++ value: (*boolValue)(&value), ++ name: name, ++ usage: usage, ++ }) ++ fs.fs.BoolVar(p, name, value, usage) ++} ++ ++func (fs *FakeFlagSet) GenMan() { ++ fmt.Printf(".TH \"ETCD\" \"1\" \" etcd User Manuals\" \"Etcd contributors\" \"Nov 2017\" \"\"\n") ++ fmt.Printf(".SH NAME:\netcd - Distributed reliable key-value store for the most critical data of a distributed system\n\n") ++ fmt.Printf(".SH USAGE:\netcd [flags]\n\n") ++ fmt.Printf(".SH DESCRIPTION:\nEtcd is a distributed key-value store designed to reliably and quickly preserve and provide access to critical data. It enables reliable distributed coordination through distributed locking, leader elections, and write barriers. An etcd cluster is intended for high availability and permanent data storage and retrieval.\n\n") ++ fmt.Printf(".SH GENERAL OPTIONS\n\n") ++ for _, group := range fs.groups { ++ fmt.Printf(".I %v flags\n\n", strings.Title(group)) ++ for _, flag := range fs.flags[group] { ++ var flagstr string ++ if len(flag.name) == 1 { ++ flagstr = "-" + flag.name ++ } else { ++ flagstr = "--" + flag.name ++ } ++ fmt.Printf(".RS\n\\fB%v %v\\fP\n %v\n\n.RE\n", flagstr, flag.value.String(), flag.usage) ++ } ++ } ++ fmt.Printf(".SH SEE ALSO:\n\\fBetcdctl(1)\\fP, \\fBetcdctl2(1)\\fP, \\fBetcdctl3(1)\\fP\n\n") ++} diff --git a/SOURCES/0001-hack-to-generate-man-pages.patch b/SOURCES/0001-hack-to-generate-man-pages.patch new file mode 100644 index 0000000..37ea9cf --- /dev/null +++ b/SOURCES/0001-hack-to-generate-man-pages.patch @@ -0,0 +1,120 @@ +diff -up etcd-3.4.13/etcdctl/ctlv2/ctl.go.orig2 etcd-3.4.13/etcdctl/ctlv2/ctl.go +--- etcd-3.4.13/etcdctl/ctlv2/ctl.go.orig2 2020-08-24 21:11:28.000000000 +0200 ++++ etcd-3.4.13/etcdctl/ctlv2/ctl.go 2020-09-04 00:13:47.552811076 +0200 +@@ -36,6 +36,68 @@ func Start() { + } + app.Usage = "A simple command line client for etcd." + ++ cli.AppHelpTemplate = `.TH "ETCD" "1" " etcd User Manuals" "Etcd contributors" "Nov 2017" "" ++.SH NAME: ++{{.Name}} - {{.Usage}} ++ ++{{if .Version}} ++.SH VERSION: ++ {{.Version}} ++{{end}} ++ ++.SH USAGE: ++ {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} ++ {{if .Commands}} ++ ++.SH COMMANDS: ++{{range .Commands}}{{if not .HideHelp}}\fB{{ .Name }}\fP{{ "\n\t\t\t" }}{{.Usage}}{{ "\n" }} ++ ++{{end}}{{end}}{{end}}{{if .VisibleFlags}} ++ ++.SH GLOBAL OPTIONS: ++{{range .VisibleFlags}}{{ . }} ++ ++{{end}}{{end}} ++ ++.SH SEE ALSO ++{{range .Commands}}{{if not .HideHelp}}{{if ne .Name "help" }}\fBetcdctl-{{ .Name }}(1)\fP, ++{{end}}{{end}}{{end}} ++` ++ ++ cli.CommandHelpTemplate = `.TH "ETCD" "1" " etcd User Manuals" "Etcd contributors" "Nov 2017" "" ++.SH NAME: ++ {{.HelpName}} - {{.Usage}} ++ ++.SH USAGE: ++ {{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} ++ ++{{if .VisibleFlags}} ++.SH OPTIONS: ++ {{range .VisibleFlags}}{{.}} ++ {{end}}{{end}} ++` ++ ++ ++ cli.SubcommandHelpTemplate = `.TH "ETCD" "1" " etcd User Manuals" "Etcd contributors" "Nov 2017" "" ++.SH NAME: ++ {{.HelpName}} - {{.Usage}} ++ ++.SH USAGE: ++ {{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} ++ ++.SH COMMANDS: ++{{range .VisibleCategories}}{{if .Name}} ++{{.Name}}:{{end}}{{range .VisibleCommands}} ++\fB{{ .Name }}\fP{{"\n\t\t\t"}}{{.Usage}}{{ "\n" }}{{end}} ++{{end}} ++ ++{{if .VisibleFlags}} ++.SH OPTIONS: ++{{range .VisibleFlags}}{{.}} ++{{end}}{{end}} ++` ++ ++ + app.Flags = []cli.Flag{ + cli.BoolFlag{Name: "debug", Usage: "output cURL commands which can be used to reproduce the request"}, + cli.BoolFlag{Name: "no-sync", Usage: "don't synchronize cluster information before sending request"}, +diff -up etcd-3.4.13/etcdctl/ctlv3/ctl_nocov.go.orig2 etcd-3.4.13/etcdctl/ctlv3/ctl_nocov.go +--- etcd-3.4.13/etcdctl/ctlv3/ctl_nocov.go.orig2 2020-08-24 21:11:28.000000000 +0200 ++++ etcd-3.4.13/etcdctl/ctlv3/ctl_nocov.go 2020-09-04 00:13:47.553811076 +0200 +@@ -16,13 +16,20 @@ + + package ctlv3 + +-import "go.etcd.io/etcd/etcdctl/ctlv3/command" ++//import "github.com/coreos/etcd/etcdctl/ctlv3/command" ++import cobra "github.com/spf13/cobra/doc" + + func Start() { + rootCmd.SetUsageFunc(usageFunc) + // Make help just show the usage + rootCmd.SetHelpTemplate(`{{.UsageString}}`) +- if err := rootCmd.Execute(); err != nil { +- command.ExitWithError(command.ExitError, err) ++ //if err := rootCmd.Execute(); err != nil { ++ // command.ExitWithError(command.ExitError, err) ++ //} ++ header := &cobra.GenManHeader{ ++ Title: "etcdctl3", ++ Section: "1", + } ++ ++ cobra.GenManTree(rootCmd, header, "") + } +diff -up etcd-3.4.13/vendor/github.com/urfave/cli/flag.go.orig2 etcd-3.4.13/vendor/github.com/urfave/cli/flag.go +--- etcd-3.4.13/vendor/github.com/urfave/cli/flag.go.orig2 2020-08-24 21:11:28.000000000 +0200 ++++ etcd-3.4.13/vendor/github.com/urfave/cli/flag.go 2020-09-04 00:13:47.555811078 +0200 +@@ -670,7 +670,7 @@ func prefixedNames(fullName, placeholder + parts := strings.Split(fullName, ",") + for i, name := range parts { + name = strings.Trim(name, " ") +- prefixed += prefixFor(name) + name ++ prefixed += "\\fB" + prefixFor(name) + name + "\\fP" + if placeholder != "" { + prefixed += " " + placeholder + } +@@ -745,7 +745,7 @@ func stringifyFlag(f Flag) string { + usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString)) + + return withEnvHint(fv.FieldByName("EnvVar").String(), +- fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault)) ++ fmt.Sprintf("%s\n\t\t\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault)) + } + + func stringifyIntSliceFlag(f IntSliceFlag) string { diff --git a/SOURCES/0001-remove-unknown-field-Etcd.Debug.patch b/SOURCES/0001-remove-unknown-field-Etcd.Debug.patch new file mode 100644 index 0000000..76ec821 --- /dev/null +++ b/SOURCES/0001-remove-unknown-field-Etcd.Debug.patch @@ -0,0 +1,37 @@ +From 2c95b49b63651ae3e0a3f63c45c05295d1af2c42 Mon Sep 17 00:00:00 2001 +From: lsytj0413 <511121939@qq.com> +Date: Thu, 19 Sep 2019 09:51:51 +0800 +Subject: [PATCH] test(functional): remove unknown field Etcd.Debug + +--- + functional/tester/cluster_test.go | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/functional/tester/cluster_test.go b/functional/tester/cluster_test.go +index 7c7b25f2ad..2948c00e7f 100644 +--- a/functional/tester/cluster_test.go ++++ b/functional/tester/cluster_test.go +@@ -64,7 +64,6 @@ func Test_read(t *testing.T) { + InitialCorruptCheck: true, + Logger: "zap", + LogOutputs: []string{"/tmp/etcd-functional-1/etcd.log"}, +- Debug: true, + }, + ClientCertData: "", + ClientCertPath: "", +@@ -117,7 +116,6 @@ func Test_read(t *testing.T) { + InitialCorruptCheck: true, + Logger: "zap", + LogOutputs: []string{"/tmp/etcd-functional-2/etcd.log"}, +- Debug: true, + }, + ClientCertData: "", + ClientCertPath: "", +@@ -170,7 +168,6 @@ func Test_read(t *testing.T) { + InitialCorruptCheck: true, + Logger: "zap", + LogOutputs: []string{"/tmp/etcd-functional-3/etcd.log"}, +- Debug: true, + }, + ClientCertData: "", + ClientCertPath: "", diff --git a/SOURCES/0001-update-grpc-go-version-to-v1.32.0.patch b/SOURCES/0001-update-grpc-go-version-to-v1.32.0.patch new file mode 100644 index 0000000..4c40ac0 --- /dev/null +++ b/SOURCES/0001-update-grpc-go-version-to-v1.32.0.patch @@ -0,0 +1,412 @@ +From 2859e9f94608b44c9c351c7ccfcff21665573627 Mon Sep 17 00:00:00 2001 +From: Sky Ao +Date: Thu, 15 Oct 2020 15:34:16 +0800 +Subject: [PATCH 1/4] update grpc-go version to v1.32.0 which has some breaking + api changes in naming and loadbalancer package + +--- + clientv3/balancer/balancer.go | 39 ++- + clientv3/balancer/picker/err.go | 6 +- + .../balancer/picker/roundrobin_balanced.go | 7 +- + clientv3/naming/grpc.go | 27 +- + clientv3/naming/grpcnaming/naming.go | 73 +++++ + proxy/grpcproxy/cluster.go | 2 +- + proxy/grpcproxy/register.go | 2 +- + 7 files changed, 424 insertions(+), 46 deletions(-) + create mode 100644 clientv3/naming/grpcnaming/naming.go + +diff --git a/clientv3/balancer/balancer.go b/clientv3/balancer/balancer.go +index 3eecb9d1d2..d3e672c632 100644 +--- a/clientv3/balancer/balancer.go ++++ b/clientv3/balancer/balancer.go +@@ -136,15 +136,34 @@ type baseBalancer struct { + connectivityRecorder connectivity.Recorder + + picker picker.Picker ++ ++ resolverErr error // the last error reported by the resolver; cleared on successful resolution + } + +-// HandleResolvedAddrs implements "grpc/balancer.Balancer" interface. +-// gRPC sends initial or updated resolved addresses from "Build". +-func (bb *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) { +- if err != nil { +- bb.lg.Warn("HandleResolvedAddrs called with error", zap.String("balancer-id", bb.id), zap.Error(err)) ++func (bb *baseBalancer) ResolverError(err error) { ++ bb.resolverErr = err ++ if len(bb.addrToSc) == 0 { ++ bb.connectivityRecorder.RecordTransition(bb.connectivityRecorder.GetCurrentState(), grpcconnectivity.TransientFailure) ++ } ++ ++ if bb.connectivityRecorder.GetCurrentState() != grpcconnectivity.TransientFailure { ++ // The picker will not change since the balancer does not currently ++ // report an error. + return + } ++ bb.updatePicker() ++ bb.currentConn.UpdateState(balancer.State{ ++ ConnectivityState: bb.connectivityRecorder.GetCurrentState(), ++ Picker: bb.picker, ++ }) ++} ++ ++// UpdateClientConnState implements "grpc/balancer.Balancer" interface. ++func (bb *baseBalancer) UpdateClientConnState(state balancer.ClientConnState) error { ++ addrs := state.ResolverState.Addresses ++ // Successful resolution; clear resolver error and ensure we return nil. ++ bb.resolverErr = nil ++ + bb.lg.Info("resolved", + zap.String("picker", bb.picker.String()), + zap.String("balancer-id", bb.id), +@@ -191,10 +210,14 @@ func (bb *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) + // (DO NOT) delete(bb.scToSt, sc) + } + } ++ ++ return nil + } + +-// HandleSubConnStateChange implements "grpc/balancer.Balancer" interface. +-func (bb *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s grpcconnectivity.State) { ++// UpdateSubConnState implements "grpc/balancer.Balancer" interface. ++func (bb *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) { ++ s := state.ConnectivityState ++ + bb.mu.Lock() + defer bb.mu.Unlock() + +@@ -247,7 +270,7 @@ func (bb *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s grpcconn + bb.updatePicker() + } + +- bb.currentConn.UpdateBalancerState(bb.connectivityRecorder.GetCurrentState(), bb.picker) ++ bb.currentConn.UpdateState(balancer.State{ConnectivityState: bb.connectivityRecorder.GetCurrentState(), Picker: bb.picker}) + } + + func (bb *baseBalancer) updatePicker() { +diff --git a/clientv3/balancer/picker/err.go b/clientv3/balancer/picker/err.go +index f4b941d652..a37baa7bd2 100644 +--- a/clientv3/balancer/picker/err.go ++++ b/clientv3/balancer/picker/err.go +@@ -15,8 +15,6 @@ + package picker + + import ( +- "context" +- + "google.golang.org/grpc/balancer" + ) + +@@ -34,6 +32,6 @@ func (ep *errPicker) String() string { + return ep.p.String() + } + +-func (ep *errPicker) Pick(context.Context, balancer.PickInfo) (balancer.SubConn, func(balancer.DoneInfo), error) { +- return nil, nil, ep.err ++func (ep *errPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { ++ return balancer.PickResult{}, ep.err + } +diff --git a/clientv3/balancer/picker/roundrobin_balanced.go b/clientv3/balancer/picker/roundrobin_balanced.go +index e3971ecc42..993c05ec13 100644 +--- a/clientv3/balancer/picker/roundrobin_balanced.go ++++ b/clientv3/balancer/picker/roundrobin_balanced.go +@@ -15,7 +15,6 @@ + package picker + + import ( +- "context" + "sync" + + "go.uber.org/zap" +@@ -52,12 +51,12 @@ type rrBalanced struct { + func (rb *rrBalanced) String() string { return rb.p.String() } + + // Pick is called for every client request. +-func (rb *rrBalanced) Pick(ctx context.Context, opts balancer.PickInfo) (balancer.SubConn, func(balancer.DoneInfo), error) { ++func (rb *rrBalanced) Pick(opts balancer.PickInfo) (balancer.PickResult, error) { + rb.mu.RLock() + n := len(rb.scs) + rb.mu.RUnlock() + if n == 0 { +- return nil, nil, balancer.ErrNoSubConnAvailable ++ return balancer.PickResult{}, balancer.ErrNoSubConnAvailable + } + + rb.mu.Lock() +@@ -91,5 +90,5 @@ func (rb *rrBalanced) Pick(ctx context.Context, opts balancer.PickInfo) (balance + rb.lg.Warn("balancer failed", fss...) + } + } +- return sc, doneFunc, nil ++ return balancer.PickResult{SubConn: sc, Done: doneFunc}, nil + } +diff --git a/clientv3/naming/grpc.go b/clientv3/naming/grpc.go +index b680274bb3..f7cd2bd8a6 100644 +--- a/clientv3/naming/grpc.go ++++ b/clientv3/naming/grpc.go +@@ -20,9 +20,9 @@ import ( + "fmt" + + etcd "go.etcd.io/etcd/clientv3" ++ gnaming "go.etcd.io/etcd/clientv3/naming/grpcnaming" + + "google.golang.org/grpc/codes" +- "google.golang.org/grpc/naming" + "google.golang.org/grpc/status" + ) + +@@ -34,15 +33,15 @@ type GRPCResolver struct { + Client *etcd.Client + } + +-func (gr *GRPCResolver) Update(ctx context.Context, target string, nm naming.Update, opts ...etcd.OpOption) (err error) { ++func (gr *GRPCResolver) Update(ctx context.Context, target string, nm gnaming.Update, opts ...etcd.OpOption) (err error) { + switch nm.Op { +- case naming.Add: ++ case gnaming.Add: + var v []byte + if v, err = json.Marshal(nm); err != nil { + return status.Error(codes.InvalidArgument, err.Error()) + } + _, err = gr.Client.KV.Put(ctx, target+"/"+nm.Addr, string(v), opts...) +- case naming.Delete: ++ case gnaming.Delete: + _, err = gr.Client.Delete(ctx, target+"/"+nm.Addr, opts...) + default: + return status.Error(codes.InvalidArgument, "naming: bad naming op") +@@ -50,7 +49,7 @@ func (gr *GRPCResolver) Update(ctx context.Context, target string, nm naming.Upd + return err + } + +-func (gr *GRPCResolver) Resolve(target string) (naming.Watcher, error) { ++func (gr *GRPCResolver) Resolve(target string) (gnaming.Watcher, error) { + ctx, cancel := context.WithCancel(context.Background()) + w := &gRPCWatcher{c: gr.Client, target: target + "/", ctx: ctx, cancel: cancel} + return w, nil +@@ -68,7 +67,7 @@ type gRPCWatcher struct { + // Next gets the next set of updates from the etcd resolver. + // Calls to Next should be serialized; concurrent calls are not safe since + // there is no way to reconcile the update ordering. +-func (gw *gRPCWatcher) Next() ([]*naming.Update, error) { ++func (gw *gRPCWatcher) Next() ([]*gnaming.Update, error) { + if gw.wch == nil { + // first Next() returns all addresses + return gw.firstNext() +@@ -87,17 +86,17 @@ func (gw *gRPCWatcher) Next() ([]*naming.Update, error) { + return nil, gw.err + } + +- updates := make([]*naming.Update, 0, len(wr.Events)) ++ updates := make([]*gnaming.Update, 0, len(wr.Events)) + for _, e := range wr.Events { +- var jupdate naming.Update ++ var jupdate gnaming.Update + var err error + switch e.Type { + case etcd.EventTypePut: + err = json.Unmarshal(e.Kv.Value, &jupdate) +- jupdate.Op = naming.Add ++ jupdate.Op = gnaming.Add + case etcd.EventTypeDelete: + err = json.Unmarshal(e.PrevKv.Value, &jupdate) +- jupdate.Op = naming.Delete ++ jupdate.Op = gnaming.Delete + default: + continue + } +@@ -108,7 +107,7 @@ func (gw *gRPCWatcher) Next() ([]*naming.Update, error) { + return updates, nil + } + +-func (gw *gRPCWatcher) firstNext() ([]*naming.Update, error) { ++func (gw *gRPCWatcher) firstNext() ([]*gnaming.Update, error) { + // Use serialized request so resolution still works if the target etcd + // server is partitioned away from the quorum. + resp, err := gw.c.Get(gw.ctx, gw.target, etcd.WithPrefix(), etcd.WithSerializable()) +@@ -116,9 +115,9 @@ func (gw *gRPCWatcher) firstNext() ([]*naming.Update, error) { + return nil, err + } + +- updates := make([]*naming.Update, 0, len(resp.Kvs)) ++ updates := make([]*gnaming.Update, 0, len(resp.Kvs)) + for _, kv := range resp.Kvs { +- var jupdate naming.Update ++ var jupdate gnaming.Update + if err := json.Unmarshal(kv.Value, &jupdate); err != nil { + continue + } +diff --git a/clientv3/naming/grpcnaming/naming.go b/clientv3/naming/grpcnaming/naming.go +new file mode 100644 +index 0000000000..9b1f20cc61 +--- /dev/null ++++ b/clientv3/naming/grpcnaming/naming.go +@@ -0,0 +1,73 @@ ++/* ++ * ++ * Copyright 2014 gRPC authors. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++ ++// Package naming defines the naming API and related data structures for gRPC. ++// ++// This package is deprecated: please use package resolver instead. ++ ++ ++// Notice: this file is a copy of naming/naming.go from grpc-go v1.29.1. ++// The package of grpc naming is removed since grpc-go v1.30.0. ++// This is a work around to make etcd work with grpc new version (>=v1.30.0) without too many code change. ++package grpcnaming ++ ++// Operation defines the corresponding operations for a name resolution change. ++// ++// Deprecated: please use package resolver. ++type Operation uint8 ++ ++const ( ++ // Add indicates a new address is added. ++ Add Operation = iota ++ // Delete indicates an existing address is deleted. ++ Delete ++) ++ ++// Update defines a name resolution update. Notice that it is not valid having both ++// empty string Addr and nil Metadata in an Update. ++// ++// Deprecated: please use package resolver. ++type Update struct { ++ // Op indicates the operation of the update. ++ Op Operation ++ // Addr is the updated address. It is empty string if there is no address update. ++ Addr string ++ // Metadata is the updated metadata. It is nil if there is no metadata update. ++ // Metadata is not required for a custom naming implementation. ++ Metadata interface{} ++} ++ ++// Resolver creates a Watcher for a target to track its resolution changes. ++// ++// Deprecated: please use package resolver. ++type Resolver interface { ++ // Resolve creates a Watcher for target. ++ Resolve(target string) (Watcher, error) ++} ++ ++// Watcher watches for the updates on the specified target. ++// ++// Deprecated: please use package resolver. ++type Watcher interface { ++ // Next blocks until an update or error happens. It may return one or more ++ // updates. The first call should get the full set of the results. It should ++ // return an error if and only if Watcher cannot recover. ++ Next() ([]*Update, error) ++ // Close closes the Watcher. ++ Close() ++} +\ No newline at end of file +diff --git a/proxy/grpcproxy/cluster.go b/proxy/grpcproxy/cluster.go +index 5f3ab76584..a786457a6a 100644 +--- a/proxy/grpcproxy/cluster.go ++++ b/proxy/grpcproxy/cluster.go +@@ -18,6 +18,7 @@ import ( + "context" + "errors" + "fmt" ++ gnaming "go.etcd.io/etcd/clientv3/naming/grpcnaming" + "os" + "sync" + +@@ -27,7 +28,6 @@ import ( + pb "go.etcd.io/etcd/etcdserver/etcdserverpb" + + "golang.org/x/time/rate" +- gnaming "google.golang.org/grpc/naming" + ) + + // allow maximum 1 retry per second +diff --git a/proxy/grpcproxy/register.go b/proxy/grpcproxy/register.go +index e74cd5ca90..912e147d77 100644 +--- a/proxy/grpcproxy/register.go ++++ b/proxy/grpcproxy/register.go +@@ -16,6 +16,7 @@ package grpcproxy + + import ( + "encoding/json" ++ gnaming "go.etcd.io/etcd/clientv3/naming/grpcnaming" + "os" + + "go.etcd.io/etcd/clientv3" +@@ -23,7 +24,6 @@ import ( + "go.etcd.io/etcd/clientv3/naming" + + "golang.org/x/time/rate" +- gnaming "google.golang.org/grpc/naming" + ) + + // allow maximum 1 retry per second +From b1d600ee05737adf6fc2ba3a5c3d92c1037bb6a6 Mon Sep 17 00:00:00 2001 +From: Sky Ao +Date: Thu, 22 Oct 2020 11:20:17 +0800 +Subject: [PATCH 3/4] add doc for method ResolveError() + +--- + clientv3/balancer/balancer.go | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/clientv3/balancer/balancer.go b/clientv3/balancer/balancer.go +index d3e672c632..1488580331 100644 +--- a/clientv3/balancer/balancer.go ++++ b/clientv3/balancer/balancer.go +@@ -140,6 +140,7 @@ type baseBalancer struct { + resolverErr error // the last error reported by the resolver; cleared on successful resolution + } + ++// ResolverError implements "grpc/balancer.Balancer" interface. + func (bb *baseBalancer) ResolverError(err error) { + bb.resolverErr = err + if len(bb.addrToSc) == 0 { + +From 5ba58f2283eda7247f51b4e9dd07c367c4d77235 Mon Sep 17 00:00:00 2001 +From: Sky Ao +Date: Thu, 22 Oct 2020 11:36:03 +0800 +Subject: [PATCH 4/4] update to pass fmt checking + +--- + clientv3/naming/grpcnaming/naming.go | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/clientv3/naming/grpcnaming/naming.go b/clientv3/naming/grpcnaming/naming.go +index 9b1f20cc61..a4415a6541 100644 +--- a/clientv3/naming/grpcnaming/naming.go ++++ b/clientv3/naming/grpcnaming/naming.go +@@ -19,11 +19,6 @@ + // Package naming defines the naming API and related data structures for gRPC. + // + // This package is deprecated: please use package resolver instead. +- +- +-// Notice: this file is a copy of naming/naming.go from grpc-go v1.29.1. +-// The package of grpc naming is removed since grpc-go v1.30.0. +-// This is a work around to make etcd work with grpc new version (>=v1.30.0) without too many code change. + package grpcnaming + + // Operation defines the corresponding operations for a name resolution change. +@@ -70,4 +65,4 @@ type Watcher interface { + Next() ([]*Update, error) + // Close closes the Watcher. + Close() +-} +\ No newline at end of file ++} diff --git a/SOURCES/README.md b/SOURCES/README.md new file mode 100644 index 0000000..d2992b9 --- /dev/null +++ b/SOURCES/README.md @@ -0,0 +1,18 @@ +etcdctl*.1 to etcdctl3*.1 + +for line in $(ls *.1); do mv $line $(echo $line | sed "s/etcdctl/etcdctl3/"); done + +rename refs in man pages + +sed -i "s/\\\fBetcdctl\\\-/\\\fBetcdctl3\\\-/g" *.1 + +sed -i s"/^etcdctl/ETCDCTL=3 etcdctl/" etcdctl3*.1 + +etcdctl*.1 to etcdctl2*.1 + +for line in $(ls *.1); do mv $line $(echo $line | sed "s/etcdctl/etcdctl3/"); done + +rename refs in man pages + +sed -i "s/\\\fBetcdctl-/\\\fBetcdctl2-/g" *.1 + diff --git a/SOURCES/bz1350875-disaster-recovery-with-copies.patch b/SOURCES/bz1350875-disaster-recovery-with-copies.patch new file mode 100644 index 0000000..ca64473 --- /dev/null +++ b/SOURCES/bz1350875-disaster-recovery-with-copies.patch @@ -0,0 +1,56 @@ +From 7ad700a716c2122c3b6db6677a6f717919b88926 Mon Sep 17 00:00:00 2001 +From: Jan Chaloupka +Date: Tue, 2 May 2017 09:56:02 +0200 +Subject: [PATCH] bz1350875-disaster-recovery-with-copies: + +--- + etcdctl/ctlv2/command/backup_command.go | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/etcdctl/ctlv2/command/backup_command.go b/etcdctl/ctlv2/command/backup_command.go +index feda4b1..e77791f 100644 +--- a/etcdctl/ctlv2/command/backup_command.go ++++ b/etcdctl/ctlv2/command/backup_command.go +@@ -18,6 +18,7 @@ import ( + "fmt" + "log" + "path/filepath" ++ "strconv" + "time" + + "github.com/coreos/etcd/etcdserver/etcdserverpb" +@@ -40,6 +41,9 @@ func NewBackupCommand() cli.Command { + cli.StringFlag{Name: "wal-dir", Value: "", Usage: "Path to the etcd wal dir"}, + cli.StringFlag{Name: "backup-dir", Value: "", Usage: "Path to the backup dir"}, + cli.StringFlag{Name: "backup-wal-dir", Value: "", Usage: "Path to the backup wal dir"}, ++ cli.BoolFlag{Name: "keep-cluster-id", Usage: "Do not rewrite the cluster id"}, ++ cli.StringFlag{Name: "node-id", Value: "", Usage: "Use custom node id instead of a random value"}, ++ + }, + Action: handleBackup, + } +@@ -99,8 +103,19 @@ func handleBackup(c *cli.Context) error { + var metadata etcdserverpb.Metadata + pbutil.MustUnmarshal(&metadata, wmetadata) + idgen := idutil.NewGenerator(0, time.Now()) +- metadata.NodeID = idgen.Next() +- metadata.ClusterID = idgen.Next() ++ explicitNodeId := c.String("node-id") ++ if explicitNodeId != "" { ++ metadata.NodeID, err = strconv.ParseUint(explicitNodeId, 16, 64) ++ if err != nil { ++ log.Fatal(err) ++ } ++ } else { ++ metadata.NodeID = idgen.Next() ++ } ++ keepClusterId := c.Bool("keep-cluster-id") ++ if !keepClusterId { ++ metadata.ClusterID = idgen.Next() ++ } + + neww, err := wal.Create(destWAL, pbutil.MustMarshal(&metadata)) + if err != nil { +-- +2.7.4 + diff --git a/SOURCES/etcd.conf b/SOURCES/etcd.conf index bd091f5..6f90c25 100644 --- a/SOURCES/etcd.conf +++ b/SOURCES/etcd.conf @@ -1,34 +1,51 @@ -# This configuration file is written in [TOML](https://github.com/mojombo/toml) - -# addr = "127.0.0.1:4001" -# bind_addr = "127.0.0.1:4001" -# ca_file = "" -# cert_file = "" -# cors = [] -# cpu_profile_file = "" -data_dir = "/var/lib/etcd/default.etcd/" -# discovery = "http://etcd.local:4001/v2/keys/_etcd/registry/examplecluster" -# http_read_timeout = 10 -# http_write_timeout = 10 -# key_file = "" -# peers = [] -# peers_file = "" -# max_cluster_size = 9 -# max_result_buffer = 1024 -# max_retry_attempts = 3 -name = "default" -# snapshot = false -# verbose = false -# very_verbose = false - -# [peer] -# addr = "127.0.0.1:7001" -# bind_addr = "127.0.0.1:7001" -# ca_file = "" -# cert_file = "" -# key_file = "" - -# [cluster] -# active_size = 9 -# remove_delay = 1800.0 -# sync_interval = 5.0 +# [member] +ETCD_NAME=default +ETCD_DATA_DIR="/var/lib/etcd/default.etcd" +#ETCD_WAL_DIR="" +#ETCD_SNAPSHOT_COUNT="10000" +#ETCD_HEARTBEAT_INTERVAL="100" +#ETCD_ELECTION_TIMEOUT="1000" +#ETCD_LISTEN_PEER_URLS="http://localhost:2380" +ETCD_LISTEN_CLIENT_URLS="http://localhost:2379" +#ETCD_MAX_SNAPSHOTS="5" +#ETCD_MAX_WALS="5" +#ETCD_CORS="" +# +#[cluster] +#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380" +# if you use different ETCD_NAME (e.g. test), set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..." +#ETCD_INITIAL_CLUSTER="default=http://localhost:2380" +#ETCD_INITIAL_CLUSTER_STATE="new" +#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" +ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379" +#ETCD_DISCOVERY="" +#ETCD_DISCOVERY_SRV="" +#ETCD_DISCOVERY_FALLBACK="proxy" +#ETCD_DISCOVERY_PROXY="" +#ETCD_STRICT_RECONFIG_CHECK="false" +#ETCD_AUTO_COMPACTION_RETENTION="0" +# +#[proxy] +#ETCD_PROXY="off" +#ETCD_PROXY_FAILURE_WAIT="5000" +#ETCD_PROXY_REFRESH_INTERVAL="30000" +#ETCD_PROXY_DIAL_TIMEOUT="1000" +#ETCD_PROXY_WRITE_TIMEOUT="5000" +#ETCD_PROXY_READ_TIMEOUT="0" +# +#[security] +#ETCD_CERT_FILE="" +#ETCD_KEY_FILE="" +#ETCD_CLIENT_CERT_AUTH="false" +#ETCD_TRUSTED_CA_FILE="" +#ETCD_AUTO_TLS="false" +#ETCD_PEER_CERT_FILE="" +#ETCD_PEER_KEY_FILE="" +#ETCD_PEER_CLIENT_CERT_AUTH="false" +#ETCD_PEER_TRUSTED_CA_FILE="" +#ETCD_PEER_AUTO_TLS="false" +# +#[logging] +#ETCD_DEBUG="false" +# examples for -log-package-levels etcdserver=WARNING,security=DEBUG +#ETCD_LOG_PACKAGE_LEVELS="" diff --git a/SOURCES/etcd.service b/SOURCES/etcd.service index fd5733c..c9c3afe 100644 --- a/SOURCES/etcd.service +++ b/SOURCES/etcd.service @@ -1,14 +1,18 @@ [Unit] Description=Etcd Server After=network.target +After=network-online.target +Wants=network-online.target [Service] -Type=simple -# etc logs to the journal directly, suppress double logging -StandardOutput=null -WorkingDirectory=/var/lib/etcd +Type=notify +WorkingDirectory=/var/lib/etcd/ +EnvironmentFile=-/etc/etcd/etcd.conf User=etcd -ExecStart=/usr/bin/etcd +# set GOMAXPROCS to number of processors +ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd" +Restart=on-failure +LimitNOFILE=65536 [Install] WantedBy=multi-user.target diff --git a/SOURCES/etcdctl.1 b/SOURCES/etcdctl.1 new file mode 100644 index 0000000..bec2361 --- /dev/null +++ b/SOURCES/etcdctl.1 @@ -0,0 +1,25 @@ +.TH "ETCD" "1" " etcd User Manuals" "Jan Chaloupka" "Oct 2017" "" + + +.SH NAME +.PP +etcdctl \- A simple command line client for etcd + + +.SH SYNOPSIS +.PP +\fB[ETCDCTL_API=3] etctctl\fP [OPTIONS] + + +.SH DESCRIPTION +.PP +Command line client for etcd. +Queries to v2 data model are available through \fBetcdtl\fP command (see \fBetcdctl2(1)\fP). +Queries to v3 data model are available through \fBETCDCTL=3 etcdtl\fP command (see \fBetcdctl3(1)\fP). + +.PP +Find more information at +\[la]https://github.com/coreos/etcd\[ra]. + +.SH SEE ALSO +\fBetcd(1)\fP, \fBetcdctl2(1)\fP, \fBetcdctl3(1)\fP diff --git a/SOURCES/expand-etcd-arch-validation.patch b/SOURCES/expand-etcd-arch-validation.patch new file mode 100644 index 0000000..d6c4fba --- /dev/null +++ b/SOURCES/expand-etcd-arch-validation.patch @@ -0,0 +1,30 @@ +From b3e78645c1ffa84bcde511c90df4e3dde652c3fa Mon Sep 17 00:00:00 2001 +From: Jan Chaloupka +Date: Tue, 8 Aug 2017 15:01:04 +0200 +Subject: [PATCH] expand etcd arch validation + +--- + etcdmain/etcd.go | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/etcdmain/etcd.go b/etcdmain/etcd.go +index 2f7f00d..61553d4 100644 +--- a/etcdmain/etcd.go ++++ b/etcdmain/etcd.go +@@ -396,6 +396,13 @@ func checkSupportArch() { + if runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64le" { + return + } ++ ++ if runtime.GOARCH == "arm64" || runtime.GOARCH == "s390x" { ++ plog.Warningf("Running etcd on %s architecture is experimental.", runtime.GOARCH) ++ plog.Warningf("Please report any bugs you encounter: https://bugzilla.redhat.com/") ++ return ++ } ++ + if env, ok := os.LookupEnv("ETCD_UNSUPPORTED_ARCH"); ok && env == runtime.GOARCH { + plog.Warningf("running etcd on unsupported architecture %q since ETCD_UNSUPPORTED_ARCH is set", env) + return +-- +2.7.5 + diff --git a/SOURCES/genmanpages.sh b/SOURCES/genmanpages.sh new file mode 100755 index 0000000..a933c40 --- /dev/null +++ b/SOURCES/genmanpages.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +rm -rf man +mkdir -p man/etcdctl2 man/etcdctl3 +pushd man/etcdctl3 +ETCDCTL_API=3 ../../$1/bin/etcdctl --help + +# rename to etcdctl3... +for line in $(ls *.1); do mv $line $(echo $line | sed "s/etcdctl/etcdctl3/"); done + +# rename refs +sed -i "s/\\\fBetcdctl\\\-/\\\fBetcdctl3\\\-/g" *.1 + +# stress ETCDCTL_API use +sed -i s"/^\\\fBetcdctl /\\\fBETCDCTL=3 etcdctl /" etcdctl3*.1 + +cd ../etcdctl2 +../../$1/bin/etcdctl --help > etcdctl.1 + +for cmd in $(cat etcdctl.1 | grep "\fBetcdctl\\\-" | cut -d'-' -f2-3 | cut -d'(' -f1); do ../../$1/bin/etcdctl $cmd --help > etcdctl-$cmd.1; done + +# rename to etcdctl2 +for line in $(ls *.1); do mv $line $(echo $line | sed "s/etcdctl/etcdctl2/"); done + +# rename refs +sed -i "s/\\\fBetcdctl\\\-/\\\fBetcdctl2\\\-/g" *.1 + +cd .. +mv etcdctl2/* . +mv etcdctl3/* . +rm -rf etcdctl2 etcdctl3 +cp ../etcdctl.1 . + +# Gen etcd.1 +../$1/bin/etcd --help > etcd.1 diff --git a/SOURCES/man-3.4.14.tar.gz b/SOURCES/man-3.4.14.tar.gz new file mode 100644 index 0000000..8749cb4 Binary files /dev/null and b/SOURCES/man-3.4.14.tar.gz differ diff --git a/SPECS/etcd.spec b/SPECS/etcd.spec index 05a4f93..b971ec7 100644 --- a/SPECS/etcd.spec +++ b/SPECS/etcd.spec @@ -1,31 +1,49 @@ -%global debug_package %{nil} - -%global provider github -%global provider_tld com -%global project coreos -%global repo etcd -%global commit 4f330a9ba2097222a9add8136115f3a670dd0642 - -%global import_path %{provider}.%{provider_tld}/%{project}/%{repo} -%global gopath %{_datadir}/gocode -%global shortcommit %(c=%{commit}; echo ${c:0:7}) - +%global with_debug 1 + +%if 0%{?with_debug} +%global _dwz_low_mem_die_limit 0 +%else +%global debug_package %{nil} +%endif + +%if ! 0%{?gobuild:1} +%define gobuild(o:) go build -buildmode pie -tags=rpm_crashtraceback -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '-Wl,-z,relro,-z,now'" -a -v -x %{?**}; +%endif + +%global provider github +%global provider_tld com +%global project etcd-io +%global repo etcd +# https://github.com/etcd-io/etcd +%global provider_prefix %{provider}.%{provider_tld}/%{project}/%{repo} +%global import_path %{provider_prefix} +%global commit 8a03d2e9614b8192ebaa5a25ef92f6ff62e3593c +%global shortcommit %(c=%{commit}; echo ${c:0:7}) + +%global system_name etcd +%global man_version 3.4.14 Name: etcd -Version: 0.4.6 -Release: 0.13%{?dist} +Version: 3.4.14 +Release: 1%{?dist} Summary: A highly-available key value store for shared configuration - License: ASL 2.0 -URL: https://github.com/coreos/etcd/ -Source0: https://github.com/coreos/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz -Source1: httpd://github.com/coreos/etcdctl/archive/v%{version}/etcdctl-%{version}.tar.gz -Source2: etcd.service -Source3: etcd.conf +URL: https://%{provider_prefix} +Source0: https://%{provider_prefix}/archive/%{commit}/%{repo}-%{shortcommit}.tar.gz +Source1: %{system_name}.service +Source2: %{system_name}.conf +Source3: man-%{man_version}.tar.gz + +# e.g. el6 has ppc64 arch without gcc-go, so EA tag is required +ExclusiveArch: %{?go_arches:%{go_arches}}%{!?go_arches:x86_64 aarch64 ppc64le s390x} +# If go_compiler is not set to 1, there is no virtual provide. Use golang instead. +BuildRequires: %{?go_compiler:compiler(go-compiler)}%{!?go_compiler:golang} -ExclusiveArch: x86_64 +Obsoletes: etcd3 < 3.0.15 +Provides: etcd3 = %{version}-%{release} + +BuildRequires: libpcap-devel -BuildRequires: golang BuildRequires: systemd Requires(pre): shadow-utils @@ -36,116 +54,223 @@ Requires(postun): systemd %description A highly-available key value store for shared configuration. +%{?enable_gotoolset7} + %prep -%setup -q -n %{name}-%{version} -a 1 +%setup -q -n man-%{man_version} -T -b 3 +%setup -q -n %{repo}-%{commit} +mkdir -p man/man1 +cp ../man-%{man_version}/*.1 man/man1/. + +# move content of vendor under Godeps as has been so far +mkdir -p Godeps/_workspace/src +mv vendor/* Godeps/_workspace/src/. %build -./build -cd etcdctl-%{version} -./build +mkdir -p src/github.com/etcd-io +ln -s ../../../ src/github.com/etcd-io/etcd +mkdir -p src/go.etcd.io +ln -s ../../ src/go.etcd.io/etcd -%install +export GOPATH=$(pwd):$(pwd)/Godeps/_workspace:%{gopath} -install -d -m 0755 %{buildroot}%{_sysconfdir}/etcd -install -m 644 -t %{buildroot}%{_sysconfdir}/etcd %{SOURCE3} -install -D -p -m 0755 bin/etcd %{buildroot}%{_bindir}/etcd -install -D -p -m 0644 %{SOURCE2} %{buildroot}%{_unitdir}/%{name}.service +export LDFLAGS="-X %{import_path}/version.GitSHA=%{shortcommit} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \n')" -# And create /var/lib/etcd -install -d -m 0755 %{buildroot}%{_localstatedir}/lib/etcd +%gobuild -o bin/%{system_name} %{import_path} +%gobuild -o bin/%{system_name}ctl %{import_path}/%{system_name}ctl -install -D -p -m 0755 etcdctl-%{version}/bin/etcdctl %{buildroot}%{_bindir}/etcdctl +%install +install -D -p -m 0755 bin/%{system_name} %{buildroot}%{_bindir}/%{system_name} +install -D -p -m 0755 bin/%{system_name}ctl %{buildroot}%{_bindir}/%{system_name}ctl +install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_unitdir}/%{system_name}.service +install -d -m 0755 %{buildroot}%{_sysconfdir}/%{system_name} +install -m 644 -t %{buildroot}%{_sysconfdir}/%{system_name} %{SOURCE2} -%check -# empty for now +# install manpages +install -d %{buildroot}%{_mandir}/man1 +install -p -m 644 man/man1/* %{buildroot}%{_mandir}/man1 + +# And create /var/lib/etcd +install -d -m 0755 %{buildroot}%{_sharedstatedir}/%{system_name} %pre -getent group etcd >/dev/null || groupadd -r etcd -getent passwd etcd >/dev/null || useradd -r -g etcd -d %{_localstatedir}/lib/etcd \ - -s /sbin/nologin -c "etcd user" etcd +getent group %{system_name} >/dev/null || groupadd -r %{system_name} +getent passwd %{system_name} >/dev/null || useradd -r -g %{system_name} -d %{_sharedstatedir}/%{system_name} \ + -s /sbin/nologin -c "etcd user" %{system_name} + %post -%systemd_post %{name}.service +%systemd_post %{system_name}.service %preun -%systemd_preun %{name}.service +%systemd_preun %{system_name}.service %postun -%systemd_postun %{name}.service +%systemd_postun %{system_name}.service + +#define license tag if not already defined +%{!?_licensedir:%global license %doc} %files -%config(noreplace) %{_sysconfdir}/etcd -%{_bindir}/etcd -%{_bindir}/etcdctl -%dir %attr(-,etcd,etcd) %{_localstatedir}/lib/etcd -%{_unitdir}/%{name}.service -%doc LICENSE README.md Documentation/internal-protocol-versioning.md +%license LICENSE +%doc *.md +%config(noreplace) %{_sysconfdir}/%{system_name} +%{_bindir}/%{system_name} +%{_bindir}/%{system_name}ctl +%dir %attr(-,%{system_name},%{system_name}) %{_sharedstatedir}/%{system_name} +%{_unitdir}/%{system_name}.service +%{_mandir}/man1/*.1* %changelog -* Tue Jan 27 2015 Eric Paris - 0.4.6-0.13 -- build and include etcdctl -- return etcd tarball to sources - resolves: #1186439 +* Thu May 20 2021 Joel Capitao - 3.4.14-1 +- Update to 3.4.14 + +* Wed Mar 06 2019 Lon Hohberger - 3.2.21-2 +- Rebuild for new architectures + +* Mon Jun 04 2018 Jan Chaloupka - 3.2.21-1 +- Update to 3.2.21 + resolves: #1585787 + +* Tue Apr 17 2018 Jan Chaloupka - 3.2.18-1 +- Update to 3.2.18 + resolves: #1568389 + +* Tue Feb 06 2018 Jan Chaloupka - 3.2.15-2 +- Rebuild for 7.5.0 + resolves: #1542526 + +* Mon Jan 29 2018 Jan Chaloupka - 3.2.15-1 +- Update to 3.2.15 + resolves: #1539670 + resolves: #1378706 + +* Wed Dec 06 2017 Jan Chaloupka - 3.2.11-1 +- Update to 3.2.11 + related: #1514612 + +* Tue Nov 21 2017 Jan Chaloupka - 3.2.10-1 +- Update to 3.2.10 + resolves: #1514612 + +* Mon Nov 20 2017 Jan Chaloupka - 3.2.9-3 +- Bump man-pages tarball + related: #1510480 + +* Mon Nov 20 2017 Jan Chaloupka - 3.2.9-2 +- Fix Synopsis of etcdctl3 man pages + related: #1510480 + +* Tue Nov 07 2017 Jan Chaloupka - 3.2.9-1 +- Update to 3.2.9 + resolves: #1510480 +- Generate etcd and etcdctl man-pages + resolves: #1444336 + +* Fri Sep 29 2017 Jan Chaloupka - 3.2.7-2 +- Rebuild with correct hardening flags + resolves: #1420783 + +* Tue Sep 19 2017 Jan Chaloupka - 3.2.7-1 +- Update to 3.2.7 + resolves: #1493165 + +* Tue Aug 08 2017 Jan Chaloupka - 3.2.5-1 +- Update to 3.2.5 + resolves: #1479371 + +* Mon Jun 12 2017 Jan Chaloupka - 3.1.9-2 +- Build for secondary architectures as well + +* Fri Jun 09 2017 Scott Dodson - 3.1.9-1 +- Update to 3.1.9 + resolves: #1458941 + +* Tue Jun 06 2017 Jan Chaloupka - 3.1.8-1 +- Update to 3.1.8 + resolves: #1459122 + +* Tue May 02 2017 Jan Chaloupka - 3.1.7-1 +- Update to 3.1.7 + resolves: #1447235 + +* Tue Apr 04 2017 Yaakov Selkowitz - 3.1.3-2 +- Circumvent runtime check of officially supported architectures + resolves: #1434973 + +* Tue Mar 21 2017 Jan Chaloupka - 3.1.3-1 +- Update to 3.1.3 + resolves: #1434364 + +* Mon Feb 27 2017 Josh Boyer - 3.1.0-2.1 +- Rebuild rebase on all architectures + +* Tue Feb 21 2017 Jan Chaloupka - 3.1.0-2 +- Apply "add --keep-cluster-id and --node-id to 'etcdctl backup'" + from extras-rhel-7.2 branch + resolves: #1350875 -* Wed Jan 21 2015 Eric Paris - 0.4.6-0.12 -- set config to use /var/lib/etcd/default.etcd/ for storeage (like 2.0 will use) +* Thu Feb 16 2017 Josh Boyer - 3.1.0-1.1 +- Rebuild rebase on all architectures -* Mon Oct 06 2014 jchaloup - 0.4.6-0.11 -- back to 0.4.6 version +* Mon Feb 06 2017 Jan Chaloupka - 3.1.0-1 +- Update to 3.1.0 + etcdctl-top removed by upstream + resolves: #1416440 -* Mon Oct 06 2014 jchaloup - 0.4.6-0.10.git4f330a9 -- replace BuildArch with ExclusiveArch +* Fri Jan 20 2017 d.marlin +- Build for all archs (adding ppc64le and s390x) -* Sun Oct 05 2014 Eric Paris - 0.4.6-0.9.git378cadf -- Fix the .service file to it can launch! +* Tue Jan 10 2017 d.marlin +- Add aarch64 to ExclusiveArch list. -* Fri Oct 03 2014 jchaloup - 0.4.6-0.8.git378cadf -- Bump to upstream 4f330a9ba2097222a9add8136115f3a670dd0642 -- the last commit before golang-cover (not in rhel7.1 so far) +* Mon Jan 09 2017 d.marlin +- Correct 'link' warning for -X flag. -* Thu Oct 02 2014 jchaloup - 0.4.6-7 -- upstream commit to fix the bug caused by random iteration order over map in store/store_test.go -- upstrema commit cc1df691cc7e752f1589fe796b7c1d589316a96f +* Thu Dec 01 2016 jchaloup - 3.0.15-1 +- Update to 3.0.15 + Obsolete etcd3 < 3.0.15 -* Thu Oct 02 2014 jchaloup - 0.4.6-6 -- removing devel part in install section +* Fri Nov 18 2016 jchaloup - 3.0.14-3 +- Build with debug-info subpackage +- Until etcd3 obsoletes etcd it conflicts with it -* Thu Oct 02 2014 Eric Paris - 0.4.6-5 -- Clean up prep and build section +* Tue Nov 15 2016 Avesh Agarwal - 3.0.14-2 +- Resolves: #1395359 etcd3 should not obsolete etcd -* Mon Sep 22 2014 jchaloup - 0.4.6-4 -- resolves: #1047194 - Update to 0.4.6 from https://github.com/projectatomic/etcd-package +* Mon Nov 07 2016 jchaloup - 3.0.14-1 +- Update to v3.0.14 + related: #1386963 -* Tue Aug 19 2014 Adam Miller - 0.4.6-3 -- Add devel sub-package +* Thu Oct 27 2016 jchaloup - 3.0.13-1 +- Update to v3.0.13 + related: #1386963 -* Wed Aug 13 2014 Eric Paris - 0.4.6-2 -- Bump to 0.4.6 -- run as etcd, not root +* Fri Oct 21 2016 jchaloup - 3.0.12-3 +- etcdctl: fix migrate in outputing client.Node to json + resolves: #1386963 -* Sat Jun 07 2014 Fedora Release Engineering - 0.1.2-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild +* Tue Oct 18 2016 jchaloup - 3.0.12-2 +- Replace etcd with etcd3 when upgrading + resolves: #1384161 -* Sun Oct 20 2013 Peter Lemenkov - 0.1.2-5 -- goprotobuf library unbundled (see rhbz #1018477) -- go-log library unbundled (see rhbz #1018478) -- go-raft library unbundled (see rhbz #1018479) -- go-systemd library unbundled (see rhbz #1018480) -- kardianos library unbundled (see rhbz #1018481) +* Thu Oct 13 2016 jchaloup - 3.0.12-1 +- Update to v3.0.12 -* Sun Oct 13 2013 Peter Lemenkov - 0.1.2-4 -- go.net library unbundled (see rhbz #1018476) +* Thu Oct 06 2016 jchaloup - 3.0.10-1 +- Update to v3.0.10 -* Sat Oct 12 2013 Peter Lemenkov - 0.1.2-3 -- Prepare for packages unbundling -- Verbose build +* Fri Sep 23 2016 jchaloup - 3.0.3-2 +- Extend etcd.conf with new flags + resolves: #1378706 -* Sat Oct 12 2013 Peter Lemenkov - 0.1.2-2 -- Fix typo in the etc.service file +* Fri Jul 22 2016 jchaloup - 3.0.2-1 +- Update to v3.0.3 + related: #1347499 -* Sat Oct 12 2013 Peter Lemenkov - 0.1.2-1 -- Ver. 0.1.2 -- Integrate with systemd +* Tue Jul 12 2016 jchaloup - 3.0.2-1 +- Update to v3.0.2 + related: #1347499 -* Mon Aug 26 2013 Luke Cypret - 0.1.1-1 -- Initial creation +* Sun May 15 2016 jchaloup - 3.0.0-0.1.beta0 +- Build etcd3 v3.0.0-beta0 for AH 7.3 + resolves: #1347499