Blob Blame History Raw
From 81519130b0abec199ddc9e3559e64884742b1bf5 Mon Sep 17 00:00:00 2001
From: Jan Chaloupka <jchaloup@redhat.com>
Date: Tue, 7 Nov 2017 14:04:01 +0100
Subject: [PATCH] hack etcdmain to generate etcd.1

---
 etcdmain/config.go       |  25 ++++----
 etcdmain/fake_flagset.go | 157 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+), 11 deletions(-)
 create mode 100644 etcdmain/fake_flagset.go

diff --git a/etcdmain/config.go b/etcdmain/config.go
index b873220..4770334 100644
--- a/etcdmain/config.go
+++ b/etcdmain/config.go
@@ -118,14 +118,14 @@ func newConfig() *config {
 		),
 	}
 
-	fs := cfg.FlagSet
-	fs.Usage = func() {
+	fs := InitFlagSet(cfg.FlagSet)
+	cfg.FlagSet.Usage = func() {
 		fmt.Fprintln(os.Stderr, usageline)
 	}
 
 	fs.StringVar(&cfg.configFile, "config-file", "", "Path to the server configuration file")
 
-	// member
+	fs.AddGroup("member")
 	fs.Var(cfg.CorsInfo, "cors", "Comma-separated white list of origins for CORS (cross-origin resource sharing).")
 	fs.StringVar(&cfg.Dir, "data-dir", cfg.Dir, "Path to the data directory.")
 	fs.StringVar(&cfg.WalDir, "wal-dir", cfg.WalDir, "Path to the dedicated wal directory.")
@@ -139,7 +139,7 @@ func newConfig() *config {
 	fs.UintVar(&cfg.ElectionMs, "election-timeout", cfg.ElectionMs, "Time (in milliseconds) for an election to timeout.")
 	fs.Int64Var(&cfg.QuotaBackendBytes, "quota-backend-bytes", cfg.QuotaBackendBytes, "Raise alarms when backend size exceeds the given quota. 0 means use the default quota.")
 
-	// clustering
+	fs.AddGroup("clustering")
 	fs.Var(flags.NewURLsValue(embed.DefaultInitialAdvertisePeerURLs), "initial-advertise-peer-urls", "List of this member's peer URLs to advertise to the rest of the cluster.")
 	fs.Var(flags.NewURLsValue(embed.DefaultAdvertiseClientURLs), "advertise-client-urls", "List of this member's client URLs to advertise to the public.")
 	fs.StringVar(&cfg.Durl, "discovery", cfg.Durl, "Discovery URL used to bootstrap the cluster.")
@@ -160,7 +160,7 @@ func newConfig() *config {
 	fs.BoolVar(&cfg.StrictReconfigCheck, "strict-reconfig-check", cfg.StrictReconfigCheck, "Reject reconfiguration requests that would cause quorum loss.")
 	fs.BoolVar(&cfg.EnableV2, "enable-v2", true, "Accept etcd V2 client requests.")
 
-	// proxy
+	fs.AddGroup("proxy")
 	fs.Var(cfg.proxy, "proxy", fmt.Sprintf("Valid values include %s", strings.Join(cfg.proxy.Values, ", ")))
 	if err := cfg.proxy.Set(proxyFlagOff); err != nil {
 		// Should never happen.
@@ -172,7 +172,7 @@ func newConfig() *config {
 	fs.UintVar(&cfg.ProxyWriteTimeoutMs, "proxy-write-timeout", cfg.ProxyWriteTimeoutMs, "Time (in milliseconds) for a write to timeout.")
 	fs.UintVar(&cfg.ProxyReadTimeoutMs, "proxy-read-timeout", cfg.ProxyReadTimeoutMs, "Time (in milliseconds) for a read to timeout.")
 
-	// security
+	fs.AddGroup("security")
 	fs.StringVar(&cfg.ClientTLSInfo.CAFile, "ca-file", "", "DEPRECATED: Path to the client server TLS CA file.")
 	fs.StringVar(&cfg.ClientTLSInfo.CertFile, "cert-file", "", "Path to the client server TLS cert file.")
 	fs.StringVar(&cfg.ClientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
@@ -186,28 +186,31 @@ func newConfig() *config {
 	fs.StringVar(&cfg.PeerTLSInfo.TrustedCAFile, "peer-trusted-ca-file", "", "Path to the peer server TLS trusted CA file.")
 	fs.BoolVar(&cfg.PeerAutoTLS, "peer-auto-tls", false, "Peer TLS using generated certificates")
 
-	// logging
+	fs.AddGroup("logging")
 	fs.BoolVar(&cfg.Debug, "debug", false, "Enable debug-level logging for etcd.")
 	fs.StringVar(&cfg.LogPkgLevels, "log-package-levels", "", "Specify a particular log level for each etcd package (eg: 'etcdmain=CRITICAL,etcdserver=DEBUG').")
 	fs.StringVar(&cfg.logOutput, "log-output", "default", "Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd.")
 
-	// unsafe
+	fs.AddGroup("unsafe")
 	fs.BoolVar(&cfg.ForceNewCluster, "force-new-cluster", false, "Force to create a new one member cluster.")
 
-	// version
+	fs.AddGroup("version")
 	fs.BoolVar(&cfg.printVersion, "version", false, "Print the version and exit.")
 
 	fs.IntVar(&cfg.AutoCompactionRetention, "auto-compaction-retention", 0, "Auto compaction retention for mvcc key value store in hour. 0 means disable auto compaction.")
 
-	// pprof profiler via HTTP
+	fs.AddGroup("profiling")
 	fs.BoolVar(&cfg.EnablePprof, "enable-pprof", false, "Enable runtime profiling data via HTTP server. Address is at client URL + \"/debug/pprof/\"")
 
 	// additional metrics
 	fs.StringVar(&cfg.Metrics, "metrics", cfg.Metrics, "Set level of detail for exported metrics, specify 'extensive' to include histogram metrics")
 
-	// auth
+	fs.AddGroup("auth")
 	fs.StringVar(&cfg.AuthToken, "auth-token", cfg.AuthToken, "Specify auth token specific options.")
 
+	fs.GenMan()
+	os.Exit(0)
+
 	// ignored
 	for _, f := range cfg.ignored {
 		fs.Var(&flags.IgnoredFlag{Name: f}, f, "")
diff --git a/etcdmain/fake_flagset.go b/etcdmain/fake_flagset.go
new file mode 100644
index 0000000..71f230b
--- /dev/null
+++ b/etcdmain/fake_flagset.go
@@ -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")
+}
-- 
2.7.5