func start(flagSet *flag.FlagSet, path string, controller confab.Controller, agentClient *confab.AgentClient) { timeout := confab.NewTimeout(time.After(time.Duration(controller.Config.Confab.TimeoutInSeconds) * time.Second)) _, err := os.Stat(controller.Config.Path.ConsulConfigDir) if err != nil { printUsageAndExit(fmt.Sprintf("\"consul_config_dir\" %q could not be found", controller.Config.Path.ConsulConfigDir), flagSet) } if len(agentClient.ExpectedMembers) == 0 { printUsageAndExit("at least one \"expected-member\" must be provided", flagSet) } err = controller.WriteServiceDefinitions() if err != nil { stderr.Printf("error writing service definitions: %s", err) os.Exit(1) } err = controller.BootAgent(timeout) if err != nil { stderr.Printf("error booting consul agent: %s", err) // DO NOT call StopAgent: // - the agent may aleady be running // - the pidfile may contain the PID of another running process os.Exit(1) } if controller.Config.Consul.Agent.Server { configureServer(controller, agentClient, timeout) } else { configureClient(controller) } }
func start(flagSet *flag.FlagSet, path string, controller confab.Controller, agentClient *agent.Client) { timeout := confab.NewTimeout(time.After(time.Duration(controller.Config.Confab.TimeoutInSeconds) * time.Second)) _, err := os.Stat(controller.Config.Path.ConsulConfigDir) if err != nil { printUsageAndExit(fmt.Sprintf("\"consul_config_dir\" %q could not be found", controller.Config.Path.ConsulConfigDir), flagSet) } if len(agentClient.ExpectedMembers) == 0 { printUsageAndExit("at least one \"expected-member\" must be provided", flagSet) } err = controller.WriteConsulConfig() if err != nil { stderr.Printf("error writing consul config file: %s", err) os.Exit(1) } err = controller.WriteServiceDefinitions() if err != nil { stderr.Printf("error writing service definitions: %s", err) os.Exit(1) } err = controller.BootAgent(timeout) if err != nil { stderr.Printf("error booting consul agent: %s", err) exit(controller, 1) } if controller.Config.Consul.Agent.Mode == "server" { configureServer(controller, agentClient, timeout) } else { configureClient(controller) } }
func main() { flagSet := flag.NewFlagSet("flags", flag.ContinueOnError) flagSet.BoolVar(&isServer, "server", false, "whether to start the agent in server mode") flagSet.StringVar(&agentPath, "agent-path", "", "path to the on-filesystem consul `executable`") flagSet.StringVar(&consulConfigDir, "consul-config-dir", "", "path to consul configuration `directory`") flagSet.StringVar(&pidFile, "pid-file", "", "path to consul PID `file`") flagSet.Var(&expectedMembers, "expected-member", "address `list` of the expected members") flagSet.Var(&encryptionKeys, "encryption-key", "`key` used to encrypt consul traffic") if len(os.Args) < 2 { printUsageAndExit("invalid number of arguments", flagSet) } command := os.Args[1] if !validCommand(command) { printUsageAndExit(fmt.Sprintf("invalid COMMAND %q", command), flagSet) } flagSet.Parse(os.Args[2:]) path, err := exec.LookPath(agentPath) if err != nil { printUsageAndExit(fmt.Sprintf("\"agent-path\" %q cannot be found", agentPath), flagSet) } if len(pidFile) == 0 { printUsageAndExit("\"pid-file\" cannot be empty", flagSet) } if command == "start" { _, err = os.Stat(consulConfigDir) if err != nil { printUsageAndExit(fmt.Sprintf("\"consul-config-dir\" %q could not be found", consulConfigDir), flagSet) } if len(expectedMembers) == 0 { printUsageAndExit("at least one \"expected-member\" must be provided", flagSet) } agentRunner := confab.AgentRunner{ Path: path, PIDFile: pidFile, ConfigDir: consulConfigDir, Stdout: os.Stdout, Stderr: os.Stderr, } consulAPIClient, err := api.NewClient(api.DefaultConfig()) if err != nil { panic(err) // not tested, NewClient never errors } agentClient := confab.AgentClient{ ExpectedMembers: expectedMembers, ConsulAPIAgent: consulAPIClient.Agent(), ConsulRPCClient: nil, } controller := confab.Controller{ AgentRunner: &agentRunner, AgentClient: &agentClient, MaxRetries: 10, SyncRetryDelay: 1 * time.Second, SyncRetryClock: clock.NewClock(), EncryptKeys: encryptionKeys, SSLDisabled: false, Logger: stdout, } err = controller.BootAgent() if err != nil { stderr.Printf("error booting consul agent: %s", err) os.Exit(1) } if !isServer { return } rpcClient, err := agent.NewRPCClient("localhost:8400") if err != nil { stderr.Printf("error connecting to RPC server: %s", err) os.Exit(1) } agentClient.ConsulRPCClient = &confab.RPCClient{ *rpcClient, } err = controller.ConfigureServer() if err != nil { stderr.Printf("error connecting to RPC server: %s", err) os.Exit(1) // not tested; it is challenging with the current fake agent. } } if command == "stop" { agentRunner := confab.AgentRunner{ Path: path, PIDFile: pidFile, ConfigDir: "", Stdout: os.Stdout, Stderr: os.Stderr, } consulAPIClient, err := api.NewClient(api.DefaultConfig()) if err != nil { panic(err) // not tested, NewClient never errors } agentClient := confab.AgentClient{ ExpectedMembers: nil, ConsulAPIAgent: consulAPIClient.Agent(), ConsulRPCClient: nil, } controller := confab.Controller{ AgentRunner: &agentRunner, AgentClient: &agentClient, MaxRetries: 10, SyncRetryDelay: 1 * time.Second, SyncRetryClock: clock.NewClock(), EncryptKeys: nil, SSLDisabled: false, Logger: stdout, } rpcClient, err := agent.NewRPCClient("localhost:8400") if err != nil { stderr.Printf("error connecting to RPC server: %s", err) os.Exit(1) } agentClient.ConsulRPCClient = &confab.RPCClient{ *rpcClient, } stdout.Printf("MAIN: stopping agent") err = controller.StopAgent() if err != nil { stderr.Printf("error stopping agent: %s", err) os.Exit(1) } stdout.Printf("MAIN: stopped agent") } }
logBuffer = &bytes.Buffer{} controller = confab.Controller{ AgentClient: agentClient, AgentRunner: agentRunner, MaxRetries: 10, SyncRetryDelay: 10 * time.Millisecond, SyncRetryClock: clock, EncryptKeys: []string{"key 1", "key 2", "key 3"}, Logger: log.New(logBuffer, "[Test]", 0), } }) Describe("BootAgent", func() { It("launches the consul agent", func() { Expect(controller.BootAgent()).To(Succeed()) Expect(agentRunner.RunCalls.CallCount).To(Equal(1)) }) It("checks that the agent has joined a cluster", func() { Expect(controller.BootAgent()).To(Succeed()) Expect(agentClient.VerifyJoinedCalls.CallCount).To(Equal(1)) }) Context("when starting the agent fails", func() { It("immediately returns an error", func() { agentRunner.RunCalls.Returns.Errors = []error{errors.New("some error")} Expect(controller.BootAgent()).To(MatchError("some error")) Expect(agentRunner.RunCalls.CallCount).To(Equal(1)) Expect(agentClient.VerifyJoinedCalls.CallCount).To(Equal(0))
}, { Action: "controller.write-service-definitions.write", }, { Action: "controller.write-service-definitions.write.failed", Error: errors.New("write definitions error"), }, })) }) }) }) Describe("BootAgent", func() { It("launches the consul agent and confirms that it joined the cluster", func() { Expect(controller.BootAgent(confab.NewTimeout(make(chan time.Time)))).To(Succeed()) Expect(agentRunner.RunCalls.CallCount).To(Equal(1)) Expect(agentClient.VerifyJoinedCalls.CallCount).To(Equal(1)) Expect(logger.Messages).To(ContainSequence([]fakes.LoggerMessage{ { Action: "controller.boot-agent.run", }, { Action: "controller.boot-agent.verify-joined", }, { Action: "controller.boot-agent.success", }, })) })