mirror of https://github.com/status-im/consul.git
Merge pull request #10345 from hashicorp/dnephin/backport-logging-fix
[1.9.x] agent: remove leading whitespace from agent log lines
This commit is contained in:
parent
ea6d6dd2ee
commit
1819976011
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
agent: fix logging output by removing leading whitespace from every log line
|
||||||
|
```
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -11,32 +12,28 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-checkpoint"
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
mcli "github.com/mitchellh/cli"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent"
|
"github.com/hashicorp/consul/agent"
|
||||||
"github.com/hashicorp/consul/agent/config"
|
"github.com/hashicorp/consul/agent/config"
|
||||||
|
"github.com/hashicorp/consul/command/cli"
|
||||||
"github.com/hashicorp/consul/command/flags"
|
"github.com/hashicorp/consul/command/flags"
|
||||||
"github.com/hashicorp/consul/lib"
|
"github.com/hashicorp/consul/lib"
|
||||||
"github.com/hashicorp/consul/logging"
|
"github.com/hashicorp/consul/logging"
|
||||||
"github.com/hashicorp/consul/service_os"
|
"github.com/hashicorp/consul/service_os"
|
||||||
"github.com/hashicorp/go-checkpoint"
|
consulversion "github.com/hashicorp/consul/version"
|
||||||
"github.com/hashicorp/go-hclog"
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(ui cli.Ui, revision, version, versionPre, versionHuman string, shutdownCh <-chan struct{}) *cmd {
|
func New(ui cli.Ui) *cmd {
|
||||||
ui = &cli.PrefixedUi{
|
|
||||||
OutputPrefix: "==> ",
|
|
||||||
InfoPrefix: " ",
|
|
||||||
ErrorPrefix: "==> ",
|
|
||||||
Ui: ui,
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &cmd{
|
c := &cmd{
|
||||||
UI: ui,
|
ui: ui,
|
||||||
revision: revision,
|
revision: consulversion.GitCommit,
|
||||||
version: version,
|
version: consulversion.Version,
|
||||||
versionPrerelease: versionPre,
|
versionPrerelease: consulversion.VersionPrerelease,
|
||||||
versionHuman: versionHuman,
|
versionHuman: consulversion.GetHumanVersion(),
|
||||||
shutdownCh: shutdownCh,
|
flags: flag.NewFlagSet("", flag.ContinueOnError),
|
||||||
}
|
}
|
||||||
c.init()
|
c.init()
|
||||||
return c
|
return c
|
||||||
|
@ -47,7 +44,7 @@ func New(ui cli.Ui, revision, version, versionPre, versionHuman string, shutdown
|
||||||
// ShutdownCh. If two messages are sent on the ShutdownCh it will forcibly
|
// ShutdownCh. If two messages are sent on the ShutdownCh it will forcibly
|
||||||
// exit.
|
// exit.
|
||||||
type cmd struct {
|
type cmd struct {
|
||||||
UI cli.Ui
|
ui cli.Ui
|
||||||
flags *flag.FlagSet
|
flags *flag.FlagSet
|
||||||
http *flags.HTTPFlags
|
http *flags.HTTPFlags
|
||||||
help string
|
help string
|
||||||
|
@ -55,7 +52,6 @@ type cmd struct {
|
||||||
version string
|
version string
|
||||||
versionPrerelease string
|
versionPrerelease string
|
||||||
versionHuman string
|
versionHuman string
|
||||||
shutdownCh <-chan struct{}
|
|
||||||
flagArgs config.BuilderOpts
|
flagArgs config.BuilderOpts
|
||||||
logger hclog.InterceptLogger
|
logger hclog.InterceptLogger
|
||||||
}
|
}
|
||||||
|
@ -122,7 +118,7 @@ func (c *cmd) startupJoin(agent *agent.Agent, cfg *config.RuntimeConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.UI.Output("Joining cluster...")
|
c.logger.Info("Joining cluster")
|
||||||
n, err := agent.JoinLAN(cfg.StartJoinAddrsLAN)
|
n, err := agent.JoinLAN(cfg.StartJoinAddrsLAN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -138,74 +134,82 @@ func (c *cmd) startupJoinWan(agent *agent.Agent, cfg *config.RuntimeConfig) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.UI.Output("Joining -wan cluster...")
|
c.logger.Info("Joining wan cluster")
|
||||||
n, err := agent.JoinWAN(cfg.StartJoinAddrsWAN)
|
n, err := agent.JoinWAN(cfg.StartJoinAddrsWAN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger.Info("Join -wan completed. Initial agents synced with", "agent_count", n)
|
c.logger.Info("Join wan completed. Initial agents synced with", "agent_count", n)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmd) run(args []string) int {
|
func (c *cmd) run(args []string) int {
|
||||||
|
ui := &mcli.PrefixedUi{
|
||||||
|
OutputPrefix: "==> ",
|
||||||
|
InfoPrefix: " ",
|
||||||
|
ErrorPrefix: "==> ",
|
||||||
|
Ui: c.ui,
|
||||||
|
}
|
||||||
|
|
||||||
if err := c.flags.Parse(args); err != nil {
|
if err := c.flags.Parse(args); err != nil {
|
||||||
if !strings.Contains(err.Error(), "help requested") {
|
if !strings.Contains(err.Error(), "help requested") {
|
||||||
c.UI.Error(fmt.Sprintf("error parsing flags: %v", err))
|
ui.Error(fmt.Sprintf("error parsing flags: %v", err))
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if len(c.flags.Args()) > 0 {
|
if len(c.flags.Args()) > 0 {
|
||||||
c.UI.Error(fmt.Sprintf("Unexpected extra arguments: %v", c.flags.Args()))
|
ui.Error(fmt.Sprintf("Unexpected extra arguments: %v", c.flags.Args()))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
logGate := &logging.GatedWriter{Writer: &cli.UiWriter{Ui: c.UI}}
|
// FIXME: logs should always go to stderr, but previously they were sent to
|
||||||
|
// stdout, so continue to use Stdout for now, and fix this in a future release.
|
||||||
|
logGate := &logging.GatedWriter{Writer: c.ui.Stdout()}
|
||||||
loader := func(source config.Source) (cfg *config.RuntimeConfig, warnings []string, err error) {
|
loader := func(source config.Source) (cfg *config.RuntimeConfig, warnings []string, err error) {
|
||||||
return config.Load(c.flagArgs, source)
|
return config.Load(c.flagArgs, source)
|
||||||
}
|
}
|
||||||
bd, err := agent.NewBaseDeps(loader, logGate)
|
bd, err := agent.NewBaseDeps(loader, logGate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger = bd.Logger
|
c.logger = bd.Logger
|
||||||
agent, err := agent.New(bd)
|
agent, err := agent.New(bd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
config := bd.RuntimeConfig
|
config := bd.RuntimeConfig
|
||||||
|
if config.Logging.LogJSON {
|
||||||
// Setup gate to check if we should output CLI information
|
// Hide all non-error output when JSON logging is enabled.
|
||||||
cli := GatedUi{
|
ui.Ui = &cli.BasicUI{
|
||||||
JSONoutput: config.Logging.LogJSON,
|
BasicUi: mcli.BasicUi{ErrorWriter: c.ui.Stderr(), Writer: ioutil.Discard},
|
||||||
ui: c.UI,
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the agent
|
ui.Output("Starting Consul agent...")
|
||||||
cli.output("Starting Consul agent...")
|
|
||||||
|
|
||||||
segment := config.SegmentName
|
segment := config.SegmentName
|
||||||
if config.ServerMode {
|
if config.ServerMode {
|
||||||
segment = "<all>"
|
segment = "<all>"
|
||||||
}
|
}
|
||||||
cli.info(fmt.Sprintf(" Version: '%s'", c.versionHuman))
|
ui.Info(fmt.Sprintf(" Version: '%s'", c.versionHuman))
|
||||||
cli.info(fmt.Sprintf(" Node ID: '%s'", config.NodeID))
|
ui.Info(fmt.Sprintf(" Node ID: '%s'", config.NodeID))
|
||||||
cli.info(fmt.Sprintf(" Node name: '%s'", config.NodeName))
|
ui.Info(fmt.Sprintf(" Node name: '%s'", config.NodeName))
|
||||||
cli.info(fmt.Sprintf(" Datacenter: '%s' (Segment: '%s')", config.Datacenter, segment))
|
ui.Info(fmt.Sprintf(" Datacenter: '%s' (Segment: '%s')", config.Datacenter, segment))
|
||||||
cli.info(fmt.Sprintf(" Server: %v (Bootstrap: %v)", config.ServerMode, config.Bootstrap))
|
ui.Info(fmt.Sprintf(" Server: %v (Bootstrap: %v)", config.ServerMode, config.Bootstrap))
|
||||||
cli.info(fmt.Sprintf(" Client Addr: %v (HTTP: %d, HTTPS: %d, gRPC: %d, DNS: %d)", config.ClientAddrs,
|
ui.Info(fmt.Sprintf(" Client Addr: %v (HTTP: %d, HTTPS: %d, gRPC: %d, DNS: %d)", config.ClientAddrs,
|
||||||
config.HTTPPort, config.HTTPSPort, config.GRPCPort, config.DNSPort))
|
config.HTTPPort, config.HTTPSPort, config.GRPCPort, config.DNSPort))
|
||||||
cli.info(fmt.Sprintf(" Cluster Addr: %v (LAN: %d, WAN: %d)", config.AdvertiseAddrLAN,
|
ui.Info(fmt.Sprintf(" Cluster Addr: %v (LAN: %d, WAN: %d)", config.AdvertiseAddrLAN,
|
||||||
config.SerfPortLAN, config.SerfPortWAN))
|
config.SerfPortLAN, config.SerfPortWAN))
|
||||||
cli.info(fmt.Sprintf(" Encrypt: Gossip: %v, TLS-Outgoing: %v, TLS-Incoming: %v, Auto-Encrypt-TLS: %t",
|
ui.Info(fmt.Sprintf(" Encrypt: Gossip: %v, TLS-Outgoing: %v, TLS-Incoming: %v, Auto-Encrypt-TLS: %t",
|
||||||
config.EncryptKey != "", config.VerifyOutgoing, config.VerifyIncoming, config.AutoEncryptTLS || config.AutoEncryptAllowTLS))
|
config.EncryptKey != "", config.VerifyOutgoing, config.VerifyIncoming, config.AutoEncryptTLS || config.AutoEncryptAllowTLS))
|
||||||
// Enable log streaming
|
// Enable log streaming
|
||||||
cli.output("")
|
ui.Output("")
|
||||||
cli.output("Log data will now stream in as it occurs:\n")
|
ui.Output("Log data will now stream in as it occurs:\n")
|
||||||
logGate.Flush()
|
logGate.Flush()
|
||||||
|
|
||||||
// wait for signal
|
// wait for signal
|
||||||
|
@ -258,19 +262,19 @@ func (c *cmd) run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.startupJoin(agent, config); err != nil {
|
if err := c.startupJoin(agent, config); err != nil {
|
||||||
c.logger.Error((err.Error()))
|
c.logger.Error(err.Error())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.startupJoinWan(agent, config); err != nil {
|
if err := c.startupJoinWan(agent, config); err != nil {
|
||||||
c.logger.Error((err.Error()))
|
c.logger.Error(err.Error())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the agent know we've finished registration
|
// Let the agent know we've finished registration
|
||||||
agent.StartSync()
|
agent.StartSync()
|
||||||
|
|
||||||
cli.output("Consul agent running!")
|
c.logger.Info("Consul agent running!")
|
||||||
|
|
||||||
// wait for signal
|
// wait for signal
|
||||||
signalCh = make(chan os.Signal, 10)
|
signalCh = make(chan os.Signal, 10)
|
||||||
|
@ -283,8 +287,6 @@ func (c *cmd) run(args []string) int {
|
||||||
sig = s
|
sig = s
|
||||||
case <-service_os.Shutdown_Channel():
|
case <-service_os.Shutdown_Channel():
|
||||||
sig = os.Interrupt
|
sig = os.Interrupt
|
||||||
case <-c.shutdownCh:
|
|
||||||
sig = os.Interrupt
|
|
||||||
case err := <-agent.RetryJoinCh():
|
case err := <-agent.RetryJoinCh():
|
||||||
c.logger.Error("Retry join failed", "error", err)
|
c.logger.Error("Retry join failed", "error", err)
|
||||||
return 1
|
return 1
|
||||||
|
@ -340,23 +342,6 @@ func (c *cmd) run(args []string) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type GatedUi struct {
|
|
||||||
JSONoutput bool
|
|
||||||
ui cli.Ui
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GatedUi) output(s string) {
|
|
||||||
if !g.JSONoutput {
|
|
||||||
g.ui.Output(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GatedUi) info(s string) {
|
|
||||||
if !g.JSONoutput {
|
|
||||||
g.ui.Info(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cmd) Synopsis() string {
|
func (c *cmd) Synopsis() string {
|
||||||
return synopsis
|
return synopsis
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,19 @@ package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/testrpc"
|
"github.com/mitchellh/cli"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent"
|
"github.com/hashicorp/consul/agent"
|
||||||
"github.com/hashicorp/consul/sdk/testutil"
|
"github.com/hashicorp/consul/sdk/testutil"
|
||||||
"github.com/hashicorp/consul/sdk/testutil/retry"
|
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/hashicorp/consul/testrpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestConfigFail should test command line flags that lead to an immediate error.
|
// TestConfigFail should test command line flags that lead to an immediate error.
|
||||||
|
@ -110,8 +111,8 @@ func TestRetryJoinFail(t *testing.T) {
|
||||||
tmpDir := testutil.TempDir(t, "consul")
|
tmpDir := testutil.TempDir(t, "consul")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
ui := cli.NewMockUi()
|
ui := newCaptureUI()
|
||||||
cmd := New(ui, "", "", "", "", nil)
|
cmd := New(ui)
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-bind", "127.0.0.1",
|
"-bind", "127.0.0.1",
|
||||||
|
@ -131,8 +132,8 @@ func TestRetryJoinWanFail(t *testing.T) {
|
||||||
tmpDir := testutil.TempDir(t, "consul")
|
tmpDir := testutil.TempDir(t, "consul")
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
ui := cli.NewMockUi()
|
ui := newCaptureUI()
|
||||||
cmd := New(ui, "", "", "", "", nil)
|
cmd := New(ui)
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-server",
|
"-server",
|
||||||
|
@ -172,8 +173,8 @@ func TestProtectDataDir(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ui := cli.NewMockUi()
|
ui := newCaptureUI()
|
||||||
cmd := New(ui, "", "", "", "", nil)
|
cmd := New(ui)
|
||||||
args := []string{"-config-file=" + cfgFile.Name()}
|
args := []string{"-config-file=" + cfgFile.Name()}
|
||||||
if code := cmd.Run(args); code == 0 {
|
if code := cmd.Run(args); code == 0 {
|
||||||
t.Fatalf("should fail")
|
t.Fatalf("should fail")
|
||||||
|
@ -194,8 +195,8 @@ func TestBadDataDirPermissions(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dataDir)
|
defer os.RemoveAll(dataDir)
|
||||||
|
|
||||||
ui := cli.NewMockUi()
|
ui := newCaptureUI()
|
||||||
cmd := New(ui, "", "", "", "", nil)
|
cmd := New(ui)
|
||||||
args := []string{"-data-dir=" + dataDir, "-server=true", "-bind=10.0.0.1"}
|
args := []string{"-data-dir=" + dataDir, "-server=true", "-bind=10.0.0.1"}
|
||||||
if code := cmd.Run(args); code == 0 {
|
if code := cmd.Run(args); code == 0 {
|
||||||
t.Fatalf("Should fail with bad data directory permissions")
|
t.Fatalf("Should fail with bad data directory permissions")
|
||||||
|
@ -204,3 +205,19 @@ func TestBadDataDirPermissions(t *testing.T) {
|
||||||
t.Fatalf("expected permission denied error, got: %s", out)
|
t.Fatalf("expected permission denied error, got: %s", out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type captureUI struct {
|
||||||
|
*cli.MockUi
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *captureUI) Stdout() io.Writer {
|
||||||
|
return c.MockUi.OutputWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *captureUI) Stderr() io.Writer {
|
||||||
|
return c.MockUi.ErrorWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCaptureUI() *captureUI {
|
||||||
|
return &captureUI{MockUi: cli.NewMockUi()}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
mcli "github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ui implements the mitchellh/cli.Ui interface, while exposing the underlying
|
||||||
|
// io.Writer used for stdout and stderr.
|
||||||
|
// TODO: rename to UI to match golang style guide
|
||||||
|
type Ui interface {
|
||||||
|
mcli.Ui
|
||||||
|
Stdout() io.Writer
|
||||||
|
Stderr() io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// BasicUI augments mitchellh/cli.BasicUi by exposing the underlying io.Writer.
|
||||||
|
type BasicUI struct {
|
||||||
|
mcli.BasicUi
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BasicUI) Stdout() io.Writer {
|
||||||
|
return b.BasicUi.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BasicUI) Stderr() io.Writer {
|
||||||
|
return b.BasicUi.ErrorWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command is an alias to reduce the diff. It can be removed at any time.
|
||||||
|
type Command mcli.Command
|
|
@ -41,6 +41,7 @@ import (
|
||||||
catlistdc "github.com/hashicorp/consul/command/catalog/list/dc"
|
catlistdc "github.com/hashicorp/consul/command/catalog/list/dc"
|
||||||
catlistnodes "github.com/hashicorp/consul/command/catalog/list/nodes"
|
catlistnodes "github.com/hashicorp/consul/command/catalog/list/nodes"
|
||||||
catlistsvc "github.com/hashicorp/consul/command/catalog/list/services"
|
catlistsvc "github.com/hashicorp/consul/command/catalog/list/services"
|
||||||
|
"github.com/hashicorp/consul/command/cli"
|
||||||
"github.com/hashicorp/consul/command/config"
|
"github.com/hashicorp/consul/command/config"
|
||||||
configdelete "github.com/hashicorp/consul/command/config/delete"
|
configdelete "github.com/hashicorp/consul/command/config/delete"
|
||||||
configlist "github.com/hashicorp/consul/command/config/list"
|
configlist "github.com/hashicorp/consul/command/config/list"
|
||||||
|
@ -105,17 +106,9 @@ import (
|
||||||
"github.com/hashicorp/consul/command/validate"
|
"github.com/hashicorp/consul/command/validate"
|
||||||
"github.com/hashicorp/consul/command/version"
|
"github.com/hashicorp/consul/command/version"
|
||||||
"github.com/hashicorp/consul/command/watch"
|
"github.com/hashicorp/consul/command/watch"
|
||||||
consulversion "github.com/hashicorp/consul/version"
|
|
||||||
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rev := consulversion.GitCommit
|
|
||||||
ver := consulversion.Version
|
|
||||||
verPre := consulversion.VersionPrerelease
|
|
||||||
verHuman := consulversion.GetHumanVersion()
|
|
||||||
|
|
||||||
Register("acl", func(cli.Ui) (cli.Command, error) { return acl.New(), nil })
|
Register("acl", func(cli.Ui) (cli.Command, error) { return acl.New(), nil })
|
||||||
Register("acl bootstrap", func(ui cli.Ui) (cli.Command, error) { return aclbootstrap.New(ui), nil })
|
Register("acl bootstrap", func(ui cli.Ui) (cli.Command, error) { return aclbootstrap.New(ui), nil })
|
||||||
Register("acl policy", func(cli.Ui) (cli.Command, error) { return aclpolicy.New(), nil })
|
Register("acl policy", func(cli.Ui) (cli.Command, error) { return aclpolicy.New(), nil })
|
||||||
|
@ -151,9 +144,7 @@ func init() {
|
||||||
Register("acl binding-rule read", func(ui cli.Ui) (cli.Command, error) { return aclbrread.New(ui), nil })
|
Register("acl binding-rule read", func(ui cli.Ui) (cli.Command, error) { return aclbrread.New(ui), nil })
|
||||||
Register("acl binding-rule update", func(ui cli.Ui) (cli.Command, error) { return aclbrupdate.New(ui), nil })
|
Register("acl binding-rule update", func(ui cli.Ui) (cli.Command, error) { return aclbrupdate.New(ui), nil })
|
||||||
Register("acl binding-rule delete", func(ui cli.Ui) (cli.Command, error) { return aclbrdelete.New(ui), nil })
|
Register("acl binding-rule delete", func(ui cli.Ui) (cli.Command, error) { return aclbrdelete.New(ui), nil })
|
||||||
Register("agent", func(ui cli.Ui) (cli.Command, error) {
|
Register("agent", func(ui cli.Ui) (cli.Command, error) { return agent.New(ui), nil })
|
||||||
return agent.New(ui, rev, ver, verPre, verHuman, make(chan struct{})), nil
|
|
||||||
})
|
|
||||||
Register("catalog", func(cli.Ui) (cli.Command, error) { return catalog.New(), nil })
|
Register("catalog", func(cli.Ui) (cli.Command, error) { return catalog.New(), nil })
|
||||||
Register("catalog datacenters", func(ui cli.Ui) (cli.Command, error) { return catlistdc.New(ui), nil })
|
Register("catalog datacenters", func(ui cli.Ui) (cli.Command, error) { return catlistdc.New(ui), nil })
|
||||||
Register("catalog nodes", func(ui cli.Ui) (cli.Command, error) { return catlistnodes.New(ui), nil })
|
Register("catalog nodes", func(ui cli.Ui) (cli.Command, error) { return catlistnodes.New(ui), nil })
|
||||||
|
|
|
@ -6,7 +6,9 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/mitchellh/cli"
|
mcli "github.com/mitchellh/cli"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Factory is a function that returns a new instance of a CLI-sub command.
|
// Factory is a function that returns a new instance of a CLI-sub command.
|
||||||
|
@ -24,14 +26,14 @@ func Register(name string, fn Factory) {
|
||||||
registry[name] = fn
|
registry[name] = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map returns a realized mapping of available CLI commands in a format that
|
// CommandsFromRegistry returns a realized mapping of available CLI commands in a format that
|
||||||
// the CLI class can consume. This should be called after all registration is
|
// the CLI class can consume. This should be called after all registration is
|
||||||
// complete.
|
// complete.
|
||||||
func Map(ui cli.Ui) map[string]cli.CommandFactory {
|
func CommandsFromRegistry(ui cli.Ui) map[string]mcli.CommandFactory {
|
||||||
m := make(map[string]cli.CommandFactory)
|
m := make(map[string]mcli.CommandFactory)
|
||||||
for name, fn := range registry {
|
for name, fn := range registry {
|
||||||
thisFn := fn
|
thisFn := fn
|
||||||
m[name] = func() (cli.Command, error) {
|
m[name] = func() (mcli.Command, error) {
|
||||||
return thisFn(ui)
|
return thisFn(ui)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
main.go
14
main.go
|
@ -6,11 +6,13 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
mcli "github.com/mitchellh/cli"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/command"
|
"github.com/hashicorp/consul/command"
|
||||||
|
"github.com/hashicorp/consul/command/cli"
|
||||||
"github.com/hashicorp/consul/command/version"
|
"github.com/hashicorp/consul/command/version"
|
||||||
"github.com/hashicorp/consul/lib"
|
"github.com/hashicorp/consul/lib"
|
||||||
_ "github.com/hashicorp/consul/service_os"
|
_ "github.com/hashicorp/consul/service_os"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -24,19 +26,21 @@ func main() {
|
||||||
func realMain() int {
|
func realMain() int {
|
||||||
log.SetOutput(ioutil.Discard)
|
log.SetOutput(ioutil.Discard)
|
||||||
|
|
||||||
ui := &cli.BasicUi{Writer: os.Stdout, ErrorWriter: os.Stderr}
|
ui := &cli.BasicUI{
|
||||||
cmds := command.Map(ui)
|
BasicUi: mcli.BasicUi{Writer: os.Stdout, ErrorWriter: os.Stderr},
|
||||||
|
}
|
||||||
|
cmds := command.CommandsFromRegistry(ui)
|
||||||
var names []string
|
var names []string
|
||||||
for c := range cmds {
|
for c := range cmds {
|
||||||
names = append(names, c)
|
names = append(names, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
cli := &cli.CLI{
|
cli := &mcli.CLI{
|
||||||
Args: os.Args[1:],
|
Args: os.Args[1:],
|
||||||
Commands: cmds,
|
Commands: cmds,
|
||||||
Autocomplete: true,
|
Autocomplete: true,
|
||||||
Name: "consul",
|
Name: "consul",
|
||||||
HelpFunc: cli.FilteredHelpFunc(names, cli.BasicHelpFunc("consul")),
|
HelpFunc: mcli.FilteredHelpFunc(names, mcli.BasicHelpFunc("consul")),
|
||||||
HelpWriter: os.Stdout,
|
HelpWriter: os.Stdout,
|
||||||
ErrorWriter: os.Stderr,
|
ErrorWriter: os.Stderr,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue