test: for upgrade compatibility tests retain assigned container ip addresses on upgrade (#13615)
Use a synthetic pod construct to hold onto the IP address in the interim.
This commit is contained in:
parent
883ccc2a98
commit
f3f941f1a0
|
@ -7,6 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
dockercontainer "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
|
@ -24,11 +25,13 @@ const disableRYUKEnv = "TESTCONTAINERS_RYUK_DISABLED"
|
||||||
type consulContainerNode struct {
|
type consulContainerNode struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
client *api.Client
|
client *api.Client
|
||||||
|
pod testcontainers.Container
|
||||||
container testcontainers.Container
|
container testcontainers.Container
|
||||||
ip string
|
ip string
|
||||||
port int
|
port int
|
||||||
config Config
|
config Config
|
||||||
req testcontainers.ContainerRequest
|
podReq testcontainers.ContainerRequest
|
||||||
|
consulReq testcontainers.ContainerRequest
|
||||||
dataDir string
|
dataDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,15 +39,11 @@ func (c *consulContainerNode) GetConfig() Config {
|
||||||
return c.config
|
return c.config
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConsulContainerWithReq(ctx context.Context, req testcontainers.ContainerRequest) (testcontainers.Container, error) {
|
func startContainer(ctx context.Context, req testcontainers.ContainerRequest) (testcontainers.Container, error) {
|
||||||
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||||
ContainerRequest: req,
|
ContainerRequest: req,
|
||||||
Started: true,
|
Started: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return container, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConsulContainer starts a Consul node in a container with the given config.
|
// NewConsulContainer starts a Consul node in a container with the given config.
|
||||||
|
@ -74,34 +73,40 @@ func NewConsulContainer(ctx context.Context, config Config) (Node, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req := newContainerRequest(config, name, configFile, tmpDirData, license)
|
podReq, consulReq := newContainerRequest(config, name, configFile, tmpDirData, license)
|
||||||
container, err := newConsulContainerWithReq(ctx, req)
|
|
||||||
|
podContainer, err := startContainer(ctx, podReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.StartLogProducer(ctx); err != nil {
|
localIP, err := podContainer.Host(ctx)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
container.FollowOutput(&NodeLogConsumer{
|
|
||||||
|
mappedPort, err := podContainer.MappedPort(ctx, "8500")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ip, err := podContainer.ContainerIP(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
consulContainer, err := startContainer(ctx, consulReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := consulContainer.StartLogProducer(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
consulContainer.FollowOutput(&NodeLogConsumer{
|
||||||
Prefix: pc.NodeName,
|
Prefix: pc.NodeName,
|
||||||
})
|
})
|
||||||
|
|
||||||
localIP, err := container.Host(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mappedPort, err := container.MappedPort(ctx, "8500")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ip, err := container.ContainerIP(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uri := fmt.Sprintf("http://%s:%s", localIP, mappedPort.Port())
|
uri := fmt.Sprintf("http://%s:%s", localIP, mappedPort.Port())
|
||||||
apiConfig := api.DefaultConfig()
|
apiConfig := api.DefaultConfig()
|
||||||
apiConfig.Address = uri
|
apiConfig.Address = uri
|
||||||
|
@ -112,25 +117,37 @@ func NewConsulContainer(ctx context.Context, config Config) (Node, error) {
|
||||||
|
|
||||||
return &consulContainerNode{
|
return &consulContainerNode{
|
||||||
config: config,
|
config: config,
|
||||||
container: container,
|
pod: podContainer,
|
||||||
|
container: consulContainer,
|
||||||
ip: ip,
|
ip: ip,
|
||||||
port: mappedPort.Int(),
|
port: mappedPort.Int(),
|
||||||
client: apiClient,
|
client: apiClient,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
req: req,
|
podReq: podReq,
|
||||||
|
consulReq: consulReq,
|
||||||
dataDir: tmpDirData,
|
dataDir: tmpDirData,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContainerRequest(config Config, name, configFile, dataDir, license string) testcontainers.ContainerRequest {
|
const pauseImage = "k8s.gcr.io/pause:3.3"
|
||||||
|
|
||||||
|
func newContainerRequest(config Config, name, configFile, dataDir, license string) (podRequest, consulRequest testcontainers.ContainerRequest) {
|
||||||
skipReaper := isRYUKDisabled()
|
skipReaper := isRYUKDisabled()
|
||||||
|
|
||||||
return testcontainers.ContainerRequest{
|
pod := testcontainers.ContainerRequest{
|
||||||
Image: consulImage + ":" + config.Version,
|
Image: pauseImage,
|
||||||
ExposedPorts: []string{"8500/tcp"},
|
|
||||||
WaitingFor: wait.ForLog(bootLogLine).WithStartupTimeout(10 * time.Second),
|
|
||||||
AutoRemove: false,
|
AutoRemove: false,
|
||||||
Name: name,
|
Name: name + "-pod",
|
||||||
|
SkipReaper: skipReaper,
|
||||||
|
ExposedPorts: []string{"8500/tcp"},
|
||||||
|
}
|
||||||
|
|
||||||
|
app := testcontainers.ContainerRequest{
|
||||||
|
NetworkMode: dockercontainer.NetworkMode("container:" + name + "-pod"),
|
||||||
|
Image: consulImage + ":" + config.Version,
|
||||||
|
WaitingFor: wait.ForLog(bootLogLine).WithStartupTimeout(10 * time.Second),
|
||||||
|
AutoRemove: false,
|
||||||
|
Name: name,
|
||||||
Mounts: []testcontainers.ContainerMount{
|
Mounts: []testcontainers.ContainerMount{
|
||||||
{Source: testcontainers.DockerBindMountSource{HostPath: configFile}, Target: "/consul/config/config.hcl"},
|
{Source: testcontainers.DockerBindMountSource{HostPath: configFile}, Target: "/consul/config/config.hcl"},
|
||||||
{Source: testcontainers.DockerBindMountSource{HostPath: dataDir}, Target: "/consul/data"},
|
{Source: testcontainers.DockerBindMountSource{HostPath: dataDir}, Target: "/consul/data"},
|
||||||
|
@ -139,6 +156,8 @@ func newContainerRequest(config Config, name, configFile, dataDir, license strin
|
||||||
SkipReaper: skipReaper,
|
SkipReaper: skipReaper,
|
||||||
Env: map[string]string{"CONSUL_LICENSE": license},
|
Env: map[string]string{"CONSUL_LICENSE": license},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pod, app
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClient returns an API client that can be used to communicate with the Node.
|
// GetClient returns an API client that can be used to communicate with the Node.
|
||||||
|
@ -162,23 +181,24 @@ func (c *consulContainerNode) Upgrade(ctx context.Context, config Config) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
req2 := newContainerRequest(
|
// We'll keep the same pod.
|
||||||
|
_, consulReq2 := newContainerRequest(
|
||||||
config,
|
config,
|
||||||
c.req.Name,
|
c.consulReq.Name,
|
||||||
file,
|
file,
|
||||||
c.dataDir,
|
c.dataDir,
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
req2.Env = c.req.Env // copy license
|
consulReq2.Env = c.consulReq.Env // copy license
|
||||||
|
|
||||||
_ = c.container.StopLogProducer()
|
_ = c.container.StopLogProducer()
|
||||||
if err := c.container.Terminate(ctx); err != nil {
|
if err := c.container.Terminate(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.req = req2
|
c.consulReq = consulReq2
|
||||||
|
|
||||||
container, err := newConsulContainerWithReq(ctx, c.req)
|
container, err := startContainer(ctx, c.consulReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -192,32 +212,6 @@ func (c *consulContainerNode) Upgrade(ctx context.Context, config Config) error
|
||||||
|
|
||||||
c.container = container
|
c.container = container
|
||||||
|
|
||||||
localIP, err := container.Host(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
mappedPort, err := container.MappedPort(ctx, "8500")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ip, err := container.ContainerIP(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
uri := fmt.Sprintf("http://%s:%s", localIP, mappedPort.Port())
|
|
||||||
c.ip = ip
|
|
||||||
c.port = mappedPort.Int()
|
|
||||||
apiConfig := api.DefaultConfig()
|
|
||||||
apiConfig.Address = uri
|
|
||||||
c.client, err = api.NewClient(apiConfig)
|
|
||||||
c.ctx = ctx
|
|
||||||
c.config = config
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue