func stop(path string, controller confab.Controller, agentClient *agent.Client) { rpcClient, err := consulagent.NewRPCClient("localhost:8400") if err != nil { stderr.Printf("error connecting to RPC server: %s", err) exit(controller, 1) } agentClient.ConsulRPCClient = &agent.RPCClient{*rpcClient} stderr.Printf("stopping agent") controller.StopAgent() stderr.Printf("stopped agent") }
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") } }
for i := 0; i < 9; i++ { agentClient.VerifyJoinedCalls.Returns.Errors[i] = errors.New("some error") } agentClient.VerifyJoinedCalls.Returns.Errors[9] = errors.New("the final error") Expect(controller.BootAgent()).To(MatchError("the final error")) Expect(agentClient.VerifyJoinedCalls.CallCount).To(Equal(10)) Expect(agentClient.VerifySyncedCalls.CallCount).To(Equal(0)) }) }) }) Describe("StopAgent", func() { It("tells client to leave the cluster", func() { Expect(controller.StopAgent()).To(Succeed()) Expect(agentClient.LeaveCall.CallCount).To(Equal(1)) }) It("waits for the agent to stop", func() { Expect(controller.StopAgent()).To(Succeed()) Expect(agentRunner.WaitCall.CallCount).To(Equal(1)) }) Context("when the agent client Leave() returns an error", func() { BeforeEach(func() { agentClient.LeaveCall.Returns.Error = errors.New("leave error") }) It("tells the runner to stop the agent", func() { Expect(controller.StopAgent()).To(Succeed()) Expect(agentRunner.StopCall.CallCount).To(Equal(1))
}, { Action: "controller.boot-agent.verify-joined", }, { Action: "controller.boot-agent.verify-joined.failed", Error: errors.New("timeout exceeded"), }, })) }) }) }) Describe("StopAgent", func() { It("tells client to leave the cluster and waits for the agent to stop", func() { controller.StopAgent() Expect(agentClient.LeaveCall.CallCount).To(Equal(1)) Expect(agentRunner.WaitCall.CallCount).To(Equal(1)) Expect(agentRunner.CleanupCall.CallCount).To(Equal(1)) Expect(logger.Messages).To(ContainSequence([]fakes.LoggerMessage{ { Action: "controller.stop-agent.leave", }, { Action: "controller.stop-agent.wait", }, { Action: "controller.stop-agent.cleanup", }, { Action: "controller.stop-agent.success",
func exit(controller confab.Controller, code int) { controller.StopAgent() os.Exit(code) }