Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 16 additions & 7 deletions pkg/checks/checkgrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,31 @@ import (

"github.com/opencloud-eu/opencloud/pkg/handlers"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials/insecure"
)

// NewGRPCCheck checks the reachability of a grpc server.
func NewGRPCCheck(address string) func(context.Context) error {
return func(_ context.Context) error {
address, err := handlers.FailSaveAddress(address)
if err != nil {
return err
address, err := handlers.FailSaveAddress(address)
if err != nil {
return func(context.Context) error {
return fmt.Errorf("invalid address: %v", err)
}
}

conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return func(context.Context) error {
return fmt.Errorf("could not connect to grpc server: %v", err)
}
_ = conn.Close()
}

return func(ctx context.Context) error {
s := conn.GetState()
if s == connectivity.TransientFailure || s == connectivity.Shutdown {
return fmt.Errorf("grpc connection in bad state: %v", s)
}
return nil
}
}
27 changes: 16 additions & 11 deletions pkg/checks/checkhttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ import (

// NewHTTPCheck checks the reachability of a http server.
func NewHTTPCheck(url string) func(context.Context) error {
return func(_ context.Context) error {
url, err := handlers.FailSaveAddress(url)
if err != nil {
return err
}

if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "http://" + url
url, err := handlers.FailSaveAddress(url)
if err != nil {
return func(context.Context) error {
return fmt.Errorf("invalid url: %v", err)
}
}
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "http://" + url
}

c := http.Client{
Timeout: 3 * time.Second,
c := &http.Client{
Timeout: 3 * time.Second,
}
return func(ctx context.Context) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return err
}
resp, err := c.Get(url)
resp, err := c.Do(req)
if err != nil {
return fmt.Errorf("could not connect to http server: %v", err)
}
Expand Down
14 changes: 8 additions & 6 deletions pkg/checks/checknats.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import (

// NewNatsCheck checks the reachability of a nats server.
func NewNatsCheck(natsCluster string, options ...nats.Option) func(context.Context) error {
return func(_ context.Context) error {
n, err := nats.Connect(natsCluster, options...)
if err != nil {
conn, err := nats.Connect(natsCluster, options...)
if err != nil {
return func(context.Context) error {
return fmt.Errorf("could not connect to nats server: %v", err)
}
defer n.Close()
if n.Status() != nats.CONNECTED {
return fmt.Errorf("nats server not connected")
}

return func(_ context.Context) error {
if conn.Status() != nats.CONNECTED {
return fmt.Errorf("nats server not connected: %v", conn.Status())
}
return nil
}
Expand Down
19 changes: 8 additions & 11 deletions pkg/checks/checktcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,19 @@ import (

// NewTCPCheck returns a check that connects to a given tcp endpoint.
func NewTCPCheck(address string) func(context.Context) error {
return func(_ context.Context) error {
address, err := handlers.FailSaveAddress(address)
if err != nil {
return err
}

conn, err := net.DialTimeout("tcp", address, 3*time.Second)
if err != nil {
address, err := handlers.FailSaveAddress(address)
if err != nil {
return func(context.Context) error {
return err
}
}

err = conn.Close()
return func(ctx context.Context) error {
d := net.Dialer{Timeout: 3 * time.Second}
conn, err := d.DialContext(ctx, "tcp", address)
if err != nil {
return err
}

return nil
return conn.Close()
}
}
32 changes: 5 additions & 27 deletions pkg/handlers/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"io"
"maps"
"net"
"net/http"
"strings"

Expand Down Expand Up @@ -117,32 +116,11 @@ func (h *CheckHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

// FailSaveAddress replaces wildcard addresses with the outbound IP.
func FailSaveAddress(address string) (string, error) {
if strings.Contains(address, "0.0.0.0") || strings.Contains(address, "::") {
outboundIp, err := getOutBoundIP()
if err != nil {
return "", err
}
address = strings.Replace(address, "0.0.0.0", outboundIp, 1)
address = strings.Replace(address, "::", "["+outboundIp+"]", 1)
address = strings.Replace(address, "[::]", "["+outboundIp+"]", 1)
if strings.Contains(address, "0.0.0.0") {
return strings.Replace(address, "0.0.0.0", "localhost", 1), nil
}
return address, nil
}

// getOutBoundIP returns the outbound IP address.
func getOutBoundIP() (string, error) {
interfacesAddresses, err := net.InterfaceAddrs()
if err != nil {
return "", err
}

for _, address := range interfacesAddresses {
if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
return ipNet.IP.String(), nil
}
}
if strings.Contains(address, "::") {
return strings.Replace(strings.Replace(address, "[::]", "localhost", 1), "::", "localhost", 1), nil
}

return "", fmt.Errorf("no IP found")
return address, nil
}
6 changes: 3 additions & 3 deletions services/proxy/pkg/server/debug/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ func Server(opts ...Option) (*http.Server, error) {
options := newOptions(opts...)

healthHandlerConfiguration := handlers.NewCheckHandlerConfiguration().
WithLogger(options.Logger).
WithCheck("web reachability", checks.NewHTTPCheck(options.Config.HTTP.Addr))
WithLogger(options.Logger)

readyHandlerConfiguration := healthHandlerConfiguration.
WithCheck("nats reachability", checks.NewNatsCheck(options.Config.Events.Endpoint))
WithCheck("nats reachability", checks.NewNatsCheck(options.Config.Events.Endpoint)).
WithCheck("web reachability", checks.NewHTTPCheck(options.Config.HTTP.Addr))

var configDumpFunc http.HandlerFunc = configDump(options.Config)
return debug.NewService(
Expand Down
Loading