Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
b784246
Add basic /healthcheck directory structure
monazhn Jun 29, 2021
fe5a7bc
Initial commit of healthcheck
tifftoff Jun 29, 2021
d9b3840
Add README
monazhn Jun 29, 2021
fa57263
create function to initialize HTTP endpoints
tifftoff Jun 29, 2021
0d5d6ae
add documentation for package healthcheck
tifftoff Jun 29, 2021
b03576a
add flag indicating whether to use healthcheck or not
tifftoff Jun 29, 2021
c0a954d
Add basic structure for liveness + readiness tests
monazhn Jun 29, 2021
c5fe04d
Initial commit
tifftoff Jun 29, 2021
c809c0b
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
tifftoff Jun 29, 2021
36388e3
add exported function for proxy client to sya its ready
tifftoff Jun 29, 2021
30ea13e
make proxy succeed readiness test when ready for new connections
tifftoff Jun 30, 2021
5c5e540
Add hc struct, max connections check for readiness
monazhn Jun 30, 2021
e77ecc8
Error check ListenAndServe
monazhn Jun 30, 2021
405fbff
Add comments to healthcheck.go
monazhn Jun 30, 2021
b3836b6
set up testing
tifftoff Jun 30, 2021
d0be8f7
wrote tests for liveness, bad startup, and successful startup
tifftoff Jun 30, 2021
a31adb3
Include tests for Readiness and MaxConnections
monazhn Jul 1, 2021
c47bbc4
fixing tests
tifftoff Jul 1, 2021
9a0328b
Revert code pushed by mistake :-(
monazhn Jul 1, 2021
450f18f
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
tifftoff Jul 1, 2021
d1ddfe5
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
tifftoff Jul 1, 2021
b75abed
Change test for MaxConnections to be more complete
monazhn Jul 1, 2021
200a92b
Remove unwanted test
monazhn Jul 1, 2021
d832fb7
Add License information
monazhn Jul 1, 2021
10033a5
fix copyright year
tifftoff Jul 1, 2021
f14b4f2
use early returns instead of else
tifftoff Jul 1, 2021
0b989c1
use early return on error case
tifftoff Jul 1, 2021
234dd7a
sync reads and writes
tifftoff Jul 1, 2021
599fd09
rename InitHealthCheck to NewHealthCheck
tifftoff Jul 1, 2021
ff2c39b
forgot an unlock
tifftoff Jul 1, 2021
5835b2c
add pointer receiver to NotifyReadyForConnections()
tifftoff Jul 1, 2021
1f8e64e
GoDoc for exported functions
monazhn Jul 6, 2021
0efecc0
Keep reference to server
monazhn Jul 6, 2021
dfdfe35
Define consts for URLs, paths, port numbers
monazhn Jul 6, 2021
b3bc070
Close health check after each test
monazhn Jul 6, 2021
e6f929f
Fix for flaky tests.
monazhn Jul 6, 2021
0dac6c5
"Factored" const declarations
monazhn Jul 7, 2021
633f95c
Add informative error logs when readiness fails
monazhn Jul 7, 2021
076329c
styling
tifftoff Jul 7, 2021
c7a4142
Merge branch 'GoogleCloudPlatform:main' into health-check
monazhn Jul 7, 2021
5b1c3ab
Add comments
monazhn Jul 8, 2021
a8da1d6
renamed mutex variables, added comments
tifftoff Jul 8, 2021
0ac0523
chagne Inc. to LLC
tifftoff Jul 9, 2021
e8b86b5
define locks in HC struct, replace usage of startupL with readinessL
tifftoff Jul 9, 2021
e2c8126
change CloseHealthCheck to Close
tifftoff Jul 9, 2021
9ee6d99
omit newHealthCheck function
tifftoff Jul 9, 2021
b2cb592
edit test names
tifftoff Jul 9, 2021
98bcf1c
added comments describing each test
tifftoff Jul 9, 2021
f98f04d
forgot a period
tifftoff Jul 9, 2021
93e0a1f
removed variables storing the results of the health tests
tifftoff Jul 9, 2021
a5559bf
typo
tifftoff Jul 9, 2021
f8c1f97
Derive URLs from constants
monazhn Jul 9, 2021
2d62d1e
Separate ListenAndServe into Listen and Serve
monazhn Jul 9, 2021
9c519f7
made port number a configurable argument from command line
tifftoff Jul 9, 2021
3a49c95
Use non-default ServeMux
monazhn Jul 9, 2021
6bf83ea
Iterate readiness criteria
monazhn Jul 10, 2021
463dd2e
Have Close function take a context as an argument
monazhn Jul 10, 2021
46d226f
Define a constant for testing port
monazhn Jul 10, 2021
8cbd3df
Remove deferred call to Close()
monazhn Jul 12, 2021
b6e2be3
rename flag to useHttpHealthCheck
tifftoff Jul 12, 2021
502ee01
make caller ensure hc is not nil before NotifyReadyForConnections
tifftoff Jul 12, 2021
32ed5c1
fix flag
tifftoff Jul 13, 2021
306d070
Internal health check package
monazhn Jul 13, 2021
6247e30
Remove incomplete README
monazhn Jul 13, 2021
47088d6
Clean up comments
monazhn Jul 13, 2021
33fb809
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
monazhn Jul 13, 2021
e629b61
change default port to 9090
tifftoff Jul 13, 2021
ddf3faa
place mutex before boolean
tifftoff Jul 13, 2021
50c5156
removed newlines
tifftoff Jul 13, 2021
e0dae22
rename readinessTest and livenessTest to isReady and isLive
tifftoff Jul 13, 2021
0bf5baf
rename NotifyReadyForConnections to NotifyStarted
tifftoff Jul 13, 2021
0d7dc72
fix function names in comments
tifftoff Jul 13, 2021
de3bd1c
change package to healthcheck_test
tifftoff Jul 13, 2021
331e6bc
inline
tifftoff Jul 13, 2021
22729f3
reduce startedL critical section is isReady
tifftoff Jul 13, 2021
8e2d75a
rename proxyClient parameter to c
tifftoff Jul 13, 2021
2ca9230
make exported functions return errors instead of logging them
tifftoff Jul 13, 2021
856eb58
use errors.Is instead of basic equality check
tifftoff Jul 13, 2021
237410a
change MaxConnections from 10 to 1 when testing
tifftoff Jul 13, 2021
e5a5e41
Delete README file
monazhn Jul 13, 2021
fab7dd9
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
monazhn Jul 13, 2021
ae7b6ae
rename flag from useHttpHealthCheck to useHTTPHealthCheck
tifftoff Jul 13, 2021
350e6cc
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
tifftoff Jul 13, 2021
2f19a54
Change port number for testing
monazhn Jul 13, 2021
9043485
rename hcPort flag to healthCheckPort
tifftoff Jul 13, 2021
115c201
Add GoDoc for started flag
monazhn Jul 13, 2021
4734ed6
Add back deferred Close()
monazhn Jul 13, 2021
edb2a08
Rename HC to Server
monazhn Jul 13, 2021
c4cc7ec
Move internal pkg to cmd/cloud_sql_proxy/internal
monazhn Jul 13, 2021
30e9c0b
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
tifftoff Jul 13, 2021
362ce6e
fix imports and name changes from HC to Server
tifftoff Jul 13, 2021
8c58cc3
keep startedL and started together
tifftoff Jul 13, 2021
07c3295
Rename health check port
monazhn Jul 13, 2021
7931176
Merge branch 'health-check' of https://github.com/monazhn/cloudsql-pr…
tifftoff Jul 13, 2021
c795f3e
rename variables for clarity
tifftoff Jul 13, 2021
6bcddc5
Check for concrete error type
monazhn Jul 13, 2021
6f05d65
add AvailableConn function
tifftoff Jul 13, 2021
3426cc9
Table-driven tests
monazhn Jul 14, 2021
b6ce6fe
Remove unnecessary newline characters
monazhn Jul 14, 2021
ac78dd0
Rename proxyClient to c
monazhn Jul 14, 2021
3c84d6e
move started docstring
tifftoff Jul 14, 2021
714ec3e
make Serve's log message more explicit
tifftoff Jul 14, 2021
9533088
inline Close
tifftoff Jul 14, 2021
84c0c85
make proxy exit if health check cannot be initialized
tifftoff Jul 14, 2021
ec6b649
Use pre-declared ctx variable
monazhn Jul 14, 2021
fc9f4da
use http package constants instead of 500 and 200
tifftoff Jul 14, 2021
fe19c6b
add comment to AvailableConn
tifftoff Jul 14, 2021
3bc693c
use a channel for started instead of a bool
tifftoff Jul 14, 2021
90002bf
change started channel type
tifftoff Jul 14, 2021
f40df79
Revert back to separate tests
monazhn Jul 14, 2021
ffa7280
use Once to ensure that started can only close once
tifftoff Jul 15, 2021
4ba3cfe
make once a pointer
tifftoff Jul 15, 2021
92af34a
Merge branch 'GoogleCloudPlatform:main' into health-check
monazhn Jul 15, 2021
460f62c
Merge pull request #1 from monazhn/health-check
tifftoff Jul 15, 2021
aec9362
add startup probe
tifftoff Jul 19, 2021
2048a33
add tests against /startup
tifftoff Jul 19, 2021
ef65fae
fix comments
tifftoff Jul 19, 2021
14e6f04
add helper function that checks the status of the started channel
tifftoff Jul 20, 2021
6751476
fix logging message typo
tifftoff Jul 20, 2021
0055c15
forgot a return
tifftoff Jul 20, 2021
c5709e6
comments
tifftoff Jul 21, 2021
57343df
Merge pull request #2 from monazhn/health-check
tifftoff Jul 22, 2021
c7d116a
Merge branch 'GoogleCloudPlatform:main' into main
monazhn Jul 22, 2021
4834ab3
Merge branch 'GoogleCloudPlatform:main' into main
monazhn Jul 28, 2021
11655a3
Add health check flags to README
monazhn Jul 28, 2021
dd22c2c
Clarify wording
monazhn Jul 28, 2021
c64a93c
Move changes into separate branch
monazhn Jul 29, 2021
ea94208
Add instructions for using the new health check feature (#3)
monazhn Jul 30, 2021
a29b40d
Merge branch 'GoogleCloudPlatform:main' into main
monazhn Jul 30, 2021
046ffb4
Merge branch 'GoogleCloudPlatform:main' into main
monazhn Jul 30, 2021
4aaff8d
Fix lint
monazhn Jul 30, 2021
14c553c
Improve error message
monazhn Jul 30, 2021
3e98064
Modify error condition
monazhn Jul 31, 2021
e1e8dfb
Remove region tags
monazhn Aug 2, 2021
f18f549
Use footer link
monazhn Aug 2, 2021
1ab9c5c
Clean up docstrings
monazhn Aug 2, 2021
edef210
Clean up
monazhn Aug 2, 2021
e97040e
Add instructions for using health checks
monazhn Aug 2, 2021
6b3e7dc
Update README.md
tifftoff Aug 2, 2021
7bb5e81
Merge branch 'main' into main
monazhn Aug 2, 2021
1339f8c
Link to README
monazhn Aug 2, 2021
6ebdd83
Merge branch 'main' into main
enocom Aug 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,15 @@ message and optionally stacktrace. For example, the startup message looks like:
{"severity":"INFO","timestamp":"2020-10-12T07:20:50.52Z","caller":"cloud_sql_proxy/cloud_sql_proxy.go:510","message":"Using gcloud's active project: [my-project-id]"}
```

#### `-use_http_health_check`

Enables HTTP health checks for the proxy, including startup, liveness, and readiness probing.
Requires that you configure the Kubernetes container with HTTP probes ([instructions][health-check-example]).

#### `-health_check_port=8090`

Specifies the port that the health check server listens and serves on. Defaults to 8090.

## Running as a Kubernetes Sidecar

See the [example here][sidecar-example] as well as [Connecting from Google
Expand Down Expand Up @@ -334,6 +343,7 @@ Install via Nuget, follow these
[connect-to-k8s]: https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine
[connection-overview]: https://cloud.google.com/sql/docs/mysql/connect-overview
[contributing]: CONTRIBUTING.md
[health-check-example]: https://github.com/GoogleCloudPlatform/cloudsql-proxy/tree/main/examples/k8s-health-check#cloud-sql-proxy-health-checks
[iam-auth]: https://cloud.google.com/sql/docs/postgres/authentication
[pkg-badge]: https://pkg.go.dev/badge/github.com/GoogleCloudPlatform/cloudsql-proxy.svg
[pkg-docs]: https://pkg.go.dev/github.com/GoogleCloudPlatform/cloudsql-proxy
Expand Down
19 changes: 19 additions & 0 deletions cmd/cloud_sql_proxy/cloud_sql_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"syscall"
"time"

"github.com/GoogleCloudPlatform/cloudsql-proxy/cmd/cloud_sql_proxy/internal/healthcheck"
"github.com/GoogleCloudPlatform/cloudsql-proxy/logging"
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/certs"
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/fuse"
Expand Down Expand Up @@ -131,6 +132,10 @@ unavailable.`,
`When set, the proxy uses this host as the base API path. Example:
https://sqladmin.googleapis.com`,
)

// Settings for healthcheck
useHTTPHealthCheck = flag.Bool("use_http_health_check", false, "When set, creates an HTTP server that checks and communicates the health of the proxy client.")
healthCheckPort = flag.String("health_check_port", "8090", "When applicable, health checks take place on this port number. Defaults to 8090.")
)

