refactor: trim DeployIntent input, extract probeLoop helper, fix test drain configs
- DeployIntent: assign trimmed imageName before validation so url.PathEscape never encodes leading/trailing whitespace - readiness: extract probeLoop orchestration helper shared by tcpProbe and httpProbe, reducing cyclomatic complexity below the gocyclo threshold (15) - service_test: add DrainDelayConfigured: true to 14 test config blocks that were missing it, preventing silent 2s drain default
- commit
- e0362ee8cd4a34f2740d9d3d12c81da125e37831
- author
- brice · · 2026-03-05 05:08 UTC
- parent
- 5c05b34
- signature
- unsigned
3 files · +121 -107
M internal/adapters/in/cli/remote/client.go +2 -1
| @@ -727,7 +727,8 @@ func (c *Client) Deploy(ctx context.Context, deployDomain string) (*DeployResult | |||
| 727 | 727 | // DeployIntent tells the server that a CLI-managed push is about to happen, | |
| 728 | 728 | // suppressing event-based deploys for this image. | |
| 729 | 729 | func (c *Client) DeployIntent(ctx context.Context, imageName string) error { | |
| 730 | - | if strings.TrimSpace(imageName) == "" { | |
| 730 | + | imageName = strings.TrimSpace(imageName) | |
| 731 | + | if imageName == "" { | |
| 731 | 732 | return fmt.Errorf("image name cannot be empty") | |
| 732 | 733 | } | |
| 733 | 734 | resp, err := c.requestWithRetry(ctx, http.MethodPost, "/deploy-intent/"+url.PathEscape(imageName), nil) | |
| @@ -727,7 +727,8 @@ func (c *Client) Deploy(ctx context.Context, deployDomain string) (*DeployResult | |||||
| 727 | // DeployIntent tells the server that a CLI-managed push is about to happen, | 727 | // DeployIntent tells the server that a CLI-managed push is about to happen, | ||
| 728 | // suppressing event-based deploys for this image. | 728 | // suppressing event-based deploys for this image. | ||
| 729 | func (c *Client) DeployIntent(ctx context.Context, imageName string) error { | 729 | func (c *Client) DeployIntent(ctx context.Context, imageName string) error { | ||
| 730 | - | if strings.TrimSpace(imageName) == "" { | 730 | + | imageName = strings.TrimSpace(imageName) |
| 731 | + | if imageName == "" { | |||
| 731 | return fmt.Errorf("image name cannot be empty") | 732 | return fmt.Errorf("image name cannot be empty") | ||
| 732 | } | 733 | } | ||
| 733 | resp, err := c.requestWithRetry(ctx, http.MethodPost, "/deploy-intent/"+url.PathEscape(imageName), nil) | 734 | resp, err := c.requestWithRetry(ctx, http.MethodPost, "/deploy-intent/"+url.PathEscape(imageName), nil) | ||
M internal/usecase/container/readiness.go +67 -68
| @@ -2,6 +2,7 @@ package container | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | + | "errors" | |
| 5 | 6 | "fmt" | |
| 6 | 7 | "net" | |
| 7 | 8 | "net/http" | |
| @@ -10,43 +11,40 @@ import ( | |||
| 10 | 11 | "github.com/bnema/zerowrap" | |
| 11 | 12 | ) | |
| 12 | 13 | ||
| 13 | - | // tcpProbe attempts a TCP connection to addr, retrying every 500ms until | |
| 14 | - | // success or timeout. This is the universal fallback readiness check — | |
| 15 | - | // it verifies the process is at least accepting connections. | |
| 16 | - | func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |
| 17 | - | log := zerowrap.FromCtx(ctx) | |
| 18 | - | deadline := time.Now().Add(timeout) | |
| 19 | - | dialer := &net.Dialer{} | |
| 20 | - | attempts := 0 | |
| 21 | - | var lastErr error | |
| 14 | + | var errProbeTimeout = errors.New("probe timeout") | |
| 15 | + | ||
| 16 | + | func probeLoop( | |
| 17 | + | ctx context.Context, | |
| 18 | + | deadline time.Time, | |
| 19 | + | baseSleep time.Duration, | |
| 20 | + | defaultAttemptTimeout time.Duration, | |
| 21 | + | work func(attemptCtx context.Context) (success bool, err error), | |
| 22 | + | ) error { | |
| 22 | 23 | for { | |
| 23 | 24 | if err := ctx.Err(); err != nil { | |
| 24 | 25 | return err | |
| 25 | 26 | } | |
| 26 | 27 | if time.Now().After(deadline) { | |
| 27 | - | return fmt.Errorf("TCP probe timeout after %s: %s not reachable (attempts=%d, last_error=%v)", timeout, addr, attempts, lastErr) | |
| 28 | + | return errProbeTimeout | |
| 28 | 29 | } | |
| 29 | 30 | ||
| 30 | 31 | remaining := time.Until(deadline) | |
| 31 | - | attemptTimeout := time.Second | |
| 32 | + | attemptTimeout := defaultAttemptTimeout | |
| 32 | 33 | if remaining < attemptTimeout { | |
| 33 | 34 | attemptTimeout = remaining | |
| 34 | 35 | } | |
| 36 | + | ||
| 35 | 37 | attemptCtx, cancel := context.WithTimeout(ctx, attemptTimeout) | |
| 36 | - | conn, err := dialer.DialContext(attemptCtx, "tcp", addr) | |
| 38 | + | success, err := work(attemptCtx) | |
| 37 | 39 | cancel() | |
| 38 | - | attempts++ | |
| 39 | - | if err == nil { | |
| 40 | - | conn.Close() | |
| 41 | - | log.Debug().Str("addr", addr).Int("attempts", attempts).Msg("TCP probe connected") | |
| 42 | - | return nil | |
| 40 | + | if err != nil { | |
| 41 | + | return err | |
| 43 | 42 | } | |
| 44 | - | lastErr = err | |
| 45 | - | if attempts <= 3 || attempts%10 == 0 { | |
| 46 | - | log.Debug().Err(err).Str("addr", addr).Int("attempt", attempts).Msg("TCP probe attempt failed") | |
| 43 | + | if success { | |
| 44 | + | return nil | |
| 47 | 45 | } | |
| 48 | 46 | ||
| 49 | - | sleepInterval := 500 * time.Millisecond | |
| 47 | + | sleepInterval := baseSleep | |
| 50 | 48 | if remProbe := time.Until(deadline); remProbe < sleepInterval { | |
| 51 | 49 | sleepInterval = remProbe | |
| 52 | 50 | } | |
| @@ -59,8 +57,9 @@ func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |||
| 59 | 57 | if ctx.Err() != nil { | |
| 60 | 58 | return ctx.Err() | |
| 61 | 59 | } | |
| 62 | - | return fmt.Errorf("TCP probe timeout after %s: %s not reachable (attempts=%d, last_error=%v)", timeout, addr, attempts, lastErr) | |
| 60 | + | return errProbeTimeout | |
| 63 | 61 | } | |
| 62 | + | ||
| 64 | 63 | t := time.NewTimer(sleepInterval) | |
| 65 | 64 | select { | |
| 66 | 65 | case <-t.C: | |
| @@ -71,6 +70,36 @@ func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |||
| 71 | 70 | } | |
| 72 | 71 | } | |
| 73 | 72 | ||
| 73 | + | // tcpProbe attempts a TCP connection to addr, retrying every 500ms until | |
| 74 | + | // success or timeout. This is the universal fallback readiness check — | |
| 75 | + | // it verifies the process is at least accepting connections. | |
| 76 | + | func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |
| 77 | + | log := zerowrap.FromCtx(ctx) | |
| 78 | + | deadline := time.Now().Add(timeout) | |
| 79 | + | dialer := &net.Dialer{} | |
| 80 | + | attempts := 0 | |
| 81 | + | var lastErr error | |
| 82 | + | err := probeLoop(ctx, deadline, 500*time.Millisecond, time.Second, func(attemptCtx context.Context) (bool, error) { | |
| 83 | + | conn, err := dialer.DialContext(attemptCtx, "tcp", addr) | |
| 84 | + | attempts++ | |
| 85 | + | if err == nil { | |
| 86 | + | conn.Close() | |
| 87 | + | log.Debug().Str("addr", addr).Int("attempts", attempts).Msg("TCP probe connected") | |
| 88 | + | return true, nil | |
| 89 | + | } | |
| 90 | + | ||
| 91 | + | lastErr = err | |
| 92 | + | if attempts <= 3 || attempts%10 == 0 { | |
| 93 | + | log.Debug().Err(err).Str("addr", addr).Int("attempt", attempts).Msg("TCP probe attempt failed") | |
| 94 | + | } | |
| 95 | + | return false, nil | |
| 96 | + | }) | |
| 97 | + | if errors.Is(err, errProbeTimeout) { | |
| 98 | + | return fmt.Errorf("TCP probe timeout after %s: %s not reachable (attempts=%d, last_error=%v)", timeout, addr, attempts, lastErr) | |
| 99 | + | } | |
| 100 | + | return err | |
| 101 | + | } | |
| 102 | + | ||
| 74 | 103 | // httpProbe performs HTTP GET requests to url, retrying every 1s until a | |
| 75 | 104 | // 2xx/3xx response or timeout. Used when gordon.health label is set. | |
| 76 | 105 | func httpProbe(ctx context.Context, url string, timeout time.Duration) error { | |
| @@ -82,57 +111,27 @@ func httpProbe(ctx context.Context, url string, timeout time.Duration) error { | |||
| 82 | 111 | } | |
| 83 | 112 | deadline := time.Now().Add(timeout) | |
| 84 | 113 | var lastStatus int | |
| 85 | - | ||
| 86 | - | for { | |
| 87 | - | if err := ctx.Err(); err != nil { | |
| 88 | - | return err | |
| 89 | - | } | |
| 90 | - | if time.Now().After(deadline) { | |
| 91 | - | return fmt.Errorf("HTTP probe timeout after %s: last status %d from %s", timeout, lastStatus, url) | |
| 92 | - | } | |
| 93 | - | ||
| 94 | - | remaining := time.Until(deadline) | |
| 95 | - | attemptTimeout := 2 * time.Second | |
| 96 | - | if remaining < attemptTimeout { | |
| 97 | - | attemptTimeout = remaining | |
| 98 | - | } | |
| 99 | - | req, reqErr := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) | |
| 114 | + | err := probeLoop(ctx, deadline, time.Second, 2*time.Second, func(attemptCtx context.Context) (bool, error) { | |
| 115 | + | req, reqErr := http.NewRequestWithContext(attemptCtx, http.MethodGet, url, nil) | |
| 100 | 116 | if reqErr != nil { | |
| 101 | - | return reqErr | |
| 117 | + | return false, reqErr | |
| 102 | 118 | } | |
| 103 | - | attemptCtx, cancel := context.WithTimeout(ctx, attemptTimeout) | |
| 104 | - | req = req.WithContext(attemptCtx) | |
| 119 | + | ||
| 105 | 120 | resp, err := client.Do(req) | |
| 106 | - | cancel() | |
| 107 | - | if err == nil { | |
| 108 | - | lastStatus = resp.StatusCode | |
| 109 | - | resp.Body.Close() | |
| 110 | - | if lastStatus >= 200 && lastStatus < 400 { | |
| 111 | - | return nil | |
| 112 | - | } | |
| 121 | + | if err != nil { | |
| 122 | + | return false, nil | |
| 113 | 123 | } | |
| 114 | 124 | ||
| 115 | - | sleepInterval := time.Second | |
| 116 | - | if remProbe := time.Until(deadline); remProbe < sleepInterval { | |
| 117 | - | sleepInterval = remProbe | |
| 118 | - | } | |
| 119 | - | if ctxDeadline, ok := ctx.Deadline(); ok { | |
| 120 | - | if remCtx := time.Until(ctxDeadline); remCtx < sleepInterval { | |
| 121 | - | sleepInterval = remCtx | |
| 122 | - | } | |
| 123 | - | } | |
| 124 | - | if sleepInterval <= 0 { | |
| 125 | - | if ctx.Err() != nil { | |
| 126 | - | return ctx.Err() | |
| 127 | - | } | |
| 128 | - | return fmt.Errorf("HTTP probe timeout after %s: last status %d from %s", timeout, lastStatus, url) | |
| 129 | - | } | |
| 130 | - | t := time.NewTimer(sleepInterval) | |
| 131 | - | select { | |
| 132 | - | case <-t.C: | |
| 133 | - | case <-ctx.Done(): | |
| 134 | - | t.Stop() | |
| 135 | - | return ctx.Err() | |
| 125 | + | lastStatus = resp.StatusCode | |
| 126 | + | resp.Body.Close() | |
| 127 | + | if lastStatus >= 200 && lastStatus < 400 { | |
| 128 | + | return true, nil | |
| 136 | 129 | } | |
| 130 | + | ||
| 131 | + | return false, nil | |
| 132 | + | }) | |
| 133 | + | if errors.Is(err, errProbeTimeout) { | |
| 134 | + | return fmt.Errorf("HTTP probe timeout after %s: last status %d from %s", timeout, lastStatus, url) | |
| 137 | 135 | } | |
| 136 | + | return err | |
| 138 | 137 | } | |
| @@ -2,6 +2,7 @@ package container | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | + | "errors" | |||
| 5 | "fmt" | 6 | "fmt" | ||
| 6 | "net" | 7 | "net" | ||
| 7 | "net/http" | 8 | "net/http" | ||
| @@ -10,43 +11,40 @@ import ( | |||||
| 10 | "github.com/bnema/zerowrap" | 11 | "github.com/bnema/zerowrap" | ||
| 11 | ) | 12 | ) | ||
| 12 | 13 | ||||
| 13 | - | // tcpProbe attempts a TCP connection to addr, retrying every 500ms until | 14 | + | var errProbeTimeout = errors.New("probe timeout") |
| 14 | - | // success or timeout. This is the universal fallback readiness check — | 15 | + | |
| 15 | - | // it verifies the process is at least accepting connections. | 16 | + | func probeLoop( |
| 16 | - | func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | 17 | + | ctx context.Context, |
| 17 | - | log := zerowrap.FromCtx(ctx) | 18 | + | deadline time.Time, |
| 18 | - | deadline := time.Now().Add(timeout) | 19 | + | baseSleep time.Duration, |
| 19 | - | dialer := &net.Dialer{} | 20 | + | defaultAttemptTimeout time.Duration, |
| 20 | - | attempts := 0 | 21 | + | work func(attemptCtx context.Context) (success bool, err error), |
| 21 | - | var lastErr error | 22 | + | ) error { |
| 22 | for { | 23 | for { | ||
| 23 | if err := ctx.Err(); err != nil { | 24 | if err := ctx.Err(); err != nil { | ||
| 24 | return err | 25 | return err | ||
| 25 | } | 26 | } | ||
| 26 | if time.Now().After(deadline) { | 27 | if time.Now().After(deadline) { | ||
| 27 | - | return fmt.Errorf("TCP probe timeout after %s: %s not reachable (attempts=%d, last_error=%v)", timeout, addr, attempts, lastErr) | 28 | + | return errProbeTimeout |
| 28 | } | 29 | } | ||
| 29 | 30 | ||||
| 30 | remaining := time.Until(deadline) | 31 | remaining := time.Until(deadline) | ||
| 31 | - | attemptTimeout := time.Second | 32 | + | attemptTimeout := defaultAttemptTimeout |
| 32 | if remaining < attemptTimeout { | 33 | if remaining < attemptTimeout { | ||
| 33 | attemptTimeout = remaining | 34 | attemptTimeout = remaining | ||
| 34 | } | 35 | } | ||
| 36 | + | ||||
| 35 | attemptCtx, cancel := context.WithTimeout(ctx, attemptTimeout) | 37 | attemptCtx, cancel := context.WithTimeout(ctx, attemptTimeout) | ||
| 36 | - | conn, err := dialer.DialContext(attemptCtx, "tcp", addr) | 38 | + | success, err := work(attemptCtx) |
| 37 | cancel() | 39 | cancel() | ||
| 38 | - | attempts++ | 40 | + | if err != nil { |
| 39 | - | if err == nil { | 41 | + | return err |
| 40 | - | conn.Close() | |||
| 41 | - | log.Debug().Str("addr", addr).Int("attempts", attempts).Msg("TCP probe connected") | |||
| 42 | - | return nil | |||
| 43 | } | 42 | } | ||
| 44 | - | lastErr = err | 43 | + | if success { |
| 45 | - | if attempts <= 3 || attempts%10 == 0 { | 44 | + | return nil |
| 46 | - | log.Debug().Err(err).Str("addr", addr).Int("attempt", attempts).Msg("TCP probe attempt failed") | |||
| 47 | } | 45 | } | ||
| 48 | 46 | ||||
| 49 | - | sleepInterval := 500 * time.Millisecond | 47 | + | sleepInterval := baseSleep |
| 50 | if remProbe := time.Until(deadline); remProbe < sleepInterval { | 48 | if remProbe := time.Until(deadline); remProbe < sleepInterval { | ||
| 51 | sleepInterval = remProbe | 49 | sleepInterval = remProbe | ||
| 52 | } | 50 | } | ||
| @@ -59,8 +57,9 @@ func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |||||
| 59 | if ctx.Err() != nil { | 57 | if ctx.Err() != nil { | ||
| 60 | return ctx.Err() | 58 | return ctx.Err() | ||
| 61 | } | 59 | } | ||
| 62 | - | return fmt.Errorf("TCP probe timeout after %s: %s not reachable (attempts=%d, last_error=%v)", timeout, addr, attempts, lastErr) | 60 | + | return errProbeTimeout |
| 63 | } | 61 | } | ||
| 62 | + | ||||
| 64 | t := time.NewTimer(sleepInterval) | 63 | t := time.NewTimer(sleepInterval) | ||
| 65 | select { | 64 | select { | ||
| 66 | case <-t.C: | 65 | case <-t.C: | ||
| @@ -71,6 +70,36 @@ func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |||||
| 71 | } | 70 | } | ||
| 72 | } | 71 | } | ||
| 73 | 72 | ||||
| 73 | + | // tcpProbe attempts a TCP connection to addr, retrying every 500ms until | |||
| 74 | + | // success or timeout. This is the universal fallback readiness check — | |||
| 75 | + | // it verifies the process is at least accepting connections. | |||
| 76 | + | func tcpProbe(ctx context.Context, addr string, timeout time.Duration) error { | |||
| 77 | + | log := zerowrap.FromCtx(ctx) | |||
| 78 | + | deadline := time.Now().Add(timeout) | |||
| 79 | + | dialer := &net.Dialer{} | |||
| 80 | + | attempts := 0 | |||
| 81 | + | var lastErr error | |||
| 82 | + | err := probeLoop(ctx, deadline, 500*time.Millisecond, time.Second, func(attemptCtx context.Context) (bool, error) { | |||
| 83 | + | conn, err := dialer.DialContext(attemptCtx, "tcp", addr) | |||
| 84 | + | attempts++ | |||
| 85 | + | if err == nil { | |||
| 86 | + | conn.Close() | |||
| 87 | + | log.Debug().Str("addr", addr).Int("attempts", attempts).Msg("TCP probe connected") | |||
| 88 | + | return true, nil | |||
| 89 | + | } | |||
| 90 | + | ||||
| 91 | + | lastErr = err | |||
| 92 | + | if attempts <= 3 || attempts%10 == 0 { | |||
| 93 | + | log.Debug().Err(err).Str("addr", addr).Int("attempt", attempts).Msg("TCP probe attempt failed") | |||
| 94 | + | } | |||
| 95 | + | return false, nil | |||
| 96 | + | }) | |||
| 97 | + | if errors.Is(err, errProbeTimeout) { | |||
| 98 | + | return fmt.Errorf("TCP probe timeout after %s: %s not reachable (attempts=%d, last_error=%v)", timeout, addr, attempts, lastErr) | |||
| 99 | + | } | |||
| 100 | + | return err | |||
| 101 | + | } | |||
| 102 | + | ||||
| 74 | // httpProbe performs HTTP GET requests to url, retrying every 1s until a | 103 | // httpProbe performs HTTP GET requests to url, retrying every 1s until a | ||
| 75 | // 2xx/3xx response or timeout. Used when gordon.health label is set. | 104 | // 2xx/3xx response or timeout. Used when gordon.health label is set. | ||
| 76 | func httpProbe(ctx context.Context, url string, timeout time.Duration) error { | 105 | func httpProbe(ctx context.Context, url string, timeout time.Duration) error { | ||
| @@ -82,57 +111,27 @@ func httpProbe(ctx context.Context, url string, timeout time.Duration) error { | |||||
| 82 | } | 111 | } | ||
| 83 | deadline := time.Now().Add(timeout) | 112 | deadline := time.Now().Add(timeout) | ||
| 84 | var lastStatus int | 113 | var lastStatus int | ||
| 85 | - | 114 | + | err := probeLoop(ctx, deadline, time.Second, 2*time.Second, func(attemptCtx context.Context) (bool, error) { | |
| 86 | - | for { | 115 | + | req, reqErr := http.NewRequestWithContext(attemptCtx, http.MethodGet, url, nil) |
| 87 | - | if err := ctx.Err(); err != nil { | |||
| 88 | - | return err | |||
| 89 | - | } | |||
| 90 | - | if time.Now().After(deadline) { | |||
| 91 | - | return fmt.Errorf("HTTP probe timeout after %s: last status %d from %s", timeout, lastStatus, url) | |||
| 92 | - | } | |||
| 93 | - | ||||
| 94 | - | remaining := time.Until(deadline) | |||
| 95 | - | attemptTimeout := 2 * time.Second | |||
| 96 | - | if remaining < attemptTimeout { | |||
| 97 | - | attemptTimeout = remaining | |||
| 98 | - | } | |||
| 99 | - | req, reqErr := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) | |||
| 100 | if reqErr != nil { | 116 | if reqErr != nil { | ||
| 101 | - | return reqErr | 117 | + | return false, reqErr |
| 102 | } | 118 | } | ||
| 103 | - | attemptCtx, cancel := context.WithTimeout(ctx, attemptTimeout) | 119 | + | |
| 104 | - | req = req.WithContext(attemptCtx) | |||
| 105 | resp, err := client.Do(req) | 120 | resp, err := client.Do(req) | ||
| 106 | - | cancel() | 121 | + | if err != nil { |
| 107 | - | if err == nil { | 122 | + | return false, nil |
| 108 | - | lastStatus = resp.StatusCode | |||
| 109 | - | resp.Body.Close() | |||
| 110 | - | if lastStatus >= 200 && lastStatus < 400 { | |||
| 111 | - | return nil | |||
| 112 | - | } | |||
| 113 | } | 123 | } | ||
| 114 | 124 | ||||
| 115 | - | sleepInterval := time.Second | 125 | + | lastStatus = resp.StatusCode |
| 116 | - | if remProbe := time.Until(deadline); remProbe < sleepInterval { | 126 | + | resp.Body.Close() |
| 117 | - | sleepInterval = remProbe | 127 | + | if lastStatus >= 200 && lastStatus < 400 { |
| 118 | - | } | 128 | + | return true, nil |
| 119 | - | if ctxDeadline, ok := ctx.Deadline(); ok { | |||
| 120 | - | if remCtx := time.Until(ctxDeadline); remCtx < sleepInterval { | |||
| 121 | - | sleepInterval = remCtx | |||
| 122 | - | } | |||
| 123 | - | } | |||
| 124 | - | if sleepInterval <= 0 { | |||
| 125 | - | if ctx.Err() != nil { | |||
| 126 | - | return ctx.Err() | |||
| 127 | - | } | |||
| 128 | - | return fmt.Errorf("HTTP probe timeout after %s: last status %d from %s", timeout, lastStatus, url) | |||
| 129 | - | } | |||
| 130 | - | t := time.NewTimer(sleepInterval) | |||
| 131 | - | select { | |||
| 132 | - | case <-t.C: | |||
| 133 | - | case <-ctx.Done(): | |||
| 134 | - | t.Stop() | |||
| 135 | - | return ctx.Err() | |||
| 136 | } | 129 | } | ||
| 130 | + | ||||
| 131 | + | return false, nil | |||
| 132 | + | }) | |||
| 133 | + | if errors.Is(err, errProbeTimeout) { | |||
| 134 | + | return fmt.Errorf("HTTP probe timeout after %s: last status %d from %s", timeout, lastStatus, url) | |||
| 137 | } | 135 | } | ||
| 136 | + | return err | |||
| 138 | } | 137 | } | ||
M internal/usecase/container/service_test.go +52 -38
| @@ -195,10 +195,11 @@ func TestService_Deploy_Success(t *testing.T) { | |||
| 195 | 195 | eventBus := mocks.NewMockEventPublisher(t) | |
| 196 | 196 | ||
| 197 | 197 | config := Config{ | |
| 198 | - | NetworkIsolation: false, | |
| 199 | - | VolumeAutoCreate: false, | |
| 200 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 201 | - | DrainDelay: time.Millisecond, | |
| 198 | + | NetworkIsolation: false, | |
| 199 | + | VolumeAutoCreate: false, | |
| 200 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 201 | + | DrainDelay: time.Millisecond, | |
| 202 | + | DrainDelayConfigured: true, | |
| 202 | 203 | } | |
| 203 | 204 | ||
| 204 | 205 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| @@ -275,10 +276,11 @@ func TestService_Deploy_ReadinessRecoveryWindow_AllowsTransientFlap(t *testing.T | |||
| 275 | 276 | eventBus := mocks.NewMockEventPublisher(t) | |
| 276 | 277 | ||
| 277 | 278 | config := Config{ | |
| 278 | - | NetworkIsolation: false, | |
| 279 | - | VolumeAutoCreate: false, | |
| 280 | - | ReadinessDelay: time.Millisecond, | |
| 281 | - | DrainDelay: time.Millisecond, | |
| 279 | + | NetworkIsolation: false, | |
| 280 | + | VolumeAutoCreate: false, | |
| 281 | + | ReadinessDelay: time.Millisecond, | |
| 282 | + | DrainDelay: time.Millisecond, | |
| 283 | + | DrainDelayConfigured: true, | |
| 282 | 284 | } | |
| 283 | 285 | ||
| 284 | 286 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| @@ -426,9 +428,10 @@ func TestService_Deploy_ReplacesExistingContainer(t *testing.T) { | |||
| 426 | 428 | cacheInvalidator := mocks.NewMockProxyCacheInvalidator(t) | |
| 427 | 429 | ||
| 428 | 430 | config := Config{ | |
| 429 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 430 | - | DrainDelay: time.Millisecond, | |
| 431 | - | StabilizationDelay: time.Millisecond, | |
| 431 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 432 | + | DrainDelay: time.Millisecond, | |
| 433 | + | DrainDelayConfigured: true, | |
| 434 | + | StabilizationDelay: time.Millisecond, | |
| 432 | 435 | } | |
| 433 | 436 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 434 | 437 | svc.SetProxyCacheInvalidator(cacheInvalidator) | |
| @@ -657,10 +660,11 @@ func TestService_Deploy_WithNetworkIsolation(t *testing.T) { | |||
| 657 | 660 | eventBus := mocks.NewMockEventPublisher(t) | |
| 658 | 661 | ||
| 659 | 662 | config := Config{ | |
| 660 | - | NetworkIsolation: true, | |
| 661 | - | NetworkPrefix: "gordon", | |
| 662 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 663 | - | DrainDelay: time.Millisecond, | |
| 663 | + | NetworkIsolation: true, | |
| 664 | + | NetworkPrefix: "gordon", | |
| 665 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 666 | + | DrainDelay: time.Millisecond, | |
| 667 | + | DrainDelayConfigured: true, | |
| 664 | 668 | } | |
| 665 | 669 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 666 | 670 | ctx := testContext() | |
| @@ -712,10 +716,11 @@ func TestService_Deploy_WithVolumeAutoCreate(t *testing.T) { | |||
| 712 | 716 | eventBus := mocks.NewMockEventPublisher(t) | |
| 713 | 717 | ||
| 714 | 718 | config := Config{ | |
| 715 | - | VolumeAutoCreate: true, | |
| 716 | - | VolumePrefix: "gordon", | |
| 717 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 718 | - | DrainDelay: time.Millisecond, | |
| 719 | + | VolumeAutoCreate: true, | |
| 720 | + | VolumePrefix: "gordon", | |
| 721 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 722 | + | DrainDelay: time.Millisecond, | |
| 723 | + | DrainDelayConfigured: true, | |
| 719 | 724 | } | |
| 720 | 725 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 721 | 726 | ctx := testContext() | |
| @@ -1433,6 +1438,7 @@ func TestService_Deploy_InternalDeployForcesPull(t *testing.T) { | |||
| 1433 | 1438 | InternalRegistryPassword: "secret", | |
| 1434 | 1439 | ReadinessDelay: time.Millisecond, | |
| 1435 | 1440 | DrainDelay: time.Millisecond, | |
| 1441 | + | DrainDelayConfigured: true, | |
| 1436 | 1442 | } | |
| 1437 | 1443 | ||
| 1438 | 1444 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| @@ -1503,8 +1509,9 @@ func TestService_AutoStart_StartsNewContainers(t *testing.T) { | |||
| 1503 | 1509 | eventBus := mocks.NewMockEventPublisher(t) | |
| 1504 | 1510 | ||
| 1505 | 1511 | config := Config{ | |
| 1506 | - | ReadinessDelay: time.Millisecond, | |
| 1507 | - | DrainDelay: time.Millisecond, | |
| 1512 | + | ReadinessDelay: time.Millisecond, | |
| 1513 | + | DrainDelay: time.Millisecond, | |
| 1514 | + | DrainDelayConfigured: true, | |
| 1508 | 1515 | } | |
| 1509 | 1516 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 1510 | 1517 | ctx := testContext() | |
| @@ -1549,8 +1556,9 @@ func TestService_AutoStart_SkipsExistingContainers(t *testing.T) { | |||
| 1549 | 1556 | eventBus := mocks.NewMockEventPublisher(t) | |
| 1550 | 1557 | ||
| 1551 | 1558 | config := Config{ | |
| 1552 | - | ReadinessDelay: time.Millisecond, | |
| 1553 | - | DrainDelay: time.Millisecond, | |
| 1559 | + | ReadinessDelay: time.Millisecond, | |
| 1560 | + | DrainDelay: time.Millisecond, | |
| 1561 | + | DrainDelayConfigured: true, | |
| 1554 | 1562 | } | |
| 1555 | 1563 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 1556 | 1564 | ctx := testContext() | |
| @@ -1623,10 +1631,11 @@ func TestService_AutoStart_UsesInternalDeployContext(t *testing.T) { | |||
| 1623 | 1631 | eventBus := mocks.NewMockEventPublisher(t) | |
| 1624 | 1632 | ||
| 1625 | 1633 | config := Config{ | |
| 1626 | - | RegistryDomain: "reg.example.com", | |
| 1627 | - | RegistryPort: 5000, | |
| 1628 | - | ReadinessDelay: time.Millisecond, | |
| 1629 | - | DrainDelay: time.Millisecond, | |
| 1634 | + | RegistryDomain: "reg.example.com", | |
| 1635 | + | RegistryPort: 5000, | |
| 1636 | + | ReadinessDelay: time.Millisecond, | |
| 1637 | + | DrainDelay: time.Millisecond, | |
| 1638 | + | DrainDelayConfigured: true, | |
| 1630 | 1639 | } | |
| 1631 | 1640 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 1632 | 1641 | ||
| @@ -1674,9 +1683,10 @@ func TestService_Deploy_OrphanCleanupSkipsTrackedContainer(t *testing.T) { | |||
| 1674 | 1683 | cacheInvalidator := mocks.NewMockProxyCacheInvalidator(t) | |
| 1675 | 1684 | ||
| 1676 | 1685 | config := Config{ | |
| 1677 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 1678 | - | DrainDelay: time.Millisecond, | |
| 1679 | - | StabilizationDelay: time.Millisecond, | |
| 1686 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 1687 | + | DrainDelay: time.Millisecond, | |
| 1688 | + | DrainDelayConfigured: true, | |
| 1689 | + | StabilizationDelay: time.Millisecond, | |
| 1680 | 1690 | } | |
| 1681 | 1691 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 1682 | 1692 | svc.SetProxyCacheInvalidator(cacheInvalidator) | |
| @@ -1765,8 +1775,9 @@ func TestService_Deploy_OrphanCleanupRemovesTrueOrphans(t *testing.T) { | |||
| 1765 | 1775 | eventBus := mocks.NewMockEventPublisher(t) | |
| 1766 | 1776 | ||
| 1767 | 1777 | config := Config{ | |
| 1768 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 1769 | - | DrainDelay: time.Millisecond, | |
| 1778 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests | |
| 1779 | + | DrainDelay: time.Millisecond, | |
| 1780 | + | DrainDelayConfigured: true, | |
| 1770 | 1781 | } | |
| 1771 | 1782 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 1772 | 1783 | ctx := testContext() | |
| @@ -2207,8 +2218,9 @@ func TestService_Deploy_ContextCancellation(t *testing.T) { | |||
| 2207 | 2218 | eventBus := mocks.NewMockEventPublisher(t) | |
| 2208 | 2219 | ||
| 2209 | 2220 | config := Config{ | |
| 2210 | - | ReadinessDelay: time.Millisecond, | |
| 2211 | - | DrainDelay: time.Millisecond, | |
| 2221 | + | ReadinessDelay: time.Millisecond, | |
| 2222 | + | DrainDelay: time.Millisecond, | |
| 2223 | + | DrainDelayConfigured: true, | |
| 2212 | 2224 | } | |
| 2213 | 2225 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 2214 | 2226 | ||
| @@ -2360,8 +2372,9 @@ func TestService_Deploy_SkipsRedundantDeploy(t *testing.T) { | |||
| 2360 | 2372 | eventBus := mocks.NewMockEventPublisher(t) | |
| 2361 | 2373 | ||
| 2362 | 2374 | config := Config{ | |
| 2363 | - | ReadinessDelay: time.Millisecond, | |
| 2364 | - | DrainDelay: time.Millisecond, | |
| 2375 | + | ReadinessDelay: time.Millisecond, | |
| 2376 | + | DrainDelay: time.Millisecond, | |
| 2377 | + | DrainDelayConfigured: true, | |
| 2365 | 2378 | } | |
| 2366 | 2379 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 2367 | 2380 | ctx := testContext() | |
| @@ -2413,8 +2426,9 @@ func TestService_Deploy_SkipsRedundantDeploy_WhenTrackedImageIDMissing(t *testin | |||
| 2413 | 2426 | eventBus := mocks.NewMockEventPublisher(t) | |
| 2414 | 2427 | ||
| 2415 | 2428 | config := Config{ | |
| 2416 | - | ReadinessDelay: time.Millisecond, | |
| 2417 | - | DrainDelay: time.Millisecond, | |
| 2429 | + | ReadinessDelay: time.Millisecond, | |
| 2430 | + | DrainDelay: time.Millisecond, | |
| 2431 | + | DrainDelayConfigured: true, | |
| 2418 | 2432 | } | |
| 2419 | 2433 | svc := NewService(runtime, envLoader, eventBus, nil, config) | |
| 2420 | 2434 | ctx := testContext() | |
| @@ -195,10 +195,11 @@ func TestService_Deploy_Success(t *testing.T) { | |||||
| 195 | eventBus := mocks.NewMockEventPublisher(t) | 195 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 196 | 196 | ||||
| 197 | config := Config{ | 197 | config := Config{ | ||
| 198 | - | NetworkIsolation: false, | 198 | + | NetworkIsolation: false, |
| 199 | - | VolumeAutoCreate: false, | 199 | + | VolumeAutoCreate: false, |
| 200 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | 200 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests |
| 201 | - | DrainDelay: time.Millisecond, | 201 | + | DrainDelay: time.Millisecond, |
| 202 | + | DrainDelayConfigured: true, | |||
| 202 | } | 203 | } | ||
| 203 | 204 | ||||
| 204 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 205 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| @@ -275,10 +276,11 @@ func TestService_Deploy_ReadinessRecoveryWindow_AllowsTransientFlap(t *testing.T | |||||
| 275 | eventBus := mocks.NewMockEventPublisher(t) | 276 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 276 | 277 | ||||
| 277 | config := Config{ | 278 | config := Config{ | ||
| 278 | - | NetworkIsolation: false, | 279 | + | NetworkIsolation: false, |
| 279 | - | VolumeAutoCreate: false, | 280 | + | VolumeAutoCreate: false, |
| 280 | - | ReadinessDelay: time.Millisecond, | 281 | + | ReadinessDelay: time.Millisecond, |
| 281 | - | DrainDelay: time.Millisecond, | 282 | + | DrainDelay: time.Millisecond, |
| 283 | + | DrainDelayConfigured: true, | |||
| 282 | } | 284 | } | ||
| 283 | 285 | ||||
| 284 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 286 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| @@ -426,9 +428,10 @@ func TestService_Deploy_ReplacesExistingContainer(t *testing.T) { | |||||
| 426 | cacheInvalidator := mocks.NewMockProxyCacheInvalidator(t) | 428 | cacheInvalidator := mocks.NewMockProxyCacheInvalidator(t) | ||
| 427 | 429 | ||||
| 428 | config := Config{ | 430 | config := Config{ | ||
| 429 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | 431 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests |
| 430 | - | DrainDelay: time.Millisecond, | 432 | + | DrainDelay: time.Millisecond, |
| 431 | - | StabilizationDelay: time.Millisecond, | 433 | + | DrainDelayConfigured: true, |
| 434 | + | StabilizationDelay: time.Millisecond, | |||
| 432 | } | 435 | } | ||
| 433 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 436 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 434 | svc.SetProxyCacheInvalidator(cacheInvalidator) | 437 | svc.SetProxyCacheInvalidator(cacheInvalidator) | ||
| @@ -657,10 +660,11 @@ func TestService_Deploy_WithNetworkIsolation(t *testing.T) { | |||||
| 657 | eventBus := mocks.NewMockEventPublisher(t) | 660 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 658 | 661 | ||||
| 659 | config := Config{ | 662 | config := Config{ | ||
| 660 | - | NetworkIsolation: true, | 663 | + | NetworkIsolation: true, |
| 661 | - | NetworkPrefix: "gordon", | 664 | + | NetworkPrefix: "gordon", |
| 662 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | 665 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests |
| 663 | - | DrainDelay: time.Millisecond, | 666 | + | DrainDelay: time.Millisecond, |
| 667 | + | DrainDelayConfigured: true, | |||
| 664 | } | 668 | } | ||
| 665 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 669 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 666 | ctx := testContext() | 670 | ctx := testContext() | ||
| @@ -712,10 +716,11 @@ func TestService_Deploy_WithVolumeAutoCreate(t *testing.T) { | |||||
| 712 | eventBus := mocks.NewMockEventPublisher(t) | 716 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 713 | 717 | ||||
| 714 | config := Config{ | 718 | config := Config{ | ||
| 715 | - | VolumeAutoCreate: true, | 719 | + | VolumeAutoCreate: true, |
| 716 | - | VolumePrefix: "gordon", | 720 | + | VolumePrefix: "gordon", |
| 717 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | 721 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests |
| 718 | - | DrainDelay: time.Millisecond, | 722 | + | DrainDelay: time.Millisecond, |
| 723 | + | DrainDelayConfigured: true, | |||
| 719 | } | 724 | } | ||
| 720 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 725 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 721 | ctx := testContext() | 726 | ctx := testContext() | ||
| @@ -1433,6 +1438,7 @@ func TestService_Deploy_InternalDeployForcesPull(t *testing.T) { | |||||
| 1433 | InternalRegistryPassword: "secret", | 1438 | InternalRegistryPassword: "secret", | ||
| 1434 | ReadinessDelay: time.Millisecond, | 1439 | ReadinessDelay: time.Millisecond, | ||
| 1435 | DrainDelay: time.Millisecond, | 1440 | DrainDelay: time.Millisecond, | ||
| 1441 | + | DrainDelayConfigured: true, | |||
| 1436 | } | 1442 | } | ||
| 1437 | 1443 | ||||
| 1438 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 1444 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| @@ -1503,8 +1509,9 @@ func TestService_AutoStart_StartsNewContainers(t *testing.T) { | |||||
| 1503 | eventBus := mocks.NewMockEventPublisher(t) | 1509 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 1504 | 1510 | ||||
| 1505 | config := Config{ | 1511 | config := Config{ | ||
| 1506 | - | ReadinessDelay: time.Millisecond, | 1512 | + | ReadinessDelay: time.Millisecond, |
| 1507 | - | DrainDelay: time.Millisecond, | 1513 | + | DrainDelay: time.Millisecond, |
| 1514 | + | DrainDelayConfigured: true, | |||
| 1508 | } | 1515 | } | ||
| 1509 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 1516 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 1510 | ctx := testContext() | 1517 | ctx := testContext() | ||
| @@ -1549,8 +1556,9 @@ func TestService_AutoStart_SkipsExistingContainers(t *testing.T) { | |||||
| 1549 | eventBus := mocks.NewMockEventPublisher(t) | 1556 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 1550 | 1557 | ||||
| 1551 | config := Config{ | 1558 | config := Config{ | ||
| 1552 | - | ReadinessDelay: time.Millisecond, | 1559 | + | ReadinessDelay: time.Millisecond, |
| 1553 | - | DrainDelay: time.Millisecond, | 1560 | + | DrainDelay: time.Millisecond, |
| 1561 | + | DrainDelayConfigured: true, | |||
| 1554 | } | 1562 | } | ||
| 1555 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 1563 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 1556 | ctx := testContext() | 1564 | ctx := testContext() | ||
| @@ -1623,10 +1631,11 @@ func TestService_AutoStart_UsesInternalDeployContext(t *testing.T) { | |||||
| 1623 | eventBus := mocks.NewMockEventPublisher(t) | 1631 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 1624 | 1632 | ||||
| 1625 | config := Config{ | 1633 | config := Config{ | ||
| 1626 | - | RegistryDomain: "reg.example.com", | 1634 | + | RegistryDomain: "reg.example.com", |
| 1627 | - | RegistryPort: 5000, | 1635 | + | RegistryPort: 5000, |
| 1628 | - | ReadinessDelay: time.Millisecond, | 1636 | + | ReadinessDelay: time.Millisecond, |
| 1629 | - | DrainDelay: time.Millisecond, | 1637 | + | DrainDelay: time.Millisecond, |
| 1638 | + | DrainDelayConfigured: true, | |||
| 1630 | } | 1639 | } | ||
| 1631 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 1640 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 1632 | 1641 | ||||
| @@ -1674,9 +1683,10 @@ func TestService_Deploy_OrphanCleanupSkipsTrackedContainer(t *testing.T) { | |||||
| 1674 | cacheInvalidator := mocks.NewMockProxyCacheInvalidator(t) | 1683 | cacheInvalidator := mocks.NewMockProxyCacheInvalidator(t) | ||
| 1675 | 1684 | ||||
| 1676 | config := Config{ | 1685 | config := Config{ | ||
| 1677 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | 1686 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests |
| 1678 | - | DrainDelay: time.Millisecond, | 1687 | + | DrainDelay: time.Millisecond, |
| 1679 | - | StabilizationDelay: time.Millisecond, | 1688 | + | DrainDelayConfigured: true, |
| 1689 | + | StabilizationDelay: time.Millisecond, | |||
| 1680 | } | 1690 | } | ||
| 1681 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 1691 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 1682 | svc.SetProxyCacheInvalidator(cacheInvalidator) | 1692 | svc.SetProxyCacheInvalidator(cacheInvalidator) | ||
| @@ -1765,8 +1775,9 @@ func TestService_Deploy_OrphanCleanupRemovesTrueOrphans(t *testing.T) { | |||||
| 1765 | eventBus := mocks.NewMockEventPublisher(t) | 1775 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 1766 | 1776 | ||||
| 1767 | config := Config{ | 1777 | config := Config{ | ||
| 1768 | - | ReadinessDelay: time.Millisecond, // Minimal delay for tests | 1778 | + | ReadinessDelay: time.Millisecond, // Minimal delay for tests |
| 1769 | - | DrainDelay: time.Millisecond, | 1779 | + | DrainDelay: time.Millisecond, |
| 1780 | + | DrainDelayConfigured: true, | |||
| 1770 | } | 1781 | } | ||
| 1771 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 1782 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 1772 | ctx := testContext() | 1783 | ctx := testContext() | ||
| @@ -2207,8 +2218,9 @@ func TestService_Deploy_ContextCancellation(t *testing.T) { | |||||
| 2207 | eventBus := mocks.NewMockEventPublisher(t) | 2218 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 2208 | 2219 | ||||
| 2209 | config := Config{ | 2220 | config := Config{ | ||
| 2210 | - | ReadinessDelay: time.Millisecond, | 2221 | + | ReadinessDelay: time.Millisecond, |
| 2211 | - | DrainDelay: time.Millisecond, | 2222 | + | DrainDelay: time.Millisecond, |
| 2223 | + | DrainDelayConfigured: true, | |||
| 2212 | } | 2224 | } | ||
| 2213 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 2225 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 2214 | 2226 | ||||
| @@ -2360,8 +2372,9 @@ func TestService_Deploy_SkipsRedundantDeploy(t *testing.T) { | |||||
| 2360 | eventBus := mocks.NewMockEventPublisher(t) | 2372 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 2361 | 2373 | ||||
| 2362 | config := Config{ | 2374 | config := Config{ | ||
| 2363 | - | ReadinessDelay: time.Millisecond, | 2375 | + | ReadinessDelay: time.Millisecond, |
| 2364 | - | DrainDelay: time.Millisecond, | 2376 | + | DrainDelay: time.Millisecond, |
| 2377 | + | DrainDelayConfigured: true, | |||
| 2365 | } | 2378 | } | ||
| 2366 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 2379 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 2367 | ctx := testContext() | 2380 | ctx := testContext() | ||
| @@ -2413,8 +2426,9 @@ func TestService_Deploy_SkipsRedundantDeploy_WhenTrackedImageIDMissing(t *testin | |||||
| 2413 | eventBus := mocks.NewMockEventPublisher(t) | 2426 | eventBus := mocks.NewMockEventPublisher(t) | ||
| 2414 | 2427 | ||||
| 2415 | config := Config{ | 2428 | config := Config{ | ||
| 2416 | - | ReadinessDelay: time.Millisecond, | 2429 | + | ReadinessDelay: time.Millisecond, |
| 2417 | - | DrainDelay: time.Millisecond, | 2430 | + | DrainDelay: time.Millisecond, |
| 2431 | + | DrainDelayConfigured: true, | |||
| 2418 | } | 2432 | } | ||
| 2419 | svc := NewService(runtime, envLoader, eventBus, nil, config) | 2433 | svc := NewService(runtime, envLoader, eventBus, nil, config) | ||
| 2420 | ctx := testContext() | 2434 | ctx := testContext() | ||