From 1568a70bc4dd9edaf7c42d573b7ce0c2a36e012e Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Fri, 19 Nov 2021 17:28:47 +0000 Subject: [PATCH] Replace COMPLEMENT_VERSION_CHECK_ITERATIONS with COMPLEMENT_SPAWN_HS_TIMEOUT_SECS The new name is clearer and easier to understand. Fixes #232. Currently, Complement will still accept the old env var but will log a Deprecated warning. Homerunner will just look for the new env var HOMERUNNER_SPAWN_HS_TIMEOUT_SECS and will ignore the old env var. --- cmd/homerunner/README.md | 4 ++-- cmd/homerunner/main.go | 20 ++++++++++---------- cmd/homerunner/setup.go | 10 +++++----- internal/config/config.go | 23 +++++++++++++++-------- internal/docker/builder.go | 12 +++++++++--- internal/docker/deployer.go | 2 +- 6 files changed, 42 insertions(+), 29 deletions(-) diff --git a/cmd/homerunner/README.md b/cmd/homerunner/README.md index fc656016..720a777e 100644 --- a/cmd/homerunner/README.md +++ b/cmd/homerunner/README.md @@ -4,9 +4,9 @@ An HTTP server which can spin up homeservers and execute blueprints on them. Pow Environment variables (all are optional): ``` -HOMERUNNER_LIFETIME_MINS=30 # how long networks can exist for before being destroyed +HOMERUNNER_LIFETIME_MINS=30 # how long networks can exist for before being destroyed HOMERUNNER_PORT=54321 # port to listen on -HOMERUNNER_VER_CHECK_ITERATIONS=100 # how long to wait for the base image to spin up +HOMERUNNER_SPAWN_HS_TIMEOUT_SECS=5 # how long to wait for the base image to spin up HOMERUNNER_KEEP_BLUEPRINTS='clean_hs federation_one_to_one_room' # space delimited blueprint names to keep images for HOMERUNNER_SNAPSHOT_BLUEPRINT=/some/file.json # single shot execute this blueprint then commit the image, does not run the server ``` diff --git a/cmd/homerunner/main.go b/cmd/homerunner/main.go index 0f25839e..9c650417 100644 --- a/cmd/homerunner/main.go +++ b/cmd/homerunner/main.go @@ -20,7 +20,7 @@ const Pkg = "homerunner" type Config struct { HomeserverLifetimeMins int Port int - VersionCheckIterations int + SpawnHSTimeout time.Duration KeepBlueprints []string Snapshot string } @@ -29,7 +29,7 @@ func NewConfig() *Config { cfg := &Config{ HomeserverLifetimeMins: 30, Port: 54321, - VersionCheckIterations: 100, + SpawnHSTimeout: 5 * time.Second, KeepBlueprints: strings.Split(os.Getenv("HOMERUNNER_KEEP_BLUEPRINTS"), " "), Snapshot: os.Getenv("HOMERUNNER_SNAPSHOT_BLUEPRINT"), } @@ -39,20 +39,20 @@ func NewConfig() *Config { if val, _ := strconv.Atoi(os.Getenv("HOMERUNNER_PORT")); val != 0 { cfg.Port = val } - if val, _ := strconv.Atoi(os.Getenv("HOMERUNNER_VER_CHECK_ITERATIONS")); val != 0 { - cfg.VersionCheckIterations = val + if val, _ := strconv.Atoi(os.Getenv("HOMERUNNER_SPAWN_HS_TIMEOUT_SECS")); val != 0 { + cfg.SpawnHSTimeout = time.Duration(val) * time.Second } return cfg } func cleanup(c *Config) { cfg := &config.Complement{ - PackageNamespace: Pkg, - BaseImageURI: "nothing", - DebugLoggingEnabled: true, - VersionCheckIterations: c.VersionCheckIterations, - KeepBlueprints: c.KeepBlueprints, - BestEffort: true, + PackageNamespace: Pkg, + BaseImageURI: "nothing", + DebugLoggingEnabled: true, + SpawnHSTimeout: c.SpawnHSTimeout, + KeepBlueprints: c.KeepBlueprints, + BestEffort: true, } builder, err := docker.NewBuilder(cfg) if err != nil { diff --git a/cmd/homerunner/setup.go b/cmd/homerunner/setup.go index 4d16bc18..4f3bf8db 100644 --- a/cmd/homerunner/setup.go +++ b/cmd/homerunner/setup.go @@ -37,11 +37,11 @@ func (r *Runtime) CreateDeployment(imageURI string, blueprint *b.Blueprint) (*do } namespace := "homerunner_" + blueprint.Name cfg := &config.Complement{ - BaseImageURI: imageURI, - DebugLoggingEnabled: true, - VersionCheckIterations: r.Config.VersionCheckIterations, - BestEffort: true, - PackageNamespace: Pkg, + BaseImageURI: imageURI, + DebugLoggingEnabled: true, + SpawnHSTimeout: r.Config.SpawnHSTimeout, + BestEffort: true, + PackageNamespace: Pkg, } builder, err := docker.NewBuilder(cfg) if err != nil { diff --git a/internal/config/config.go b/internal/config/config.go index fd2ae68f..aadcfcb9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,19 +1,21 @@ package config import ( + "fmt" "os" "strconv" "strings" + "time" ) type Complement struct { - BaseImageURI string - BaseImageArgs []string - DebugLoggingEnabled bool - AlwaysPrintServerLogs bool - BestEffort bool - VersionCheckIterations int - KeepBlueprints []string + BaseImageURI string + BaseImageArgs []string + DebugLoggingEnabled bool + AlwaysPrintServerLogs bool + BestEffort bool + SpawnHSTimeout time.Duration + KeepBlueprints []string // The namespace for all complement created blueprints and deployments PackageNamespace string } @@ -24,7 +26,12 @@ func NewConfigFromEnvVars() *Complement { cfg.BaseImageArgs = strings.Split(os.Getenv("COMPLEMENT_BASE_IMAGE_ARGS"), " ") cfg.DebugLoggingEnabled = os.Getenv("COMPLEMENT_DEBUG") == "1" cfg.AlwaysPrintServerLogs = os.Getenv("COMPLEMENT_ALWAYS_PRINT_SERVER_LOGS") == "1" - cfg.VersionCheckIterations = parseEnvWithDefault("COMPLEMENT_VERSION_CHECK_ITERATIONS", 100) + cfg.SpawnHSTimeout = time.Duration(parseEnvWithDefault("COMPLEMENT_SPAWN_HS_TIMEOUT_SECS", 30)) * time.Second + if os.Getenv("COMPLEMENT_VERSION_CHECK_ITERATIONS") != "" { + fmt.Fprintln(os.Stderr, "Deprecated: COMPLEMENT_VERSION_CHECK_ITERATIONS will be removed in a later version. Use COMPLEMENT_SPAWN_HS_TIMEOUT_SECS instead which does the same thing and is clearer.") + // each iteration had a 50ms sleep between tries so the timeout is 50 * iteration ms + cfg.SpawnHSTimeout = time.Duration(50*parseEnvWithDefault("COMPLEMENT_VERSION_CHECK_ITERATIONS", 100)) * time.Millisecond + } cfg.KeepBlueprints = strings.Split(os.Getenv("COMPLEMENT_KEEP_BLUEPRINTS"), " ") if cfg.BaseImageURI == "" { panic("COMPLEMENT_BASE_IMAGE must be set") diff --git a/internal/docker/builder.go b/internal/docker/builder.go index 315ca576..0d5d04aa 100644 --- a/internal/docker/builder.go +++ b/internal/docker/builder.go @@ -383,7 +383,7 @@ func (d *Builder) deployBaseImage(blueprintName string, hs b.Homeserver, context return deployImage( d.Docker, d.Config.BaseImageURI, d.CSAPIPort, fmt.Sprintf("complement_%s", contextStr), d.Config.PackageNamespace, blueprintName, hs.Name, asIDToRegistrationMap, contextStr, - networkID, d.Config.VersionCheckIterations, + networkID, d.Config.SpawnHSTimeout, ) } @@ -491,7 +491,8 @@ func generateASRegistrationYaml(as b.ApplicationService) string { } func deployImage( - docker *client.Client, imageID string, csPort int, containerName, pkgNamespace, blueprintName, hsName string, asIDToRegistrationMap map[string]string, contextStr, networkID string, versionCheckIterations int, + docker *client.Client, imageID string, csPort int, containerName, pkgNamespace, blueprintName, hsName string, + asIDToRegistrationMap map[string]string, contextStr, networkID string, spawnHSTimeout time.Duration, ) (*HomeserverDeployment, error) { ctx := context.Background() var extraHosts []string @@ -595,7 +596,12 @@ func deployImage( versionsURL := fmt.Sprintf("%s/_matrix/client/versions", baseURL) // hit /versions to check it is up var lastErr error - for i := 0; i < versionCheckIterations; i++ { + stopTime := time.Now().Add(spawnHSTimeout) + for { + if time.Now().After(stopTime) { + lastErr = fmt.Errorf("timed out checking for homeserver to be up: %s", lastErr) + break + } res, err := http.Get(versionsURL) if err != nil { lastErr = fmt.Errorf("GET %s => error: %s", versionsURL, err) diff --git a/internal/docker/deployer.go b/internal/docker/deployer.go index 636401a6..f1f228d0 100644 --- a/internal/docker/deployer.go +++ b/internal/docker/deployer.go @@ -89,7 +89,7 @@ func (d *Deployer) Deploy(ctx context.Context, blueprintName string) (*Deploymen // TODO: Make CSAPI port configurable deployment, err := deployImage( d.Docker, img.ID, 8008, fmt.Sprintf("complement_%s_%s_%s_%d", d.config.PackageNamespace, d.DeployNamespace, contextStr, d.Counter), - d.config.PackageNamespace, blueprintName, hsName, asIDToRegistrationMap, contextStr, networkID, d.config.VersionCheckIterations) + d.config.PackageNamespace, blueprintName, hsName, asIDToRegistrationMap, contextStr, networkID, d.config.SpawnHSTimeout) if err != nil { if deployment != nil && deployment.ContainerID != "" { // print logs to help debug