Make APIServer manage its own port allocations
This means we will no longer need to pass a free port into the APIServer constructor.
This commit is contained in:
parent
d62ff04228
commit
657963b319
|
|
@ -3,7 +3,6 @@ package test
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
|
|
@ -14,6 +13,7 @@ import (
|
|||
|
||||
// APIServer knows how to run a kubernetes apiserver. Set it up with the path to a precompiled binary.
|
||||
type APIServer struct {
|
||||
AddressManager AddressManager
|
||||
PathFinder BinPathFinder
|
||||
ProcessStarter simpleSessionStarter
|
||||
CertDirManager certDirManager
|
||||
|
|
@ -52,7 +52,10 @@ func NewAPIServer(config *APIServerConfig) (*APIServer, error) {
|
|||
|
||||
// URL returns the URL APIServer is listening on. Clients can use this to connect to APIServer.
|
||||
func (s *APIServer) URL() string {
|
||||
return s.Config.APIServerURL
|
||||
// TODO handle errors
|
||||
port, _ := s.AddressManager.Port()
|
||||
host, _ := s.AddressManager.Host()
|
||||
return fmt.Sprintf("http://%s:%d", host, port)
|
||||
}
|
||||
|
||||
// Start starts the apiserver, waits for it to come up, and returns an error, if occoured.
|
||||
|
|
@ -60,28 +63,31 @@ func (s *APIServer) Start() error {
|
|||
if s.PathFinder == nil {
|
||||
s.PathFinder = DefaultBinPathFinder
|
||||
}
|
||||
if s.AddressManager == nil {
|
||||
s.AddressManager = &DefaultAddressManager{}
|
||||
}
|
||||
if err := s.Config.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := s.Etcd.Start()
|
||||
port, addr, err := s.AddressManager.Initialize("localhost")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.stdOut = gbytes.NewBuffer()
|
||||
s.stdErr = gbytes.NewBuffer()
|
||||
|
||||
certDir, err := s.CertDirManager.Create()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientURL, err := url.Parse(s.Config.APIServerURL)
|
||||
err = s.Etcd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.stdOut = gbytes.NewBuffer()
|
||||
s.stdErr = gbytes.NewBuffer()
|
||||
|
||||
args := []string{
|
||||
"--authorization-mode=Node,RBAC",
|
||||
"--runtime-config=admissionregistration.k8s.io/v1alpha1",
|
||||
|
|
@ -92,11 +98,11 @@ func (s *APIServer) Start() error {
|
|||
"--storage-backend=etcd3",
|
||||
fmt.Sprintf("--etcd-servers=%s", s.Etcd.URL()),
|
||||
fmt.Sprintf("--cert-dir=%s", certDir),
|
||||
fmt.Sprintf("--insecure-port=%s", clientURL.Port()),
|
||||
fmt.Sprintf("--insecure-bind-address=%s", clientURL.Hostname()),
|
||||
fmt.Sprintf("--insecure-port=%d", port),
|
||||
fmt.Sprintf("--insecure-bind-address=%s", addr),
|
||||
}
|
||||
|
||||
detectedStart := s.stdErr.Detect(fmt.Sprintf("Serving insecurely on %s", clientURL.Host))
|
||||
detectedStart := s.stdErr.Detect(fmt.Sprintf("Serving insecurely on %s:%d", addr, port))
|
||||
timedOut := time.After(20 * time.Second)
|
||||
|
||||
command := exec.Command(s.PathFinder("kube-apiserver"), args...)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import "github.com/asaskevich/govalidator"
|
|||
|
||||
// APIServerConfig is a struct holding data to configure the API Server process
|
||||
type APIServerConfig struct {
|
||||
APIServerURL string `valid:"required,url"`
|
||||
APIServerURL string `valid:"url"`
|
||||
}
|
||||
|
||||
// Validate checks that the config contains only valid URLs
|
||||
|
|
|
|||
|
|
@ -16,12 +16,6 @@ var _ = Describe("APIServerConfig", func() {
|
|||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("errors on empty config", func() {
|
||||
conf := &APIServerConfig{}
|
||||
err := conf.Validate()
|
||||
Expect(err).To(MatchError(ContainSubstring("APIServerURL: non zero value required")))
|
||||
})
|
||||
|
||||
It("errors on malformed URLs", func() {
|
||||
conf := &APIServerConfig{
|
||||
APIServerURL: "something not URLish",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ var _ = Describe("Apiserver", func() {
|
|||
apiServerConfig *APIServerConfig
|
||||
fakeEtcdProcess *testfakes.FakeFixtureProcess
|
||||
fakePathFinder *testfakes.FakeBinPathFinder
|
||||
fakeAddressManager *testfakes.FakeAddressManager
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
|
|
@ -30,11 +31,13 @@ var _ = Describe("Apiserver", func() {
|
|||
fakeCertDirManager = &testfakes.FakeCertDirManager{}
|
||||
fakeEtcdProcess = &testfakes.FakeFixtureProcess{}
|
||||
fakePathFinder = &testfakes.FakeBinPathFinder{}
|
||||
fakeAddressManager = &testfakes.FakeAddressManager{}
|
||||
|
||||
apiServerConfig = &APIServerConfig{
|
||||
APIServerURL: "http://this.is.the.API.server:8080",
|
||||
APIServerURL: "",
|
||||
}
|
||||
apiServer = &APIServer{
|
||||
AddressManager: fakeAddressManager,
|
||||
PathFinder: fakePathFinder.Spy,
|
||||
CertDirManager: fakeCertDirManager,
|
||||
Config: apiServerConfig,
|
||||
|
|
@ -42,104 +45,150 @@ var _ = Describe("Apiserver", func() {
|
|||
}
|
||||
})
|
||||
|
||||
It("can be queried for the URL it listens on", func() {
|
||||
Expect(apiServer.URL()).To(Equal("http://this.is.the.API.server:8080"))
|
||||
})
|
||||
Describe("starting and stopping the server", func() {
|
||||
Context("when given a path to a binary that runs for a long time", func() {
|
||||
It("can start and stop that binary", func() {
|
||||
sessionBuffer := gbytes.NewBuffer()
|
||||
fmt.Fprint(sessionBuffer, "Everything is fine")
|
||||
fakeSession.BufferReturns(sessionBuffer)
|
||||
|
||||
Context("when given a path to a binary that runs for a long time", func() {
|
||||
It("can start and stop that binary", func() {
|
||||
sessionBuffer := gbytes.NewBuffer()
|
||||
fmt.Fprint(sessionBuffer, "Everything is fine")
|
||||
fakeSession.BufferReturns(sessionBuffer)
|
||||
fakeSession.ExitCodeReturnsOnCall(0, -1)
|
||||
fakeSession.ExitCodeReturnsOnCall(1, 143)
|
||||
|
||||
fakeSession.ExitCodeReturnsOnCall(0, -1)
|
||||
fakeSession.ExitCodeReturnsOnCall(1, 143)
|
||||
fakePathFinder.Returns("/some/path/to/apiserver")
|
||||
fakeAddressManager.InitializeReturns(1234, "this.is.the.API.server", nil)
|
||||
|
||||
fakePathFinder.Returns("/some/path/to/apiserver")
|
||||
apiServer.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(command.Args).To(ContainElement("--insecure-port=1234"))
|
||||
Expect(command.Args).To(ContainElement("--insecure-bind-address=this.is.the.API.server"))
|
||||
Expect(command.Path).To(Equal("/some/path/to/apiserver"))
|
||||
fmt.Fprint(err, "Serving insecurely on this.is.the.API.server:1234")
|
||||
return fakeSession, nil
|
||||
}
|
||||
|
||||
apiServer.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(command.Path).To(Equal("/some/path/to/apiserver"))
|
||||
fmt.Fprint(err, "Serving insecurely on this.is.the.API.server:8080")
|
||||
return fakeSession, nil
|
||||
}
|
||||
By("Starting the API Server")
|
||||
err := apiServer.Start()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Starting the API Server")
|
||||
err := apiServer.Start()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
By("...in turn starting Etcd")
|
||||
Expect(fakeEtcdProcess.StartCallCount()).To(Equal(1),
|
||||
"the Etcd process should be started exactly once")
|
||||
|
||||
By("starting Etcd")
|
||||
Expect(fakeEtcdProcess.StartCallCount()).To(Equal(1),
|
||||
"the Etcd process should be started exactly once")
|
||||
By("...in turn calling the PathFinder")
|
||||
Expect(fakePathFinder.CallCount()).To(Equal(1))
|
||||
Expect(fakePathFinder.ArgsForCall(0)).To(Equal("kube-apiserver"))
|
||||
|
||||
By("...in turn calls the PathFinder")
|
||||
Expect(fakePathFinder.CallCount()).To(Equal(1))
|
||||
Expect(fakePathFinder.ArgsForCall(0)).To(Equal("kube-apiserver"))
|
||||
By("...in turn calling the PortFinder")
|
||||
Expect(fakeAddressManager.InitializeCallCount()).To(Equal(1))
|
||||
Expect(fakeAddressManager.InitializeArgsForCall(0)).To(Equal("localhost"))
|
||||
|
||||
Eventually(apiServer).Should(gbytes.Say("Everything is fine"))
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(0))
|
||||
Expect(apiServer).NotTo(gexec.Exit())
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(1))
|
||||
Expect(fakeCertDirManager.CreateCallCount()).To(Equal(1))
|
||||
Eventually(apiServer).Should(gbytes.Say("Everything is fine"))
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(0))
|
||||
Expect(apiServer).NotTo(gexec.Exit())
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(1))
|
||||
Expect(fakeCertDirManager.CreateCallCount()).To(Equal(1))
|
||||
|
||||
By("Stopping the API Server")
|
||||
apiServer.Stop()
|
||||
By("Stopping the API Server")
|
||||
apiServer.Stop()
|
||||
|
||||
Expect(fakeEtcdProcess.StopCallCount()).To(Equal(1))
|
||||
Expect(apiServer).To(gexec.Exit(143))
|
||||
Expect(fakeSession.TerminateCallCount()).To(Equal(1))
|
||||
Expect(fakeSession.WaitCallCount()).To(Equal(1))
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(2))
|
||||
Expect(fakeCertDirManager.DestroyCallCount()).To(Equal(1))
|
||||
Expect(fakeEtcdProcess.StopCallCount()).To(Equal(1))
|
||||
Expect(apiServer).To(gexec.Exit(143))
|
||||
Expect(fakeSession.TerminateCallCount()).To(Equal(1))
|
||||
Expect(fakeSession.WaitCallCount()).To(Equal(1))
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(2))
|
||||
Expect(fakeCertDirManager.DestroyCallCount()).To(Equal(1))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("when starting etcd fails", func() {
|
||||
It("propagates the error, and does not start the process", func() {
|
||||
fakeEtcdProcess.StartReturnsOnCall(0, fmt.Errorf("starting etcd failed"))
|
||||
apiServer.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(true).To(BeFalse(),
|
||||
"the api server process starter shouldn't be called if starting etcd fails")
|
||||
return nil, nil
|
||||
}
|
||||
Context("when starting etcd fails", func() {
|
||||
It("propagates the error, and does not start the process", func() {
|
||||
fakeEtcdProcess.StartReturnsOnCall(0, fmt.Errorf("starting etcd failed"))
|
||||
apiServer.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(true).To(BeFalse(),
|
||||
"the api server process starter shouldn't be called if starting etcd fails")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := apiServer.Start()
|
||||
Expect(err).To(MatchError(ContainSubstring("starting etcd failed")))
|
||||
err := apiServer.Start()
|
||||
Expect(err).To(MatchError(ContainSubstring("starting etcd failed")))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the certificate directory cannot be created", func() {
|
||||
It("propagates the error, and does not start the process", func() {
|
||||
fakeCertDirManager.CreateReturnsOnCall(0, "", fmt.Errorf("Error on cert directory creation."))
|
||||
Context("when the certificate directory cannot be created", func() {
|
||||
It("propagates the error, and does not start any process", func() {
|
||||
fakeCertDirManager.CreateReturnsOnCall(0, "", fmt.Errorf("Error on cert directory creation."))
|
||||
|
||||
apiServer.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(true).To(BeFalse(),
|
||||
"the api server process starter shouldn't be called if creating the cert dir fails")
|
||||
return nil, nil
|
||||
}
|
||||
apiServer.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(true).To(BeFalse(),
|
||||
"the api server process starter shouldn't be called if creating the cert dir fails")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := apiServer.Start()
|
||||
Expect(err).To(MatchError(ContainSubstring("Error on cert directory creation.")))
|
||||
err := apiServer.Start()
|
||||
Expect(err).To(MatchError(ContainSubstring("Error on cert directory creation.")))
|
||||
Expect(fakeEtcdProcess.StartCallCount()).To(Equal(0))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the starter returns an error", func() {
|
||||
It("propagates the error", func() {
|
||||
apiServer.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
return nil, fmt.Errorf("Some error in the apiserver starter.")
|
||||
}
|
||||
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"))
|
||||
|
||||
err := apiServer.Start()
|
||||
Expect(err).To(MatchError(ContainSubstring("Some error in the apiserver starter.")))
|
||||
apiServer.ProcessStarter = func(Command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
Expect(true).To(BeFalse(),
|
||||
"the api server process starter shouldn't be called if getting a free port fails")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
Expect(apiServer.Start()).To(MatchError(ContainSubstring("some error finding a free port")))
|
||||
Expect(fakeEtcdProcess.StartCallCount()).To(Equal(0))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the starter returns an error", func() {
|
||||
It("propagates the error", func() {
|
||||
apiServer.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
return nil, fmt.Errorf("Some error in the apiserver starter.")
|
||||
}
|
||||
|
||||
err := apiServer.Start()
|
||||
Expect(err).To(MatchError(ContainSubstring("Some error in the apiserver starter.")))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when we try to stop a server that hasn't been started", func() {
|
||||
It("is a noop and does not call exit on the session", func() {
|
||||
apiServer.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
return fakeSession, nil
|
||||
}
|
||||
apiServer.Stop()
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(0))
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("when we try to stop a server that hasn't been started", func() {
|
||||
It("is a noop and does not call exit on the session", func() {
|
||||
apiServer.ProcessStarter = func(command *exec.Cmd, out, err io.Writer) (SimpleSession, error) {
|
||||
return fakeSession, nil
|
||||
}
|
||||
apiServer.Stop()
|
||||
Expect(fakeSession.ExitCodeCallCount()).To(Equal(0))
|
||||
Describe("querying the server for its URL", func() {
|
||||
It("can be queried for the URL it listens on", func() {
|
||||
fakeAddressManager.HostReturns("the.host.for.api.server", nil)
|
||||
fakeAddressManager.PortReturns(5678, nil)
|
||||
Expect(apiServer.URL()).To(Equal("http://the.host.for.api.server:5678"))
|
||||
})
|
||||
|
||||
Context("when we query for the URL before starting the server", func() {
|
||||
|
||||
Context("and so the addressmanager fails to give us a port", func() {
|
||||
It("propagates the failure", func() {
|
||||
//TODO
|
||||
})
|
||||
})
|
||||
|
||||
Context("and so the addressmanager fails to give us a host", func() {
|
||||
It("propagates the failure", func() {
|
||||
//TODO
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,11 +5,70 @@ import (
|
|||
"net"
|
||||
)
|
||||
|
||||
// AddressManager knows how to generate and remember a single address on some
|
||||
// local interface for a service to listen on.
|
||||
type AddressManager interface {
|
||||
Initialize(host string) (port int, resolvedAddress string, err error)
|
||||
Host() (string, error)
|
||||
Port() (int, error)
|
||||
}
|
||||
|
||||
//go:generate counterfeiter . AddressManager
|
||||
|
||||
// DefaultAddressManager implements an AddressManager. It allocates a new address
|
||||
// (interface & port) a process can bind and keeps track of that.
|
||||
type DefaultAddressManager struct {
|
||||
port int
|
||||
host string
|
||||
}
|
||||
|
||||
// Initialize returns a address a process can listen on. Given a hostname it returns an address,
|
||||
// a tuple consisting of a free port and the hostname resolved to its IP.
|
||||
func (d *DefaultAddressManager) Initialize(host string) (port int, resolvedHost string, err error) {
|
||||
if d.port != 0 {
|
||||
return 0, "", fmt.Errorf("this DefaultAddressManager is already initialized")
|
||||
}
|
||||
addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:0", host))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
d.port = l.Addr().(*net.TCPAddr).Port
|
||||
defer func() {
|
||||
err = l.Close()
|
||||
}()
|
||||
d.host = addr.IP.String()
|
||||
return d.port, d.host, nil
|
||||
}
|
||||
|
||||
// Port returns the port that this DefaultAddressManager is managing. Port returns an
|
||||
// error if this DefaultAddressManager has not yet been initialized.
|
||||
func (d *DefaultAddressManager) Port() (int, error) {
|
||||
if d.port == 0 {
|
||||
return 0, fmt.Errorf("this DefaultAdressManager has is not initialized yet")
|
||||
}
|
||||
return d.port, nil
|
||||
}
|
||||
|
||||
// Host returns the host that this DefaultAddressManager is managing. Host returns an
|
||||
// error if this DefaultAddressManager has not yet been initialized.
|
||||
func (d *DefaultAddressManager) Host() (string, error) {
|
||||
if d.host == "" {
|
||||
return "", fmt.Errorf("this DefaultAdressManager has is not initialized yet")
|
||||
}
|
||||
return d.host, nil
|
||||
}
|
||||
|
||||
// PortFinder is the signature of a function returning a free port and a resolved
|
||||
// address to listen/bind on, and an erro in case there were some problems finding
|
||||
// a free pair of address & port
|
||||
type PortFinder func(host string) (port int, resolvedAddress string, err error)
|
||||
|
||||
//go:generate counterfeiter . PortFinder
|
||||
|
||||
// DefaultPortFinder is the default implementation of PortFinder: It resolves that
|
||||
// hostname or IP handed in and asks the kernel for a random port. To make that a bit
|
||||
// safer, it also tries to bind to that port to make sure it is not in use. If all goes
|
||||
|
|
|
|||
|
|
@ -3,10 +3,90 @@ package test_test
|
|||
import (
|
||||
. "k8s.io/kubectl/pkg/framework/test"
|
||||
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("DefaultAddressManager", func() {
|
||||
var defaultAddressManager *DefaultAddressManager
|
||||
BeforeEach(func() {
|
||||
defaultAddressManager = &DefaultAddressManager{}
|
||||
})
|
||||
|
||||
Describe("Initialize", func() {
|
||||
It("returns a free port and an address to bind to", func() {
|
||||
port, host, err := defaultAddressManager.Initialize("localhost")
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(host).To(Equal("127.0.0.1"))
|
||||
Expect(port).NotTo(Equal(0))
|
||||
|
||||
addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", host, port))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
defer func() {
|
||||
Expect(l.Close()).To(Succeed())
|
||||
}()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Context("when given an invalid hostname", func() {
|
||||
It("propagates the error", func() {
|
||||
_, _, err := defaultAddressManager.Initialize("this is not a hostname")
|
||||
|
||||
Expect(err).To(MatchError(ContainSubstring("no such host")))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when given a hostname that we don't have permission to listen on", func() {
|
||||
It("propagates the error", func() {
|
||||
_, _, err := defaultAddressManager.Initialize("example.com")
|
||||
|
||||
Expect(err).To(MatchError(ContainSubstring("bind: can't assign requested address")))
|
||||
})
|
||||
})
|
||||
|
||||
Context("initialized multiple times", func() {
|
||||
It("fails", func() {
|
||||
_, _, err := defaultAddressManager.Initialize("localhost")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, _, err = defaultAddressManager.Initialize("localhost")
|
||||
Expect(err).To(MatchError(ContainSubstring("already initialized")))
|
||||
})
|
||||
})
|
||||
})
|
||||
Describe("Port", func() {
|
||||
It("returns an error if Initialize has not been called yet", func() {
|
||||
_, err := defaultAddressManager.Port()
|
||||
Expect(err).To(MatchError(ContainSubstring("not initialized yet")))
|
||||
})
|
||||
It("returns the same port as previously allocated by Initialize", func() {
|
||||
expectedPort, _, err := defaultAddressManager.Initialize("localhost")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
actualPort, err := defaultAddressManager.Port()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(actualPort).To(Equal(expectedPort))
|
||||
})
|
||||
})
|
||||
Describe("Host", func() {
|
||||
It("returns an error if Initialize has not been called yet", func() {
|
||||
_, err := defaultAddressManager.Host()
|
||||
Expect(err).To(MatchError(ContainSubstring("not initialized yet")))
|
||||
})
|
||||
It("returns the same port as previously allocated by Initialize", func() {
|
||||
_, expectedHost, err := defaultAddressManager.Initialize("localhost")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
actualHost, err := defaultAddressManager.Host()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(actualHost).To(Equal(expectedHost))
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("DefaultPortFinder", func() {
|
||||
It("returns a free port and an address to bind to", func() {
|
||||
port, addr, err := DefaultPortFinder("127.0.0.1")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,220 @@
|
|||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package testfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"k8s.io/kubectl/pkg/framework/test"
|
||||
)
|
||||
|
||||
type FakeAddressManager struct {
|
||||
InitializeStub func(host string) (port int, resolvedAddress string, err error)
|
||||
initializeMutex sync.RWMutex
|
||||
initializeArgsForCall []struct {
|
||||
host string
|
||||
}
|
||||
initializeReturns struct {
|
||||
result1 int
|
||||
result2 string
|
||||
result3 error
|
||||
}
|
||||
initializeReturnsOnCall map[int]struct {
|
||||
result1 int
|
||||
result2 string
|
||||
result3 error
|
||||
}
|
||||
HostStub func() (string, error)
|
||||
hostMutex sync.RWMutex
|
||||
hostArgsForCall []struct{}
|
||||
hostReturns struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
hostReturnsOnCall map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
PortStub func() (int, error)
|
||||
portMutex sync.RWMutex
|
||||
portArgsForCall []struct{}
|
||||
portReturns struct {
|
||||
result1 int
|
||||
result2 error
|
||||
}
|
||||
portReturnsOnCall map[int]struct {
|
||||
result1 int
|
||||
result2 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) Initialize(host string) (port int, resolvedAddress string, err error) {
|
||||
fake.initializeMutex.Lock()
|
||||
ret, specificReturn := fake.initializeReturnsOnCall[len(fake.initializeArgsForCall)]
|
||||
fake.initializeArgsForCall = append(fake.initializeArgsForCall, struct {
|
||||
host string
|
||||
}{host})
|
||||
fake.recordInvocation("Initialize", []interface{}{host})
|
||||
fake.initializeMutex.Unlock()
|
||||
if fake.InitializeStub != nil {
|
||||
return fake.InitializeStub(host)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2, ret.result3
|
||||
}
|
||||
return fake.initializeReturns.result1, fake.initializeReturns.result2, fake.initializeReturns.result3
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) InitializeCallCount() int {
|
||||
fake.initializeMutex.RLock()
|
||||
defer fake.initializeMutex.RUnlock()
|
||||
return len(fake.initializeArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) InitializeArgsForCall(i int) string {
|
||||
fake.initializeMutex.RLock()
|
||||
defer fake.initializeMutex.RUnlock()
|
||||
return fake.initializeArgsForCall[i].host
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) InitializeReturns(result1 int, result2 string, result3 error) {
|
||||
fake.InitializeStub = nil
|
||||
fake.initializeReturns = struct {
|
||||
result1 int
|
||||
result2 string
|
||||
result3 error
|
||||
}{result1, result2, result3}
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) InitializeReturnsOnCall(i int, result1 int, result2 string, result3 error) {
|
||||
fake.InitializeStub = nil
|
||||
if fake.initializeReturnsOnCall == nil {
|
||||
fake.initializeReturnsOnCall = make(map[int]struct {
|
||||
result1 int
|
||||
result2 string
|
||||
result3 error
|
||||
})
|
||||
}
|
||||
fake.initializeReturnsOnCall[i] = struct {
|
||||
result1 int
|
||||
result2 string
|
||||
result3 error
|
||||
}{result1, result2, result3}
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) Host() (string, error) {
|
||||
fake.hostMutex.Lock()
|
||||
ret, specificReturn := fake.hostReturnsOnCall[len(fake.hostArgsForCall)]
|
||||
fake.hostArgsForCall = append(fake.hostArgsForCall, struct{}{})
|
||||
fake.recordInvocation("Host", []interface{}{})
|
||||
fake.hostMutex.Unlock()
|
||||
if fake.HostStub != nil {
|
||||
return fake.HostStub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fake.hostReturns.result1, fake.hostReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) HostCallCount() int {
|
||||
fake.hostMutex.RLock()
|
||||
defer fake.hostMutex.RUnlock()
|
||||
return len(fake.hostArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) HostReturns(result1 string, result2 error) {
|
||||
fake.HostStub = nil
|
||||
fake.hostReturns = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) HostReturnsOnCall(i int, result1 string, result2 error) {
|
||||
fake.HostStub = nil
|
||||
if fake.hostReturnsOnCall == nil {
|
||||
fake.hostReturnsOnCall = make(map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.hostReturnsOnCall[i] = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) Port() (int, error) {
|
||||
fake.portMutex.Lock()
|
||||
ret, specificReturn := fake.portReturnsOnCall[len(fake.portArgsForCall)]
|
||||
fake.portArgsForCall = append(fake.portArgsForCall, struct{}{})
|
||||
fake.recordInvocation("Port", []interface{}{})
|
||||
fake.portMutex.Unlock()
|
||||
if fake.PortStub != nil {
|
||||
return fake.PortStub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fake.portReturns.result1, fake.portReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) PortCallCount() int {
|
||||
fake.portMutex.RLock()
|
||||
defer fake.portMutex.RUnlock()
|
||||
return len(fake.portArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) PortReturns(result1 int, result2 error) {
|
||||
fake.PortStub = nil
|
||||
fake.portReturns = struct {
|
||||
result1 int
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) PortReturnsOnCall(i int, result1 int, result2 error) {
|
||||
fake.PortStub = nil
|
||||
if fake.portReturnsOnCall == nil {
|
||||
fake.portReturnsOnCall = make(map[int]struct {
|
||||
result1 int
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.portReturnsOnCall[i] = struct {
|
||||
result1 int
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.initializeMutex.RLock()
|
||||
defer fake.initializeMutex.RUnlock()
|
||||
fake.hostMutex.RLock()
|
||||
defer fake.hostMutex.RUnlock()
|
||||
fake.portMutex.RLock()
|
||||
defer fake.portMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeAddressManager) recordInvocation(key string, args []interface{}) {
|
||||
fake.invocationsMutex.Lock()
|
||||
defer fake.invocationsMutex.Unlock()
|
||||
if fake.invocations == nil {
|
||||
fake.invocations = map[string][][]interface{}{}
|
||||
}
|
||||
if fake.invocations[key] == nil {
|
||||
fake.invocations[key] = [][]interface{}{}
|
||||
}
|
||||
fake.invocations[key] = append(fake.invocations[key], args)
|
||||
}
|
||||
|
||||
var _ test.AddressManager = new(FakeAddressManager)
|
||||
Loading…
Reference in New Issue