104 lines
3.3 KiB
Go
104 lines
3.3 KiB
Go
|
|
package hostnginx
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"slices"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestControllerSwitchesAndReloadsExactService(t *testing.T) {
|
||
|
|
configPath := writeNginxConfig(t, serverConfiguration)
|
||
|
|
runner := &recordingRunner{}
|
||
|
|
controller, err := newController(configPath, "/usr/sbin/nginx", "/bin/systemctl", "nginx.service", runner)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create host Nginx controller: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
previous, err := controller.Switch(context.Background(), 8080)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("switch host Nginx backend: %v", err)
|
||
|
|
}
|
||
|
|
if previous.ActivePort != 8081 {
|
||
|
|
t.Fatalf("unexpected previous port: %d", previous.ActivePort)
|
||
|
|
}
|
||
|
|
current, err := controller.Read()
|
||
|
|
if err != nil || current.ActivePort != 8080 {
|
||
|
|
t.Fatalf("unexpected current host Nginx configuration: snapshot=%+v err=%v", current, err)
|
||
|
|
}
|
||
|
|
wantCalls := [][]string{
|
||
|
|
{"/usr/sbin/nginx", "-t"},
|
||
|
|
{"/bin/systemctl", "reload", "--", "nginx.service"},
|
||
|
|
}
|
||
|
|
if !slices.EqualFunc(runner.calls, wantCalls, slices.Equal) {
|
||
|
|
t.Fatalf("unexpected host Nginx commands: %+v", runner.calls)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestControllerRestoresConfigurationWhenValidationFails(t *testing.T) {
|
||
|
|
configPath := writeNginxConfig(t, serverConfiguration)
|
||
|
|
runner := &recordingRunner{errors: []error{errors.New("nginx test failed"), nil, nil}}
|
||
|
|
controller, err := newController(configPath, "/usr/sbin/nginx", "/bin/systemctl", "nginx.service", runner)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create host Nginx controller: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, err := controller.Switch(context.Background(), 8080); err == nil {
|
||
|
|
t.Fatal("expected host Nginx validation failure")
|
||
|
|
}
|
||
|
|
current, err := controller.Read()
|
||
|
|
if err != nil || current.ActivePort != 8081 || string(current.Content) != serverConfiguration {
|
||
|
|
t.Fatalf("host Nginx configuration was not restored: snapshot=%+v err=%v", current, err)
|
||
|
|
}
|
||
|
|
if len(runner.calls) != 3 {
|
||
|
|
t.Fatalf("unexpected validation compensation calls: %+v", runner.calls)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestControllerRestoreUsesCompleteSnapshot(t *testing.T) {
|
||
|
|
configPath := writeNginxConfig(t, serverConfiguration)
|
||
|
|
runner := &recordingRunner{}
|
||
|
|
controller, err := newController(configPath, "/usr/sbin/nginx", "/bin/systemctl", "nginx.service", runner)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create host Nginx controller: %v", err)
|
||
|
|
}
|
||
|
|
previous, err := controller.Switch(context.Background(), 8080)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("switch host Nginx backend: %v", err)
|
||
|
|
}
|
||
|
|
if err := controller.Restore(context.Background(), previous); err != nil {
|
||
|
|
t.Fatalf("restore host Nginx backend: %v", err)
|
||
|
|
}
|
||
|
|
current, err := controller.Read()
|
||
|
|
if err != nil || current.ActivePort != 8081 || string(current.Content) != serverConfiguration {
|
||
|
|
t.Fatalf("unexpected restored configuration: snapshot=%+v err=%v", current, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func writeNginxConfig(t *testing.T, content string) string {
|
||
|
|
t.Helper()
|
||
|
|
path := filepath.Join(t.TempDir(), "nginx.conf")
|
||
|
|
if err := os.WriteFile(path, []byte(content), 0o640); err != nil {
|
||
|
|
t.Fatalf("write host Nginx configuration: %v", err)
|
||
|
|
}
|
||
|
|
return path
|
||
|
|
}
|
||
|
|
|
||
|
|
type recordingRunner struct {
|
||
|
|
calls [][]string
|
||
|
|
errors []error
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *recordingRunner) Run(_ context.Context, executable string, arguments ...string) error {
|
||
|
|
call := append([]string{executable}, arguments...)
|
||
|
|
r.calls = append(r.calls, call)
|
||
|
|
if len(r.errors) == 0 {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
err := r.errors[0]
|
||
|
|
r.errors = r.errors[1:]
|
||
|
|
return err
|
||
|
|
}
|