diff --git a/internal/docker/deployer.go b/internal/docker/deployer.go index 11e02799..18f03129 100644 --- a/internal/docker/deployer.go +++ b/internal/docker/deployer.go @@ -250,33 +250,65 @@ func (d *Deployer) executePostScript(hsDep *HomeserverDeployment, testName strin return cmd.CombinedOutput() } -// Restart a homeserver deployment. -func (d *Deployer) Restart(hsDep *HomeserverDeployment, cfg *config.Complement) error { +func (d *Deployer) PauseServer(hsDep *HomeserverDeployment) error { + ctx := context.Background() + err := d.Docker.ContainerPause(ctx, hsDep.ContainerID) + if err != nil { + return fmt.Errorf("failed to pause container %s: %s", hsDep.ContainerID, err) + } + return nil +} + +func (d *Deployer) UnpauseServer(hsDep *HomeserverDeployment) error { ctx := context.Background() - secs := int(cfg.SpawnHSTimeout.Seconds()) + err := d.Docker.ContainerUnpause(ctx, hsDep.ContainerID) + if err != nil { + return fmt.Errorf("failed to unpause container %s: %s", hsDep.ContainerID, err) + } + return nil +} + +func (d *Deployer) StopServer(hsDep *HomeserverDeployment) error { + ctx := context.Background() + secs := int(d.config.SpawnHSTimeout.Seconds()) err := d.Docker.ContainerStop(ctx, hsDep.ContainerID, container.StopOptions{ Timeout: &secs, }) if err != nil { - return fmt.Errorf("Restart: Failed to stop container %s: %s", hsDep.ContainerID, err) + return fmt.Errorf("failed to stop container %s: %s", hsDep.ContainerID, err) } + return nil +} - err = d.Docker.ContainerStart(ctx, hsDep.ContainerID, types.ContainerStartOptions{}) +// Restart a homeserver deployment. +func (d *Deployer) Restart(hsDep *HomeserverDeployment) error { + if err := d.StopServer(hsDep); err != nil { + return fmt.Errorf("Restart: %s", err) + } + if err := d.StartServer(hsDep); err != nil { + return fmt.Errorf("Restart: %s", err) + } + return nil +} + +func (d *Deployer) StartServer(hsDep *HomeserverDeployment) error { + ctx := context.Background() + err := d.Docker.ContainerStart(ctx, hsDep.ContainerID, types.ContainerStartOptions{}) if err != nil { - return fmt.Errorf("Restart: Failed to start container %s: %s", hsDep.ContainerID, err) + return fmt.Errorf("failed to start container %s: %s", hsDep.ContainerID, err) } // Wait for the container to be ready. baseURL, fedBaseURL, err := waitForPorts(ctx, d.Docker, hsDep.ContainerID) if err != nil { - return fmt.Errorf("Restart: Failed to get ports for container %s: %s", hsDep.ContainerID, err) + return fmt.Errorf("failed to get ports for container %s: %s", hsDep.ContainerID, err) } hsDep.SetEndpoints(baseURL, fedBaseURL) - stopTime := time.Now().Add(cfg.SpawnHSTimeout) + stopTime := time.Now().Add(d.config.SpawnHSTimeout) _, err = waitForContainer(ctx, d.Docker, hsDep, stopTime) if err != nil { - return fmt.Errorf("Restart: Failed to restart container %s: %s", hsDep.ContainerID, err) + return fmt.Errorf("failed to wait for container %s: %s", hsDep.ContainerID, err) } return nil diff --git a/internal/docker/deployment.go b/internal/docker/deployment.go index 0d5a9aa2..67047f3a 100644 --- a/internal/docker/deployment.go +++ b/internal/docker/deployment.go @@ -229,7 +229,7 @@ func (d *Deployment) AppServiceUser(t *testing.T, hsName, appServiceUserID strin func (d *Deployment) Restart(t *testing.T) error { t.Helper() for _, hsDep := range d.HS { - err := d.Deployer.Restart(hsDep, d.Config) + err := d.Deployer.Restart(hsDep) if err != nil { t.Errorf("Deployment.Restart: %s", err) return err @@ -238,3 +238,47 @@ func (d *Deployment) Restart(t *testing.T) error { return nil } + +func (d *Deployment) StartServer(t *testing.T, hsName string) { + t.Helper() + hsDep := d.HS[hsName] + if hsDep == nil { + t.Fatalf("StartServer: %s does not exist in this deployment", hsName) + } + if err := d.Deployer.StartServer(hsDep); err != nil { + t.Fatalf("StartServer: %s", err) + } +} + +func (d *Deployment) StopServer(t *testing.T, hsName string) { + t.Helper() + hsDep := d.HS[hsName] + if hsDep == nil { + t.Fatalf("StopServer: %s does not exist in this deployment", hsName) + } + if err := d.Deployer.StopServer(hsDep); err != nil { + t.Fatalf("StopServer: %s", err) + } +} + +func (d *Deployment) PauseServer(t *testing.T, hsName string) { + t.Helper() + hsDep := d.HS[hsName] + if hsDep == nil { + t.Fatalf("PauseServer: %s does not exist in this deployment", hsName) + } + if err := d.Deployer.PauseServer(hsDep); err != nil { + t.Fatalf("PauseServer: %s", err) + } +} + +func (d *Deployment) UnpauseServer(t *testing.T, hsName string) { + t.Helper() + hsDep := d.HS[hsName] + if hsDep == nil { + t.Fatalf("UnpauseServer: %s does not exist in this deployment", hsName) + } + if err := d.Deployer.UnpauseServer(hsDep); err != nil { + t.Fatalf("UnpauseServer: %s", err) + } +} diff --git a/test_package.go b/test_package.go index 2b661848..5c89d1f3 100644 --- a/test_package.go +++ b/test_package.go @@ -30,8 +30,29 @@ type Deployment interface { // AppServiceUser returns a client for the given app service user ID. The HS in question must have an appservice // hooked up to it already. TODO: REMOVE AppServiceUser(t *testing.T, hsName, appServiceUserID string) *client.CSAPI - // Restart a deployment. + // Restart a deployment. Restarts all homeservers in this deployment. + // This function is designed to be used to make assertions that servers are persisting information to disk. Restart(t *testing.T) error + // Stop the container running this HS. Fails the test if this is not possible. + // This function is designed to be used to make assertions when federated servers are unreachable. + // Do not use this function if you need the HS CSAPI URL to be stable, prefer PauseServer if you need this. + StopServer(t *testing.T, hsName string) + // Start the container running this HS. The HS must exist in this deployment already and it must be stopped already. + // Fails the test if this isn't true, or there was a problem. + // This function is designed to be used to start a server previously stopped via StopServer. + // Do not use this function if you need the HS CSAPI URL to be stable, prefer UnpauseServer if you need this. + StartServer(t *testing.T, hsName string) + // Pause a running homeserver. The HS will be suspended, preserving data in memory. + // Prefer this function over StopServer if you need to keep the port allocations stable across your test. + // This function is designed to be used to make assertions when federated servers are unreachable. + // Fails the test if there is a problem pausing. + // See https://docs.docker.com/engine/reference/commandline/pause/ + PauseServer(t *testing.T, hsName string) + // Unpause a running homeserver. The HS will be suspended, preserving data in memory. + // Fails the test if there is a problem unpausing. + // This function is designed to be used to make assertions when federated servers are unreachable. + // see https://docs.docker.com/engine/reference/commandline/unpause/ + UnpauseServer(t *testing.T, hsName string) // Destroy the entire deployment. Destroys all running containers. If `printServerLogs` is true, // will print container logs before killing the container. Destroy(t *testing.T)