update repo
This commit is contained in:
39
traefik/traefik-certs-dumper/cmd/boltdb.go
Normal file
39
traefik/traefik-certs-dumper/cmd/boltdb.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/boltdb"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper/kv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// boltdbCmd represents the boltdb command
|
||||
var boltdbCmd = &cobra.Command{
|
||||
Use: "boltdb",
|
||||
Short: "Dump the content of BoltDB.",
|
||||
Long: `Dump the content of BoltDB.`,
|
||||
RunE: runE(boltdbRun),
|
||||
}
|
||||
|
||||
func init() {
|
||||
kvCmd.AddCommand(boltdbCmd)
|
||||
|
||||
boltdbCmd.Flags().Bool("persist-connection", false, "Persist connection for boltdb.")
|
||||
boltdbCmd.Flags().String("bucket", "traefik", "Bucket for boltdb.")
|
||||
}
|
||||
|
||||
func boltdbRun(baseConfig *dumper.BaseConfig, cmd *cobra.Command) error {
|
||||
config, err := getKvConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Options.Bucket = cmd.Flag("bucket").Value.String()
|
||||
config.Options.PersistConnection, _ = cmd.Flags().GetBool("persist-connection")
|
||||
|
||||
config.Backend = store.BOLTDB
|
||||
boltdb.Register()
|
||||
|
||||
return kv.Dump(config, baseConfig)
|
||||
}
|
37
traefik/traefik-certs-dumper/cmd/consul.go
Normal file
37
traefik/traefik-certs-dumper/cmd/consul.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/consul"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper/kv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// consulCmd represents the consul command
|
||||
var consulCmd = &cobra.Command{
|
||||
Use: "consul",
|
||||
Short: "Dump the content of Consul.",
|
||||
Long: `Dump the content of Consul.`,
|
||||
RunE: runE(consulRun),
|
||||
}
|
||||
|
||||
func init() {
|
||||
kvCmd.AddCommand(consulCmd)
|
||||
|
||||
consulCmd.Flags().String("token", "", "Token for consul.")
|
||||
}
|
||||
|
||||
func consulRun(baseConfig *dumper.BaseConfig, cmd *cobra.Command) error {
|
||||
config, err := getKvConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Options.Token = cmd.Flag("token").Value.String()
|
||||
|
||||
config.Backend = store.CONSUL
|
||||
consul.Register()
|
||||
|
||||
return kv.Dump(config, baseConfig)
|
||||
}
|
20
traefik/traefik-certs-dumper/cmd/doc.go
Normal file
20
traefik/traefik-certs-dumper/cmd/doc.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
)
|
||||
|
||||
// docCmd represents the doc command
|
||||
var docCmd = &cobra.Command{
|
||||
Use: "doc",
|
||||
Short: "Generate documentation",
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return doc.GenMarkdownTree(rootCmd, "./docs")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(docCmd)
|
||||
}
|
43
traefik/traefik-certs-dumper/cmd/etcd.go
Normal file
43
traefik/traefik-certs-dumper/cmd/etcd.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/etcd/v2"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper/kv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// etcdCmd represents the etcd command
|
||||
var etcdCmd = &cobra.Command{
|
||||
Use: "etcd",
|
||||
Short: "Dump the content of etcd.",
|
||||
Long: `Dump the content of etcd.`,
|
||||
RunE: runE(etcdRun),
|
||||
}
|
||||
|
||||
func init() {
|
||||
kvCmd.AddCommand(etcdCmd)
|
||||
|
||||
etcdCmd.Flags().Int("sync-period", 0, "Sync period for etcd in seconds.")
|
||||
}
|
||||
|
||||
func etcdRun(baseConfig *dumper.BaseConfig, cmd *cobra.Command) error {
|
||||
config, err := getKvConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
synPeriod, err := cmd.Flags().GetInt("sync-period")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.Options.SyncPeriod = time.Duration(synPeriod) * time.Second
|
||||
|
||||
config.Backend = store.ETCD
|
||||
etcd.Register()
|
||||
|
||||
return kv.Dump(config, baseConfig)
|
||||
}
|
25
traefik/traefik-certs-dumper/cmd/file.go
Normal file
25
traefik/traefik-certs-dumper/cmd/file.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper/file"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// fileCmd represents the file command
|
||||
var fileCmd = &cobra.Command{
|
||||
Use: "file",
|
||||
Short: `Dump the content of the "acme.json" file.`,
|
||||
Long: `Dump the content of the "acme.json" file from Traefik to certificates.`,
|
||||
RunE: runE(func(baseConfig *dumper.BaseConfig, cmd *cobra.Command) error {
|
||||
acmeFile := cmd.Flag("source").Value.String()
|
||||
|
||||
return file.Dump(acmeFile, baseConfig)
|
||||
}),
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(fileCmd)
|
||||
|
||||
fileCmd.Flags().String("source", "./acme.json", "Path to 'acme.json' file.")
|
||||
}
|
174
traefik/traefik-certs-dumper/cmd/kv.go
Normal file
174
traefik/traefik-certs-dumper/cmd/kv.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper/kv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// kvCmd represents the kv command
|
||||
var kvCmd = &cobra.Command{
|
||||
Use: "kv",
|
||||
Short: `Dump the content of a KV store.`,
|
||||
Long: `Dump the content of a KV store.`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(kvCmd)
|
||||
|
||||
kvCmd.PersistentFlags().StringSlice("endpoints", []string{"localhost:8500"}, "List of endpoints.")
|
||||
kvCmd.PersistentFlags().Int("connection-timeout", 0, "Connection timeout in seconds.")
|
||||
kvCmd.PersistentFlags().String("prefix", "traefik", "Prefix used for KV store.")
|
||||
kvCmd.PersistentFlags().String("password", "", "Password for connection.")
|
||||
kvCmd.PersistentFlags().String("username", "", "Username for connection.")
|
||||
|
||||
kvCmd.PersistentFlags().Bool("tls", false, "Enable TLS encryption.")
|
||||
kvCmd.PersistentFlags().String("tls.ca", "", "Root CA for certificate verification if TLS is enabled")
|
||||
kvCmd.PersistentFlags().Bool("tls.ca.optional", false, "")
|
||||
kvCmd.PersistentFlags().String("tls.cert", "", "TLS cert")
|
||||
kvCmd.PersistentFlags().String("tls.key", "", "TLS key")
|
||||
kvCmd.PersistentFlags().Bool("tls.insecureskipverify", false, "Trust unverified certificates if TLS is enabled.")
|
||||
}
|
||||
|
||||
func getKvConfig(cmd *cobra.Command) (*kv.Config, error) {
|
||||
endpoints, err := cmd.Flags().GetStringSlice("endpoints")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
connectionTimeout, err := cmd.Flags().GetInt("connection-timeout")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tlsConfig, err := createTLSConfig(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &kv.Config{
|
||||
Endpoints: endpoints,
|
||||
Prefix: cmd.Flag("prefix").Value.String(),
|
||||
Options: &store.Config{
|
||||
ConnectionTimeout: time.Duration(connectionTimeout) * time.Second,
|
||||
Username: cmd.Flag("password").Value.String(),
|
||||
Password: cmd.Flag("username").Value.String(),
|
||||
TLS: tlsConfig,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createTLSConfig(cmd *cobra.Command) (*tls.Config, error) {
|
||||
enable, _ := cmd.Flags().GetBool("tls")
|
||||
if !enable {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ca := cmd.Flag("tls.ca").Value.String()
|
||||
caPool, err := getCertPool(ca)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caOptional, _ := cmd.Flags().GetBool("tls.ca.optional")
|
||||
clientAuth := getClientAuth(ca, caOptional)
|
||||
|
||||
insecureSkipVerify, _ := cmd.Flags().GetBool("tls.insecureskipverify")
|
||||
privateKey := cmd.Flag("tls.key").Value.String()
|
||||
certContent := cmd.Flag("tls.cert").Value.String()
|
||||
|
||||
if !insecureSkipVerify && (len(certContent) == 0 || len(privateKey) == 0) {
|
||||
return nil, fmt.Errorf("TLS Certificate or Key file must be set when TLS configuration is created")
|
||||
}
|
||||
|
||||
cert, err := getCertificate(privateKey, certContent)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load TLS keypair: %s", err)
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caPool,
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
ClientAuth: clientAuth,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getCertPool(ca string) (*x509.CertPool, error) {
|
||||
caPool := x509.NewCertPool()
|
||||
|
||||
if ca != "" {
|
||||
caContent, err := getCAContent(ca)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read CA. %s", err)
|
||||
}
|
||||
|
||||
if !caPool.AppendCertsFromPEM(caContent) {
|
||||
return nil, fmt.Errorf("failed to parse CA")
|
||||
}
|
||||
}
|
||||
|
||||
return caPool, nil
|
||||
}
|
||||
|
||||
func getCAContent(ca string) ([]byte, error) {
|
||||
if _, errCA := os.Stat(ca); errCA != nil {
|
||||
return []byte(ca), nil
|
||||
}
|
||||
|
||||
caContent, err := ioutil.ReadFile(ca)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return caContent, nil
|
||||
}
|
||||
|
||||
func getClientAuth(ca string, caOptional bool) tls.ClientAuthType {
|
||||
if ca == "" {
|
||||
return tls.NoClientCert
|
||||
}
|
||||
|
||||
if caOptional {
|
||||
return tls.VerifyClientCertIfGiven
|
||||
}
|
||||
return tls.RequireAndVerifyClientCert
|
||||
}
|
||||
|
||||
func getCertificate(privateKey, certContent string) (tls.Certificate, error) {
|
||||
if certContent == "" || privateKey == "" {
|
||||
return tls.Certificate{}, nil
|
||||
}
|
||||
|
||||
_, errKeyIsFile := os.Stat(privateKey)
|
||||
_, errCertIsFile := os.Stat(certContent)
|
||||
|
||||
if errCertIsFile == nil && os.IsNotExist(errKeyIsFile) {
|
||||
return tls.Certificate{}, fmt.Errorf("tls cert is a file, but tls key is not")
|
||||
}
|
||||
|
||||
if os.IsNotExist(errCertIsFile) && errKeyIsFile == nil {
|
||||
return tls.Certificate{}, fmt.Errorf("TLS key is a file, but tls cert is not")
|
||||
}
|
||||
|
||||
// string
|
||||
if os.IsNotExist(errCertIsFile) && os.IsNotExist(errKeyIsFile) {
|
||||
return tls.X509KeyPair([]byte(certContent), []byte(privateKey))
|
||||
}
|
||||
|
||||
// files
|
||||
if errCertIsFile == nil && errKeyIsFile == nil {
|
||||
return tls.LoadX509KeyPair(certContent, privateKey)
|
||||
}
|
||||
|
||||
if errCertIsFile != nil {
|
||||
return tls.Certificate{}, errCertIsFile
|
||||
}
|
||||
return tls.Certificate{}, errKeyIsFile
|
||||
}
|
180
traefik/traefik-certs-dumper/cmd/root.go
Normal file
180
traefik/traefik-certs-dumper/cmd/root.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "traefik-certs-dumper",
|
||||
Short: "Dump Let's Encrypt certificates from Traefik.",
|
||||
Long: `Dump Let's Encrypt certificates from Traefik.`,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if cmd.Name() == "version" {
|
||||
return nil
|
||||
}
|
||||
|
||||
crtExt := cmd.Flag("crt-ext").Value.String()
|
||||
keyExt := cmd.Flag("key-ext").Value.String()
|
||||
|
||||
subDir, _ := strconv.ParseBool(cmd.Flag("domain-subdir").Value.String())
|
||||
if !subDir {
|
||||
if crtExt == keyExt {
|
||||
return fmt.Errorf("--crt-ext (%q) and --key-ext (%q) are identical, in this case --domain-subdir is required", crtExt, keyExt)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.traefik-certs-dumper.yaml)")
|
||||
|
||||
rootCmd.PersistentFlags().String("dest", "./dump", "Path to store the dump content.")
|
||||
rootCmd.PersistentFlags().String("crt-ext", ".crt", "The file extension of the generated certificates.")
|
||||
rootCmd.PersistentFlags().String("crt-name", "certificate", "The file name (without extension) of the generated certificates.")
|
||||
rootCmd.PersistentFlags().String("key-ext", ".key", "The file extension of the generated private keys.")
|
||||
rootCmd.PersistentFlags().String("key-name", "privatekey", "The file name (without extension) of the generated private keys.")
|
||||
rootCmd.PersistentFlags().Bool("domain-subdir", false, "Use domain as sub-directory.")
|
||||
rootCmd.PersistentFlags().Bool("clean", true, "Clean destination folder before dumping content.")
|
||||
rootCmd.PersistentFlags().Bool("watch", false, "Enable watching changes.")
|
||||
rootCmd.PersistentFlags().String("post-hook", "", "Execute a command only if changes occurs on the data source. (works only with the watch mode)")
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
func initConfig() {
|
||||
if cfgFile != "" {
|
||||
// Use config file from the flag.
|
||||
viper.SetConfigFile(cfgFile)
|
||||
} else {
|
||||
// Find home directory.
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Search config in home directory with name ".traefik-certs-dumper" (without extension).
|
||||
viper.AddConfigPath(home)
|
||||
viper.SetConfigName(".traefik-certs-dumper")
|
||||
}
|
||||
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
|
||||
func runE(apply func(*dumper.BaseConfig, *cobra.Command) error) func(*cobra.Command, []string) error {
|
||||
return func(cmd *cobra.Command, _ []string) error {
|
||||
baseConfig, err := getBaseConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = apply(baseConfig, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tree(baseConfig.DumpPath, "")
|
||||
}
|
||||
}
|
||||
|
||||
func tree(root, indent string) error {
|
||||
fi, err := os.Stat(root)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not stat %s: %v", root, err)
|
||||
}
|
||||
|
||||
fmt.Println(fi.Name())
|
||||
if !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
fis, err := ioutil.ReadDir(root)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read dir %s: %v", root, err)
|
||||
}
|
||||
|
||||
var names []string
|
||||
for _, fi := range fis {
|
||||
if fi.Name()[0] != '.' {
|
||||
names = append(names, fi.Name())
|
||||
}
|
||||
}
|
||||
|
||||
for i, name := range names {
|
||||
add := "│ "
|
||||
if i == len(names)-1 {
|
||||
fmt.Printf(indent + "└──")
|
||||
add = " "
|
||||
} else {
|
||||
fmt.Printf(indent + "├──")
|
||||
}
|
||||
|
||||
if err := tree(filepath.Join(root, name), indent+add); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getBaseConfig(cmd *cobra.Command) (*dumper.BaseConfig, error) {
|
||||
subDir, err := strconv.ParseBool(cmd.Flag("domain-subdir").Value.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clean, err := strconv.ParseBool(cmd.Flag("clean").Value.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
watch, err := strconv.ParseBool(cmd.Flag("watch").Value.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dumper.BaseConfig{
|
||||
DumpPath: cmd.Flag("dest").Value.String(),
|
||||
CrtInfo: dumper.FileInfo{
|
||||
Name: cmd.Flag("crt-name").Value.String(),
|
||||
Ext: cmd.Flag("crt-ext").Value.String(),
|
||||
},
|
||||
KeyInfo: dumper.FileInfo{
|
||||
Name: cmd.Flag("key-name").Value.String(),
|
||||
Ext: cmd.Flag("key-ext").Value.String(),
|
||||
},
|
||||
DomainSubDir: subDir,
|
||||
Clean: clean,
|
||||
Watch: watch,
|
||||
Hook: cmd.Flag("post-hook").Value.String(),
|
||||
}, nil
|
||||
}
|
38
traefik/traefik-certs-dumper/cmd/version.go
Normal file
38
traefik/traefik-certs-dumper/cmd/version.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "dev"
|
||||
commit = "I don't remember exactly"
|
||||
date = "I don't remember exactly"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Display version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
displayVersion(rootCmd.Name())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
func displayVersion(name string) {
|
||||
fmt.Printf(name+`:
|
||||
version : %s
|
||||
commit : %s
|
||||
build date : %s
|
||||
go version : %s
|
||||
go compiler : %s
|
||||
platform : %s/%s
|
||||
`, version, commit, date, runtime.Version(), runtime.Compiler, runtime.GOOS, runtime.GOARCH)
|
||||
}
|
33
traefik/traefik-certs-dumper/cmd/zookeeper.go
Normal file
33
traefik/traefik-certs-dumper/cmd/zookeeper.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/zookeeper"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper"
|
||||
"github.com/ldez/traefik-certs-dumper/v2/dumper/kv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// zookeeperCmd represents the zookeeper command
|
||||
var zookeeperCmd = &cobra.Command{
|
||||
Use: "zookeeper",
|
||||
Short: "Dump the content of zookeeper.",
|
||||
Long: `Dump the content of zookeeper.`,
|
||||
RunE: runE(zookeeperRun),
|
||||
}
|
||||
|
||||
func init() {
|
||||
kvCmd.AddCommand(zookeeperCmd)
|
||||
}
|
||||
|
||||
func zookeeperRun(baseConfig *dumper.BaseConfig, cmd *cobra.Command) error {
|
||||
config, err := getKvConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Backend = store.ZK
|
||||
zookeeper.Register()
|
||||
|
||||
return kv.Dump(config, baseConfig)
|
||||
}
|
Reference in New Issue
Block a user