The APIServer constructor previously required careful configuration. Now
it takes no arguments, and gives you an APIServer that you can
`.Start()`. If you want to configure it, you still can. For example, you
can set the environment variable `TEST_ASSET_KUBE_APISERVER` to the path
to your apiserver binary, or you can override the PathFinder in go code:
```
myAPIServer := test.NewAPIServer()
myAPIServer.PathFinder = func(_ string) string {
return "/path/to/my/apiserver/binary"
}
```
Previously the responsibility of choosing a port that the APIServer
could listen on was left to the caller. Now APIServer delegates that
responsibility to an AddressManager. By default you get a random unused
port on localhost. If you want to customize that behaviour, you can
overwrite the AddressManager:
```
myAPIServer := test.NewAPIServer()
myAPIServer.AddressManager = myAddressManager
```
If this is a common request, then in future we might provide some common
custom AddressManagers.
Everything now works pretty much like before, so we're not yet feeling a
lot of the benefit. Still to do:
- Remove all vestiges of Etcd config etc from the Fixtures struct
- Remove duplicated config
- Make Fixtures and APIServer constructors take 0 params
This is motivated by #162, but also involves changing the
NewFixtures(...) constructor which is the entry point to the whole
framework. We're removing the amount of config
you need to make it work, in line with #163.
- Remove the logic from the constructors
- Have start take a configuration map for the fixture processes
- Move the testing on open ports closer to the actual start
- APIServer & Etcd get configured, from the outside, on which ports to
listen on
- Configuration, the subjects under test might be interested in, is
exposed by Fixtures.Config
Hint: Before we start any process, we get a random port and check if
that random port is acutally free to bind to. As it takes some time
until we actually start anything, we might run into cases, where another
process binds to that port while we are starting up. Even if we do the
port checking closer to actually binding, we still have the same issue.
For now, however, we take that risk - if we run into problems with that,
we are open to refactor that.
While doing that we found that we needed to refactor the fakes to handle
command line arguments which are not known up front; we do this by using
regular expresseions.
- Start() should only return when the process is actually up and
listening
- It may take some time to tear down a process, so we increased the
timeout for Stop() (to some random number)
- We make sure Std{Out,Err} is properly initialized, we should not rely
on Ginkgo/Gomega to do that for us
Create a new set of test fixtures by doing:
```
f := test.NewFixtures("/path/to/etcd", "/path/to/apiserver")
```
Before running your integration tests, start all your fixtures:
```
err := f.Start()
Expect(err).NotTo(HaveOccurred())
```
Now that you have started your etcd and apiserver, you'll find the
apiserver listening locally on the default port. When you're done with
your testing, stop and clean up:
```
err := f.Stop()
Expect(err).NotTo(HaveOccurred())
```
To start an apiserver:
```
apiServer := APIServer{Path: "/path/to/my/apiserver/binary"}
session, err := apiServer.Start("tcp://whereever.is.my.etcd:port")
Expect(err).NotTo(HaveOccurred())
```
When you're done testing against that apiserver:
```
session.Terminate().Wait()
```
...or if you prefer:
```
gexec.Terminate()
```
...which will terminate not only this apiserver, but also all other
command sessions you started in this test.