const (
Expand Down Expand Up @@ -580,6 +585,16 @@ func main() {
RefreshCfgBuffer: refreshCfgBuffer,
}

var hc *healthcheck.Server
if *useHTTPHealthCheck {
hc, err = healthcheck.NewServer(proxyClient, *healthCheckPort)
if err != nil {
logging.Errorf("Could not initialize health check server: %v", err)
os.Exit(1)
}
defer hc.Close(ctx)
}

// Initialize a source of new connections to Cloud SQL instances.
var connSrc <-chan proxy.Conn
if *useFuse {
Expand Down Expand Up @@ -619,6 +634,10 @@ func main() {

logging.Infof("Ready for new connections")

if hc != nil {
hc.NotifyStarted()
}

signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)

Expand Down
153 changes: 153 additions & 0 deletions cmd/cloud_sql_proxy/internal/healthcheck/healthcheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2021 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package healthcheck tests and communicates the health of the Cloud SQL Auth proxy.
package healthcheck

import (
"context"
"errors"
"net"
"net/http"
"sync"

"github.com/GoogleCloudPlatform/cloudsql-proxy/logging"
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
)

const (
startupPath = "/startup"
livenessPath = "/liveness"
readinessPath = "/readiness"
)

// Server is a type used to implement health checks for the proxy.
type Server struct {
// started is used to indicate whether the proxy has finished starting up.
// If started is open, startup has not finished. If started is closed,
// startup is complete.
started chan struct{}
// once ensures that started can only be closed once.
once *sync.Once
// port designates the port number on which Server listens and serves.
port string
// srv is a pointer to the HTTP server used to communicate proxy health.
srv *http.Server
}

// NewServer initializes a Server and exposes HTTP endpoints used to
// communicate proxy health.
func NewServer(c *proxy.Client, port string) (*Server, error) {
mux := http.NewServeMux()

srv := &http.Server{
Addr: ":" + port,
Handler: mux,
}

hcServer := &Server{
started: make(chan struct{}),
once: &sync.Once{},
port: port,
srv: srv,
}

mux.HandleFunc(startupPath, func(w http.ResponseWriter, _ *http.Request) {
if !hcServer.proxyStarted() {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte("error"))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})

mux.HandleFunc(readinessPath, func(w http.ResponseWriter, _ *http.Request) {
if !isReady(c, hcServer) {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte("error"))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})

mux.HandleFunc(livenessPath, func(w http.ResponseWriter, _ *http.Request) {
if !isLive() { // Because isLive() always returns true, this case should not be reached.
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte("error"))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})

ln, err := net.Listen("tcp", srv.Addr)
if err != nil {
return nil, err
}

go func() {
if err := srv.Serve(ln); err != nil && !errors.Is(err, http.ErrServerClosed) {
logging.Errorf("Failed to start health check HTTP server: %v", err)
}
}()

return hcServer, nil
}

// Close gracefully shuts down the HTTP server belonging to the Server.
func (s *Server) Close(ctx context.Context) error {
return s.srv.Shutdown(ctx)
}

// NotifyStarted tells the Server that the proxy has finished startup.
func (s *Server) NotifyStarted() {
s.once.Do(func() { close(s.started) })
}

// proxyStarted returns true if started is closed, false otherwise.
func (s *Server) proxyStarted() bool {
select {
case <-s.started:
return true
default:
return false
}
}

// isLive returns true as long as the proxy is running.
func isLive() bool {
return true
}

// isReady will check the following criteria before determining whether the
// proxy is ready for new connections.
// 1. Finished starting up / been sent the 'Ready for Connections' log.
// 2. Not yet hit the MaxConnections limit, if applicable.
func isReady(c *proxy.Client, s *Server) bool {
// Not ready until we reach the 'Ready for Connections' log
if !s.proxyStarted() {
logging.Errorf("Readiness failed because proxy has not finished starting up.")
return false
}

// Not ready if the proxy is at the optional MaxConnections limit.
if !c.AvailableConn() {
logging.Errorf("Readiness failed because proxy has reached the maximum connections limit (%d).", c.MaxConnections)
return false
}

return true
}
155 changes: 155 additions & 0 deletions cmd/cloud_sql_proxy/internal/healthcheck/healthcheck_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// Copyright 2021 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package healthcheck_test

import (
"context"
"net/http"
"testing"

"github.com/GoogleCloudPlatform/cloudsql-proxy/cmd/cloud_sql_proxy/internal/healthcheck"
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
)

const (
startupPath = "/startup"
livenessPath = "/liveness"
readinessPath = "/readiness"
testPort = "8090"
)

// Test to verify that when the proxy client is up, the liveness endpoint writes http.StatusOK.
func TestLiveness(t *testing.T) {
s, err := healthcheck.NewServer(&proxy.Client{}, testPort)
if err != nil {
t.Fatalf("Could not initialize health check: %v", err)
}
defer s.Close(context.Background())

resp, err := http.Get("http://localhost:" + testPort + livenessPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v", err)
}
if resp.StatusCode != http.StatusOK {
t.Errorf("Got status code %v instead of %v", resp.StatusCode, http.StatusOK)
}
}

// Test to verify that when startup has NOT finished, the startup and readiness endpoints write
// http.StatusServiceUnavailable.
func TestStartupFail(t *testing.T) {
s, err := healthcheck.NewServer(&proxy.Client{}, testPort)
if err != nil {
t.Fatalf("Could not initialize health check: %v\n", err)
}
defer s.Close(context.Background())

resp, err := http.Get("http://localhost:" + testPort + startupPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v\n", err)
}
if resp.StatusCode != http.StatusServiceUnavailable {
t.Errorf("%v returned status code %v instead of %v", startupPath, resp.StatusCode, http.StatusServiceUnavailable)
}

resp, err = http.Get("http://localhost:" + testPort + readinessPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v\n", err)
}
if resp.StatusCode != http.StatusServiceUnavailable {
t.Errorf("%v returned status code %v instead of %v", readinessPath, resp.StatusCode, http.StatusServiceUnavailable)
}
}

// Test to verify that when startup HAS finished (and MaxConnections limit not specified),
// the startup and readiness endpoints write http.StatusOK.
func TestStartupPass(t *testing.T) {
s, err := healthcheck.NewServer(&proxy.Client{}, testPort)
if err != nil {
t.Fatalf("Could not initialize health check: %v\n", err)
}
defer s.Close(context.Background())

// Simulate the proxy client completing startup.
s.NotifyStarted()

resp, err := http.Get("http://localhost:" + testPort + startupPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v\n", err)
}
if resp.StatusCode != http.StatusOK {
t.Errorf("%v returned status code %v instead of %v", startupPath, resp.StatusCode, http.StatusOK)
}

resp, err = http.Get("http://localhost:" + testPort + readinessPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v\n", err)
}
if resp.StatusCode != http.StatusOK {
t.Errorf("%v returned status code %v instead of %v", readinessPath, resp.StatusCode, http.StatusOK)
}
}

// Test to verify that when startup has finished, but MaxConnections has been reached,
// the readiness endpoint writes http.StatusServiceUnavailable.
func TestMaxConnectionsReached(t *testing.T) {
c := &proxy.Client{
MaxConnections: 1,
}
s, err := healthcheck.NewServer(c, testPort)
if err != nil {
t.Fatalf("Could not initialize health check: %v", err)
}
defer s.Close(context.Background())

s.NotifyStarted()
c.ConnectionsCounter = c.MaxConnections // Simulate reaching the limit for maximum number of connections

resp, err := http.Get("http://localhost:" + testPort + readinessPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v", err)
}
if resp.StatusCode != http.StatusServiceUnavailable {
t.Errorf("Got status code %v instead of %v", resp.StatusCode, http.StatusServiceUnavailable)
}
}

// Test to verify that after closing a healthcheck, its liveness endpoint serves
// an error.
func TestCloseHealthCheck(t *testing.T) {
s, err := healthcheck.NewServer(&proxy.Client{}, testPort)
if err != nil {
t.Fatalf("Could not initialize health check: %v", err)
}
defer s.Close(context.Background())

resp, err := http.Get("http://localhost:" + testPort + livenessPath)
if err != nil {
t.Fatalf("HTTP GET failed: %v", err)
}
if resp.StatusCode != http.StatusOK {
t.Errorf("Got status code %v instead of %v", resp.StatusCode, http.StatusOK)
}

err = s.Close(context.Background())
if err != nil {
t.Fatalf("Failed to close health check: %v", err)
}

_, err = http.Get("http://localhost:" + testPort + livenessPath)
if err == nil {
t.Fatalf("HTTP GET did not return error after closing health check server.")
}
}
Loading