From 788386b49acabd637d17cdee9e7b713e6fc56d72 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Wed, 10 May 2017 20:19:04 -0600 Subject: [PATCH] Implement 'config' CLI command. Renames `config` to `generate-config` and implements a new `config` command that generates the configuration file based on the current state instead of printing a static string. --- cmd/config.go | 12 ++++++-- cmd/generate_config.go | 49 ++++++++++++++++++++++++++++++++ cmd/server.go | 19 ++----------- config.go | 4 +++ ctl/config.go | 30 +++++--------------- ctl/generate_config.go | 63 ++++++++++++++++++++++++++++++++++++++++++ ctl/server.go | 42 ++++++++++++++++++++++++++++ glide.lock | 2 +- 8 files changed, 178 insertions(+), 43 deletions(-) create mode 100644 cmd/generate_config.go create mode 100644 ctl/generate_config.go create mode 100644 ctl/server.go diff --git a/cmd/config.go b/cmd/config.go index 589367712..9452cbc3c 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -22,18 +22,21 @@ import ( "github.com/spf13/cobra" "github.com/pilosa/pilosa/ctl" + "github.com/pilosa/pilosa/server" ) var Conf *ctl.ConfigCommand func NewConfigCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command { Conf = ctl.NewConfigCommand(os.Stdin, os.Stdout, os.Stderr) + Server := server.NewCommand(stdin, stdout, stderr) confCmd := &cobra.Command{ Use: "config", - Short: "Print the default configuration.", - Long: `config prints the default configuration to stdout -`, + Short: "Print the current configuration.", + Long: `config prints the current configuration to stdout`, + RunE: func(cmd *cobra.Command, args []string) error { + Conf.Config = Server.Config if err := Conf.Run(context.Background()); err != nil { return err } @@ -41,6 +44,9 @@ func NewConfigCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command }, } + // Attach flags to the command. + ctl.BuildServerFlags(confCmd, Server) + return confCmd } diff --git a/cmd/generate_config.go b/cmd/generate_config.go new file mode 100644 index 000000000..b0622b64d --- /dev/null +++ b/cmd/generate_config.go @@ -0,0 +1,49 @@ +// Copyright 2017 Pilosa Corp. +// +// 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 cmd + +import ( + "context" + "io" + "os" + + "github.com/spf13/cobra" + + "github.com/pilosa/pilosa/ctl" +) + +var GenerateConf *ctl.GenerateConfigCommand + +func NewGenerateConfigCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command { + GenerateConf = ctl.NewGenerateConfigCommand(os.Stdin, os.Stdout, os.Stderr) + confCmd := &cobra.Command{ + Use: "generate-config", + Short: "Print the default configuration.", + Long: `generate-config prints the default configuration to stdout +`, + RunE: func(cmd *cobra.Command, args []string) error { + if err := GenerateConf.Run(context.Background()); err != nil { + return err + } + return nil + }, + } + + return confCmd +} + +func init() { + subcommandFns["generate-config"] = NewGenerateConfigCommand +} diff --git a/cmd/server.go b/cmd/server.go index 54603806f..d282ed71f 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" + "github.com/pilosa/pilosa/ctl" "github.com/pilosa/pilosa/server" ) @@ -85,23 +86,9 @@ on the configured port.`, return nil }, } - flags := serveCmd.Flags() - flags.StringVarP(&Server.Config.DataDir, "data-dir", "d", "~/.pilosa", "Directory to store pilosa data files.") - flags.StringVarP(&Server.Config.Host, "bind", "b", ":10101", "Default URI on which pilosa should listen.") - flags.IntVarP(&Server.Config.MaxWritesPerRequest, "max-writes-per-request", "", Server.Config.MaxWritesPerRequest, "Number of write commands per request.") - flags.IntVarP(&Server.Config.Cluster.ReplicaN, "cluster.replicas", "", 1, "Number of hosts each piece of data should be stored on.") - flags.StringSliceVarP(&Server.Config.Cluster.Hosts, "cluster.hosts", "", []string{}, "Comma separated list of hosts in cluster.") - flags.StringSliceVarP(&Server.Config.Cluster.InternalHosts, "cluster.internal-hosts", "", []string{}, "Comma separated list of hosts in cluster used for internal communication.") - flags.DurationVarP((*time.Duration)(&Server.Config.Cluster.PollingInterval), "cluster.poll-interval", "", time.Minute, "Polling interval for cluster.") // TODO what actually is this? - flags.StringVarP(&Server.Config.Plugins.Path, "plugins.path", "", "", "Path to plugin directory.") - flags.StringVar(&Server.Config.LogPath, "log-path", "", "Log path") - flags.DurationVarP((*time.Duration)(&Server.Config.AntiEntropy.Interval), "anti-entropy.interval", "", time.Minute*10, "Interval at which to run anti-entropy routine.") - flags.StringVarP(&Server.CPUProfile, "profile.cpu", "", "", "Where to store CPU profile.") - flags.DurationVarP(&Server.CPUTime, "profile.cpu-time", "", 30*time.Second, "CPU profile duration.") - flags.StringVarP(&Server.Config.Cluster.Type, "cluster.type", "", "static", "Determine how the cluster handles membership and state sharing. Choose from [static, http, gossip]") - flags.StringVarP(&Server.Config.Cluster.GossipSeed, "cluster.gossip-seed", "", "", "Host with which to seed the gossip membership.") - flags.StringVarP(&Server.Config.Cluster.InternalPort, "cluster.internal-port", "", "", "Port to which pilosa should bind for internal state sharing.") + // Attach flags to the command. + ctl.BuildServerFlags(serveCmd, Server) return serveCmd } diff --git a/config.go b/config.go index 3e58a2d13..15e115005 100644 --- a/config.go +++ b/config.go @@ -99,3 +99,7 @@ func (d *Duration) UnmarshalText(text []byte) error { func (d Duration) MarshalText() (text []byte, err error) { return []byte(d.String()), nil } + +func (d Duration) MarshalTOML() ([]byte, error) { + return []byte(d.String()), nil +} diff --git a/ctl/config.go b/ctl/config.go index d084c1e2c..2047941c7 100644 --- a/ctl/config.go +++ b/ctl/config.go @@ -18,14 +18,15 @@ import ( "context" "fmt" "io" - "strings" + toml "github.com/pelletier/go-toml" "github.com/pilosa/pilosa" ) // ConfigCommand represents a command for printing a default config. type ConfigCommand struct { *pilosa.CmdIO + Config *pilosa.Config } // NewConfigCommand returns a new instance of ConfigCommand. @@ -37,27 +38,10 @@ func NewConfigCommand(stdin io.Reader, stdout, stderr io.Writer) *ConfigCommand // Run prints out the default config. func (cmd *ConfigCommand) Run(ctx context.Context) error { - fmt.Fprintln(cmd.Stdout, strings.TrimSpace(` -data-dir = "~/.pilosa" -bind = "localhost:10101" -max-writes-per-request = 5000 - -[cluster] - poll-interval = "2m0s" - replicas = 1 - hosts = [ - "localhost:10101", - ] - -[anti-entropy] - interval = "10m0s" - -[profile] - cpu = "" - cpu-time = "30s" - -[plugins] - path = "" -`)+"\n") + buf, err := toml.Marshal(*cmd.Config) + if err != nil { + return err + } + fmt.Fprintln(cmd.Stdout, string(buf)) return nil } diff --git a/ctl/generate_config.go b/ctl/generate_config.go new file mode 100644 index 000000000..8024a160c --- /dev/null +++ b/ctl/generate_config.go @@ -0,0 +1,63 @@ +// Copyright 2017 Pilosa Corp. +// +// 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 ctl + +import ( + "context" + "fmt" + "io" + "strings" + + "github.com/pilosa/pilosa" +) + +// GenerateConfigCommand represents a command for printing a default config. +type GenerateConfigCommand struct { + *pilosa.CmdIO +} + +// NewGenerateConfigCommand returns a new instance of GenerateConfigCommand. +func NewGenerateConfigCommand(stdin io.Reader, stdout, stderr io.Writer) *GenerateConfigCommand { + return &GenerateConfigCommand{ + CmdIO: pilosa.NewCmdIO(stdin, stdout, stderr), + } +} + +// Run prints out the default config. +func (cmd *GenerateConfigCommand) Run(ctx context.Context) error { + fmt.Fprintln(cmd.Stdout, strings.TrimSpace(` +data-dir = "~/.pilosa" +bind = "localhost:10101" +max-writes-per-request = 5000 + +[cluster] + poll-interval = "2m0s" + replicas = 1 + hosts = [ + "localhost:10101", + ] + +[anti-entropy] + interval = "10m0s" + +[profile] + cpu = "" + cpu-time = "30s" + +[plugins] + path = "" +`)+"\n") + return nil +} diff --git a/ctl/server.go b/ctl/server.go new file mode 100644 index 000000000..7c246491a --- /dev/null +++ b/ctl/server.go @@ -0,0 +1,42 @@ +// Copyright 2017 Pilosa Corp. +// +// 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 ctl + +import ( + "time" + + "github.com/pilosa/pilosa/server" + "github.com/spf13/cobra" +) + +// BuildServerFlags attaches a set of flags to the command for a server instance. +func BuildServerFlags(cmd *cobra.Command, srv *server.Command) { + flags := cmd.Flags() + flags.StringVarP(&srv.Config.DataDir, "data-dir", "d", "~/.pilosa", "Directory to store pilosa data files.") + flags.StringVarP(&srv.Config.Host, "bind", "b", ":10101", "Default URI on which pilosa should listen.") + flags.IntVarP(&srv.Config.MaxWritesPerRequest, "max-writes-per-request", "", srv.Config.MaxWritesPerRequest, "Number of write commands per request.") + flags.IntVarP(&srv.Config.Cluster.ReplicaN, "cluster.replicas", "", 1, "Number of hosts each piece of data should be stored on.") + flags.StringSliceVarP(&srv.Config.Cluster.Hosts, "cluster.hosts", "", []string{}, "Comma separated list of hosts in cluster.") + flags.StringSliceVarP(&srv.Config.Cluster.InternalHosts, "cluster.internal-hosts", "", []string{}, "Comma separated list of hosts in cluster used for internal communication.") + flags.DurationVarP((*time.Duration)(&srv.Config.Cluster.PollingInterval), "cluster.poll-interval", "", time.Minute, "Polling interval for cluster.") // TODO what actually is this? + flags.StringVarP(&srv.Config.Plugins.Path, "plugins.path", "", "", "Path to plugin directory.") + flags.StringVar(&srv.Config.LogPath, "log-path", "", "Log path") + flags.DurationVarP((*time.Duration)(&srv.Config.AntiEntropy.Interval), "anti-entropy.interval", "", time.Minute*10, "Interval at which to run anti-entropy routine.") + flags.StringVarP(&srv.CPUProfile, "profile.cpu", "", "", "Where to store CPU profile.") + flags.DurationVarP(&srv.CPUTime, "profile.cpu-time", "", 30*time.Second, "CPU profile duration.") + flags.StringVarP(&srv.Config.Cluster.Type, "cluster.type", "", "static", "Determine how the cluster handles membership and state sharing. Choose from [static, http, gossip]") + flags.StringVarP(&srv.Config.Cluster.GossipSeed, "cluster.gossip-seed", "", "", "Host with which to seed the gossip membership.") + flags.StringVarP(&srv.Config.Cluster.InternalPort, "cluster.internal-port", "", "", "Port to which pilosa should bind for internal state sharing.") +} diff --git a/glide.lock b/glide.lock index a615eac54..63123f289 100644 --- a/glide.lock +++ b/glide.lock @@ -65,7 +65,7 @@ imports: - name: github.com/pelletier/go-buffruneio version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml - version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a + version: 23f644976aa7c724adf4aec911dadf4af17840ab - name: github.com/rakyll/statik version: 89fe3459b5c829c32e89bdff9c43f18aad728f2f subpackages: