Simplify Address handling for Etcd
For Etcd, make the address it should listen on configurable via
```
ectd := &Etcd{
  Address: &url.URL{Scheme: "http", Host: "localhost:12345"},
}
```
If not specified, it will internally use the `DefaultAddressManager` do
find a free port to listen on.
			
			
This commit is contained in:
		
							parent
							
								
									f370ccb496
								
							
						
					
					
						commit
						32821b2077
					
				|  | @ -6,6 +6,8 @@ import ( | |||
| 	"os/exec" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"net/url" | ||||
| 
 | ||||
| 	"github.com/onsi/gomega/gbytes" | ||||
| 	"github.com/onsi/gomega/gexec" | ||||
| ) | ||||
|  | @ -15,7 +17,7 @@ import ( | |||
| // The documentation and examples for the Etcd's properties can be found in
 | ||||
| // in the documentation for the `APIServer`, as both implement a `ControlPaneProcess`.
 | ||||
| type Etcd struct { | ||||
| 	AddressManager AddressManager | ||||
| 	Address        *url.URL | ||||
| 	Path           string | ||||
| 	ProcessStarter SimpleSessionStarter | ||||
| 	DataDir        *Directory | ||||
|  | @ -43,18 +45,10 @@ type SimpleSessionStarter func(command *exec.Cmd, out, err io.Writer) (SimpleSes | |||
| 
 | ||||
| // URL returns the URL Etcd is listening on. Clients can use this to connect to Etcd.
 | ||||
| func (e *Etcd) URL() (string, error) { | ||||
| 	if e.AddressManager == nil { | ||||
| 		return "", fmt.Errorf("Etcd's AddressManager is not initialized") | ||||
| 	if e.Address == nil { | ||||
| 		return "", fmt.Errorf("Etcd's Address not initialized or configured") | ||||
| 	} | ||||
| 	port, err := e.AddressManager.Port() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	host, err := e.AddressManager.Host() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return fmt.Sprintf("http://%s:%d", host, port), nil | ||||
| 	return e.Address.String(), nil | ||||
| } | ||||
| 
 | ||||
| // Start starts the etcd, waits for it to come up, and returns an error, if occoured.
 | ||||
|  | @ -64,22 +58,16 @@ func (e *Etcd) Start() error { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	port, host, err := e.AddressManager.Initialize() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	clientURL := fmt.Sprintf("http://%s:%d", host, port) | ||||
| 	args := []string{ | ||||
| 		"--debug", | ||||
| 		"--listen-peer-urls=http://localhost:0", | ||||
| 		fmt.Sprintf("--advertise-client-urls=%s", clientURL), | ||||
| 		fmt.Sprintf("--listen-client-urls=%s", clientURL), | ||||
| 		fmt.Sprintf("--advertise-client-urls=%s", e.Address), | ||||
| 		fmt.Sprintf("--listen-client-urls=%s", e.Address), | ||||
| 		fmt.Sprintf("--data-dir=%s", e.DataDir.Path), | ||||
| 	} | ||||
| 
 | ||||
| 	detectedStart := e.stdErr.Detect(fmt.Sprintf( | ||||
| 		"serving insecure client requests on %s", host)) | ||||
| 		"serving insecure client requests on %s", e.Address.Hostname())) | ||||
| 	timedOut := time.After(e.StartTimeout) | ||||
| 
 | ||||
| 	command := exec.Command(e.Path, args...) | ||||
|  | @ -100,9 +88,17 @@ func (e *Etcd) ensureInitialized() error { | |||
| 	if e.Path == "" { | ||||
| 		e.Path = DefaultBinPathFinder("etcd") | ||||
| 	} | ||||
| 	if e.Address == nil { | ||||
| 		am := &DefaultAddressManager{} | ||||
| 		port, host, err := am.Initialize() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 	if e.AddressManager == nil { | ||||
| 		e.AddressManager = &DefaultAddressManager{} | ||||
| 		e.Address = &url.URL{ | ||||
| 			Scheme: "http", | ||||
| 			Host:   fmt.Sprintf("%s:%d", host, port), | ||||
| 		} | ||||
| 	} | ||||
| 	if e.ProcessStarter == nil { | ||||
| 		e.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ import ( | |||
| 
 | ||||
| 	"time" | ||||
| 
 | ||||
| 	"net/url" | ||||
| 
 | ||||
| 	. "github.com/onsi/ginkgo" | ||||
| 	. "github.com/onsi/gomega" | ||||
| 	"github.com/onsi/gomega/gbytes" | ||||
|  | @ -18,7 +20,6 @@ import ( | |||
| var _ = Describe("Etcd", func() { | ||||
| 	var ( | ||||
| 		fakeSession         *testfakes.FakeSimpleSession | ||||
| 		fakeAddressManager  *testfakes.FakeAddressManager | ||||
| 		etcd                *Etcd | ||||
| 		etcdStopper         chan struct{} | ||||
| 		dataDirCleanupCount int | ||||
|  | @ -26,7 +27,6 @@ var _ = Describe("Etcd", func() { | |||
| 
 | ||||
| 	BeforeEach(func() { | ||||
| 		fakeSession = &testfakes.FakeSimpleSession{} | ||||
| 		fakeAddressManager = &testfakes.FakeAddressManager{} | ||||
| 
 | ||||
| 		etcdStopper = make(chan struct{}, 1) | ||||
| 		fakeSession.TerminateReturns(&gexec.Session{ | ||||
|  | @ -35,7 +35,6 @@ var _ = Describe("Etcd", func() { | |||
| 		close(etcdStopper) | ||||
| 
 | ||||
| 		etcd = &Etcd{ | ||||
| 			AddressManager: fakeAddressManager, | ||||
| 			Path: "/path/to/some/etcd", | ||||
| 			DataDir: &Directory{ | ||||
| 				Path: "/path/to/some/etcd", | ||||
|  | @ -58,7 +57,7 @@ var _ = Describe("Etcd", func() { | |||
| 				fakeSession.ExitCodeReturnsOnCall(0, -1) | ||||
| 				fakeSession.ExitCodeReturnsOnCall(1, 143) | ||||
| 
 | ||||
| 				fakeAddressManager.InitializeReturns(1234, "this.is.etcd.listening.for.clients", nil) | ||||
| 				etcd.Address = &url.URL{Scheme: "http", Host: "this.is.etcd.listening.for.clients:1234"} | ||||
| 
 | ||||
| 				etcd.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
| 					Expect(command.Args).To(ContainElement(fmt.Sprintf("--advertise-client-urls=http://%s:%d", "this.is.etcd.listening.for.clients", 1234))) | ||||
|  | @ -72,9 +71,6 @@ var _ = Describe("Etcd", func() { | |||
| 				err := etcd.Start() | ||||
| 				Expect(err).NotTo(HaveOccurred()) | ||||
| 
 | ||||
| 				By("...in turn calling using the AddressManager") | ||||
| 				Expect(fakeAddressManager.InitializeCallCount()).To(Equal(1)) | ||||
| 
 | ||||
| 				Eventually(etcd).Should(gbytes.Say("Everything is dandy")) | ||||
| 				Expect(fakeSession.ExitCodeCallCount()).To(Equal(0)) | ||||
| 				Expect(etcd).NotTo(gexec.Exit()) | ||||
|  | @ -95,7 +91,7 @@ var _ = Describe("Etcd", func() { | |||
| 				etcd.DataDir.Cleanup = func() error { | ||||
| 					return fmt.Errorf("destroy failed") | ||||
| 				} | ||||
| 				fakeAddressManager.InitializeReturns(1234, "this.is.etcd", nil) | ||||
| 				etcd.Address = &url.URL{Scheme: "http", Host: "this.is.etcd:1234"} | ||||
| 				etcd.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
| 					fmt.Fprint(err, "serving insecure client requests on this.is.etcd:1234") | ||||
| 					return fakeSession, nil | ||||
|  | @ -110,7 +106,7 @@ var _ = Describe("Etcd", func() { | |||
| 		Context("when there is no function to cleanup the data directory", func() { | ||||
| 			It("does not panic", func() { | ||||
| 				etcd.DataDir.Cleanup = nil | ||||
| 				fakeAddressManager.InitializeReturns(1234, "this.is.etcd", nil) | ||||
| 				etcd.Address = &url.URL{Scheme: "http", Host: "this.is.etcd:1234"} | ||||
| 				etcd.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
| 					fmt.Fprint(err, "serving insecure client requests on this.is.etcd:1234") | ||||
| 					return fakeSession, nil | ||||
|  | @ -126,20 +122,6 @@ var _ = Describe("Etcd", func() { | |||
| 			}) | ||||
| 		}) | ||||
| 
 | ||||
| 		Context("when the address manager fails to get a new address", func() { | ||||
| 			It("propagates the error and does not start any process", func() { | ||||
| 				fakeAddressManager.InitializeReturns(0, "", fmt.Errorf("some error finding a free port")) | ||||
| 
 | ||||
| 				etcd.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
| 					Expect(true).To(BeFalse(), | ||||
| 						"the etcd process starter shouldn't be called if getting a free port fails") | ||||
| 					return nil, nil | ||||
| 				} | ||||
| 
 | ||||
| 				Expect(etcd.Start()).To(MatchError(ContainSubstring("some error finding a free port"))) | ||||
| 			}) | ||||
| 		}) | ||||
| 
 | ||||
| 		Context("when  the starter returns an error", func() { | ||||
| 			It("propagates the error", func() { | ||||
| 				etcd.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
|  | @ -181,7 +163,7 @@ var _ = Describe("Etcd", func() { | |||
| 				}) | ||||
| 			}) | ||||
| 			It("propagates the error", func() { | ||||
| 				fakeAddressManager.InitializeReturns(1234, "this.is.etcd", nil) | ||||
| 				etcd.Address = &url.URL{Scheme: "http", Host: "this.is.etcd:1234"} | ||||
| 
 | ||||
| 				etcd.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) { | ||||
| 					fmt.Fprint(err, "serving insecure client requests on this.is.etcd:1234") | ||||
|  | @ -197,26 +179,11 @@ var _ = Describe("Etcd", func() { | |||
| 
 | ||||
| 	Describe("querying the server for its URL", func() { | ||||
| 		It("can be queried for the URL it listens on", func() { | ||||
| 			fakeAddressManager.HostReturns("the.host.for.etcd", nil) | ||||
| 			fakeAddressManager.PortReturns(6789, nil) | ||||
| 			etcd.Address = &url.URL{Scheme: "http", Host: "the.host.for.etcd:6789"} | ||||
| 			apiServerURL, err := etcd.URL() | ||||
| 			Expect(err).NotTo(HaveOccurred()) | ||||
| 			Expect(apiServerURL).To(Equal("http://the.host.for.etcd:6789")) | ||||
| 		}) | ||||
| 		Context("when the addressmanager fails to give us a port", func() { | ||||
| 			It("propagates the failure", func() { | ||||
| 				fakeAddressManager.PortReturns(0, fmt.Errorf("zort")) | ||||
| 				_, err := etcd.URL() | ||||
| 				Expect(err).To(MatchError(ContainSubstring("zort"))) | ||||
| 			}) | ||||
| 		}) | ||||
| 		Context("when the addressmanager fails to give us a host", func() { | ||||
| 			It("propagates the failure", func() { | ||||
| 				fakeAddressManager.HostReturns("", fmt.Errorf("bam!")) | ||||
| 				_, err := etcd.URL() | ||||
| 				Expect(err).To(MatchError(ContainSubstring("bam!"))) | ||||
| 			}) | ||||
| 		}) | ||||
| 		Context("before starting etcd", func() { | ||||
| 			Context("and therefore the addressmanager has not been initialized", func() { | ||||
| 				BeforeEach(func() { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue