From ab311afab6da8bf6aa5b385e434707c0ddc80a4c Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Sat, 25 Aug 2018 01:13:56 +0200 Subject: [PATCH] Refactor testing to use light config definitions --- cmd/agent.go | 50 +++++++------ cmd/agent_test.go | 50 ++++--------- cmd/config_test.go | 34 +++++++++ dkron/agent_test.go | 125 ++++++++++++--------------------- dkron/api_test.go | 16 ++--- dkron/config.go | 48 ++++++++----- dkron/config_test.go | 29 +------- dkron/flag_slice_value.go | 21 ------ dkron/flag_slice_value_test.go | 33 --------- dkron/grpc_test.go | 16 ++--- 10 files changed, 168 insertions(+), 254 deletions(-) create mode 100644 cmd/config_test.go delete mode 100644 dkron/flag_slice_value.go delete mode 100644 dkron/flag_slice_value_test.go diff --git a/cmd/agent.go b/cmd/agent.go index f01c3c526..edf25c317 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -34,29 +34,7 @@ It also runs a web UI.`, // The returned value is the exit code. // protoc -I proto/ proto/executor.proto --go_out=plugins=grpc:dkron/ RunE: func(cmd *cobra.Command, args []string) error { - legacyConfig() - - // Make sure we clean up any managed plugins at the end of this - p := &Plugins{} - if err := p.DiscoverPlugins(); err != nil { - log.Fatal(err) - } - plugins := &dkron.Plugins{ - Processors: p.Processors, - Executors: p.Executors, - } - - agent = dkron.NewAgent(config, plugins) - if err := agent.Start(); err != nil { - return err - } - - exit := handleSignals() - if exit != 0 { - return fmt.Errorf("Exit status: %d", exit) - } - - return nil + return agentRun(args...) }, } @@ -67,6 +45,32 @@ func init() { viper.BindPFlags(agentCmd.Flags()) } +func agentRun(args ...string) error { + legacyConfig() + + // Make sure we clean up any managed plugins at the end of this + p := &Plugins{} + if err := p.DiscoverPlugins(); err != nil { + log.Fatal(err) + } + plugins := &dkron.Plugins{ + Processors: p.Processors, + Executors: p.Executors, + } + + agent = dkron.NewAgent(config, plugins) + if err := agent.Start(); err != nil { + return err + } + + exit := handleSignals() + if exit != 0 { + return fmt.Errorf("Exit status: %d", exit) + } + + return nil +} + // handleSignals blocks until we get an exit-causing signal func handleSignals() int { signalCh := make(chan os.Signal, 4) diff --git a/cmd/agent_test.go b/cmd/agent_test.go index 5fdf2cb3c..b8fee71d9 100644 --- a/cmd/agent_test.go +++ b/cmd/agent_test.go @@ -3,10 +3,6 @@ package cmd import ( "os" "testing" - "time" - - "github.com/hashicorp/serf/testutil" - "github.com/mitchellh/cli" ) var ( @@ -22,44 +18,22 @@ func getEnvWithDefault() string { return ea } -func TestAgentCommandRun(t *testing.T) { - shutdownCh := make(chan struct{}) - defer close(shutdownCh) - - ui := new(cli.MockUi) - a := &AgentCommand{ - Ui: ui, - ShutdownCh: shutdownCh, - } - - args := []string{ - "-bind-addr", testutil.GetBindAddr().String(), - "-log-level", logLevel, +func Test_unmarshalTags(t *testing.T) { + tagPairs := []string{ + "tag1=val1", + "tag2=val2", } - resultCh := make(chan int) - go func() { - resultCh <- a.Run(args) - }() + tags, err := unmarshalTags(tagPairs) - time.Sleep(2 * time.Second) - - // Verify it runs "forever" - select { - case <-resultCh: - t.Fatalf("ended too soon, err: %s", ui.ErrorWriter.String()) - case <-time.After(50 * time.Millisecond): + if err != nil { + t.Fatalf("err: %s", err) } - // Send a shutdown request - shutdownCh <- struct{}{} - - select { - case code := <-resultCh: - if code != 0 { - t.Fatalf("bad code: %d", code) - } - case <-time.After(50 * time.Millisecond): - t.Fatalf("timeout") + if v, ok := tags["tag1"]; !ok || v != "val1" { + t.Fatalf("bad: %v", tags) + } + if v, ok := tags["tag2"]; !ok || v != "val2" { + t.Fatalf("bad: %v", tags) } } diff --git a/cmd/config_test.go b/cmd/config_test.go new file mode 100644 index 000000000..c174a08a5 --- /dev/null +++ b/cmd/config_test.go @@ -0,0 +1,34 @@ +package cmd + +import ( + "bytes" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/victorcoder/dkron/dkron" +) + +func TestReadConfigTags(t *testing.T) { + viper.Reset() + viper.SetConfigType("yaml") + var jsonConfig = []byte(` + tags: + - foo: bar + `) + viper.ReadConfig(bytes.NewBuffer(jsonConfig)) + config := &dkron.Config{} + viper.Unmarshal(config) + t.Log(config.Tags) + assert.Equal(t, "bar", config.Tags["foo"]) + + viper.Set("tag", []string{"monthy=python"}) + viper.Unmarshal(config) + assert.NotContains(t, config.Tags, "foo") + assert.Contains(t, config.Tags, "monthy") + assert.Equal(t, "python", config.Tags["monthy"]) + + config = &dkron.Config{Tags: map[string]string{"t1": "v1", "t2": "v2"}} + assert.Equal(t, "v1", config.Tags["t1"]) + assert.Equal(t, "v2", config.Tags["t2"]) +} diff --git a/dkron/agent_test.go b/dkron/agent_test.go index 4b4bc4f3c..d4cf8fe9d 100644 --- a/dkron/agent_test.go +++ b/dkron/agent_test.go @@ -12,7 +12,7 @@ import ( ) var ( - logLevel = "error" + logLevel = "debug" etcdAddr = getEnvWithDefault() ) @@ -46,17 +46,17 @@ func TestAgentCommand_runForElection(t *testing.T) { } } - args := []string{ - "-bind-addr", a1Addr, - "-join", a2Addr, - "-node-name", a1Name, - "-server", - "-log-level", logLevel, - } + c := DefaultConfig() + c.BindAddr = a1Addr + c.StartJoin = []string{a2Addr} + c.NodeName = a1Name + c.Server = true + c.LogLevel = logLevel - c := NewConfig(args) a1 := NewAgent(c, nil) - a1.Start() + if err := a1.Start(); err != nil { + t.Fatal(err) + } // Wait for the first agent to start and set itself as leader kv1, err := watchOrDie(client, "dkron/leader") @@ -68,15 +68,13 @@ func TestAgentCommand_runForElection(t *testing.T) { assert.Equal(t, a1Name, leaderA1) // Start another agent - args2 := []string{ - "-bind-addr", a2Addr, - "-join", a1Addr + ":8946", - "-node-name", a2Name, - "-server", - "-log-level", logLevel, - } + c = DefaultConfig() + c.BindAddr = a2Addr + c.StartJoin = []string{a1Addr + ":8946"} + c.NodeName = a2Name + c.Server = true + c.LogLevel = logLevel - c = NewConfig(args2) a2 := NewAgent(c, nil) a2.Start() @@ -124,32 +122,26 @@ func Test_processFilteredNodes(t *testing.T) { a1Addr := testutil.GetBindAddr().String() a2Addr := testutil.GetBindAddr().String() - args := []string{ - "-bind-addr", a1Addr, - "-join", a2Addr, - "-node-name", "test1", - "-server", - "-tag", "role=test", - "-log-level", logLevel, - } + c := DefaultConfig() + c.BindAddr = a1Addr + c.StartJoin = []string{a2Addr} + c.NodeName = "a1Name" + c.Server = true + c.LogLevel = logLevel - c := NewConfig(args) a1 := NewAgent(c, nil) a1.Start() time.Sleep(2 * time.Second) // Start another agent - args2 := []string{ - "-bind-addr", a2Addr, - "-join", a1Addr, - "-node-name", "test2", - "-server", - "-tag", "role=test", - "-log-level", logLevel, - } + c = DefaultConfig() + c.BindAddr = a2Addr + c.StartJoin = []string{a1Addr + ":8946"} + c.NodeName = "a2Name" + c.Server = true + c.LogLevel = logLevel - c = NewConfig(args2) a2 := NewAgent(c, nil) a2.Start() @@ -176,37 +168,15 @@ func Test_processFilteredNodes(t *testing.T) { a2.Stop() } -func Test_UnmarshalTags(t *testing.T) { - tagPairs := []string{ - "tag1=val1", - "tag2=val2", - } - - tags, err := UnmarshalTags(tagPairs) - - if err != nil { - t.Fatalf("err: %s", err) - } - - if v, ok := tags["tag1"]; !ok || v != "val1" { - t.Fatalf("bad: %v", tags) - } - if v, ok := tags["tag2"]; !ok || v != "val2" { - t.Fatalf("bad: %v", tags) - } -} - func TestEncrypt(t *testing.T) { - args := []string{ - "-bind-addr", testutil.GetBindAddr().String(), - "-node-name", "test1", - "-server", - "-tag", "role=test", - "-encrypt", "kPpdjphiipNSsjd4QHWbkA==", - "-log-level", logLevel, - } + c := DefaultConfig() + c.BindAddr = testutil.GetBindAddr().String() + c.NodeName = "test1" + c.Server = true + c.Tags = map[string]string{"role": "test"} + c.EncryptKey = "kPpdjphiipNSsjd4QHWbkA==" + c.LogLevel = logLevel - c := NewConfig(args) a := NewAgent(c, nil) a.Start() @@ -219,15 +189,13 @@ func TestEncrypt(t *testing.T) { func Test_getRPCAddr(t *testing.T) { a1Addr := testutil.GetBindAddr() - args := []string{ - "-bind-addr", a1Addr.String() + ":5000", - "-node-name", "test1", - "-server", - "-tag", "role=test", - "-log-level", logLevel, - } + c := DefaultConfig() + c.BindAddr = a1Addr.String() + ":5000" + c.NodeName = "test1" + c.Server = true + c.Tags = map[string]string{"role": "test"} + c.LogLevel = logLevel - c := NewConfig(args) a := NewAgent(c, nil) a.Start() @@ -242,13 +210,12 @@ func Test_getRPCAddr(t *testing.T) { func TestAgentConfig(t *testing.T) { advAddr := testutil.GetBindAddr().String() - args := []string{ - "-bind-addr", testutil.GetBindAddr().String(), - "-advertise-addr", advAddr, - "-log-level", logLevel, - } - c := NewConfig(args) + c := DefaultConfig() + c.BindAddr = testutil.GetBindAddr().String() + c.AdvertiseAddr = advAddr + c.LogLevel = logLevel + a := NewAgent(c, nil) a.Start() diff --git a/dkron/api_test.go b/dkron/api_test.go index a84dd6f70..7c9b04b38 100644 --- a/dkron/api_test.go +++ b/dkron/api_test.go @@ -13,16 +13,14 @@ import ( ) func setupAPITest(t *testing.T) (a *Agent) { - args := []string{ - "-bind-addr", testutil.GetBindAddr().String(), - "-http-addr", "127.0.0.1:8090", - "-node-name", "test", - "-server", - "-log-level", logLevel, - "-keyspace", "dkron-test", - } + c := DefaultConfig() + c.BindAddr = testutil.GetBindAddr().String() + c.HTTPAddr = "127.0.0.1:8090" + c.NodeName = "test" + c.Server = true + c.LogLevel = logLevel + c.Keyspace = "dkron-test" - c := NewConfig(args) a = NewAgent(c, nil) a.Start() diff --git a/dkron/config.go b/dkron/config.go index 2abd427f4..70c9be830 100644 --- a/dkron/config.go +++ b/dkron/config.go @@ -30,8 +30,8 @@ type Config struct { KeyringFile string `mapstructure:"keyring-file"` RejoinAfterLeave bool `mapstructure:"rejoin-after-leave"` Server bool - EncryptKey string `mapstructure:"encrypt-key"` - StartJoin AppendSliceValue `mapstructure:"start-join"` + EncryptKey string `mapstructure:"encrypt-key"` + StartJoin []string `mapstructure:"start-join"` Keyspace string RPCPort int `mapstructure:"rpc-port"` AdvertiseRPCPort int `mapstructure:"advertise-rpc-port"` @@ -61,31 +61,47 @@ type Config struct { // DefaultBindPort is the default port that dkron will use for Serf communication const DefaultBindPort int = 8946 -// configFlagSet creates all of our configuration flags. -func ConfigFlagSet() *flag.FlagSet { +func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { log.Panic(err) } + return &Config{ + NodeName: hostname, + BindAddr: fmt.Sprintf("0.0.0.0:%d", DefaultBindPort), + HTTPAddr: ":8080", + Discover: "dkron", + Backend: "etcd", + BackendMachines: []string{"127.0.0.1:2379"}, + Profile: "lan", + Keyspace: "dkron", + LogLevel: "info", + RPCPort: 6868, + MailSubjectPrefix: "[Dkron]", + } +} + +// configFlagSet creates all of our configuration flags. +func ConfigFlagSet() *flag.FlagSet { + c := DefaultConfig() cmdFlags := flag.NewFlagSet("agent flagset", flag.ContinueOnError) cmdFlags.Bool("server", false, "start dkron server") - cmdFlags.String("node-name", hostname, "node name") - cmdFlags.String("bind", fmt.Sprintf("0.0.0.0:%d", DefaultBindPort), "[Deprecated use bind-addr]") - cmdFlags.String("bind-addr", fmt.Sprintf("0.0.0.0:%d", DefaultBindPort), "address to bind listeners to") + cmdFlags.String("node-name", c.NodeName, "node name") + cmdFlags.String("bind-addr", c.BindAddr, "address to bind listeners to") cmdFlags.String("advertise-addr", "", "address to advertise to other nodes") - cmdFlags.String("http-addr", ":8080", "HTTP address") - cmdFlags.String("discover", "dkron", "mDNS discovery name") - cmdFlags.String("backend", "etcd", "store backend") - cmdFlags.StringSlice("backend-machine", []string{"127.0.0.1:2379"}, "store backend machines addresses") - cmdFlags.String("profile", "lan", "timing profile to use (lan, wan, local)") + cmdFlags.String("http-addr", c.HTTPAddr, "HTTP address") + cmdFlags.String("discover", c.Discover, "mDNS discovery name") + cmdFlags.String("backend", c.Backend, "store backend") + cmdFlags.StringSlice("backend-machine", c.BackendMachines, "store backend machines addresses") + cmdFlags.String("profile", c.Profile, "timing profile to use (lan, wan, local)") cmdFlags.StringSlice("join", []string{}, "address of agent to join on startup") cmdFlags.StringSlice("tag", []string{}, "tag pair, specified as key=value") - cmdFlags.String("keyspace", "dkron", "key namespace to use") + cmdFlags.String("keyspace", c.Keyspace, "key namespace to use") cmdFlags.String("encrypt", "", "encryption key") - cmdFlags.String("log-level", "info", "Log level (debug, info, warn, error, fatal, panic), defaults to info") - cmdFlags.Int("rpc-port", 6868, "RPC port") + cmdFlags.String("log-level", c.LogLevel, "Log level (debug, info, warn, error, fatal, panic), defaults to info") + cmdFlags.Int("rpc-port", c.RPCPort, "RPC port") cmdFlags.Int("advertise-rpc-port", 0, "advertise RPC port") // Notifications @@ -95,7 +111,7 @@ func ConfigFlagSet() *flag.FlagSet { cmdFlags.String("mail-password", "", "password of the mail server") cmdFlags.String("mail-from", "", "notification emails from address") cmdFlags.String("mail-payload", "", "notification mail payload") - cmdFlags.String("mail-subject-prefix", "[Dkron]", "notification mail subject prefix") + cmdFlags.String("mail-subject-prefix", c.MailSubjectPrefix, "notification mail subject prefix") cmdFlags.String("webhook-url", "", "notification webhook url") cmdFlags.String("webhook-payload", "", "notification webhook payload") diff --git a/dkron/config_test.go b/dkron/config_test.go index 8b10abd4b..25f2a0491 100644 --- a/dkron/config_test.go +++ b/dkron/config_test.go @@ -1,34 +1,11 @@ package dkron import ( - "bytes" "testing" - - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" ) -func TestReadConfigTags(t *testing.T) { - - viper.Reset() - viper.SetConfigType("json") - var jsonConfig = []byte(`{ - "tags": { - "foo": "bar" - } - }`) - viper.ReadConfig(bytes.NewBuffer(jsonConfig)) - config := ReadConfig() - t.Log(config.Tags) - assert.Equal(t, "bar", config.Tags["foo"]) - - viper.Set("tag", []string{"monthy=python"}) - config = ReadConfig() - assert.NotContains(t, config.Tags, "foo") - assert.Contains(t, config.Tags, "monthy") - assert.Equal(t, "python", config.Tags["monthy"]) +func TestNetworkInterface(t *testing.T) { +} - config = NewConfig([]string{"-tag", "t1=v1", "-tag", "t2=v2"}) - assert.Equal(t, "v1", config.Tags["t1"]) - assert.Equal(t, "v2", config.Tags["t2"]) +func TestEncryptBytes(t *testing.T) { } diff --git a/dkron/flag_slice_value.go b/dkron/flag_slice_value.go deleted file mode 100644 index 89c6f0b9b..000000000 --- a/dkron/flag_slice_value.go +++ /dev/null @@ -1,21 +0,0 @@ -package dkron - -import "strings" - -// AppendSliceValue implements the flag.Value interface and allows multiple -// calls to the same variable to append a list. -type AppendSliceValue []string - -func (s *AppendSliceValue) String() string { - return strings.Join(*s, ",") -} - -// Set allows setting a flag value with multiple values in a slice. -func (s *AppendSliceValue) Set(value string) error { - if *s == nil { - *s = make([]string, 0, 1) - } - - *s = append(*s, value) - return nil -} diff --git a/dkron/flag_slice_value_test.go b/dkron/flag_slice_value_test.go deleted file mode 100644 index 6e0e80cde..000000000 --- a/dkron/flag_slice_value_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package dkron - -import ( - "flag" - "reflect" - "testing" -) - -func TestAppendSliceValue_implements(t *testing.T) { - var raw interface{} - raw = new(AppendSliceValue) - if _, ok := raw.(flag.Value); !ok { - t.Fatalf("AppendSliceValue should be a Value") - } -} - -func TestAppendSliceValueSet(t *testing.T) { - sv := new(AppendSliceValue) - err := sv.Set("foo") - if err != nil { - t.Fatalf("err: %s", err) - } - - err = sv.Set("bar") - if err != nil { - t.Fatalf("err: %s", err) - } - - expected := []string{"foo", "bar"} - if !reflect.DeepEqual([]string(*sv), expected) { - t.Fatalf("Bad: %#v", sv) - } -} diff --git a/dkron/grpc_test.go b/dkron/grpc_test.go index ca1496b88..c8700f7be 100644 --- a/dkron/grpc_test.go +++ b/dkron/grpc_test.go @@ -21,16 +21,14 @@ func TestGRPCExecutionDone(t *testing.T) { aAddr := testutil.GetBindAddr().String() - args := []string{ - "-bind-addr", aAddr, - "-backend-machine", etcdAddr, - "-node-name", "test1", - "-server", - "-keyspace", "dkron", - "-log-level", logLevel, - } + c := DefaultConfig() + c.BindAddr = aAddr + c.BackendMachines = []string{etcdAddr} + c.NodeName = "test1" + c.Server = true + c.LogLevel = logLevel + c.Keyspace = "dkron" - c := NewConfig(args) a := NewAgent(c, nil) a.Start()