2023-08-17 14:14:59 -03:00
|
|
|
package healthcheckcmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-08-26 11:47:46 -03:00
|
|
|
"errors"
|
2023-08-17 14:14:59 -03:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
2023-08-24 22:03:58 -03:00
|
|
|
"log/slog"
|
2023-08-17 14:14:59 -03:00
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
|
|
|
|
"git.maronato.dev/maronato/goshort/cmd/shared"
|
|
|
|
"git.maronato.dev/maronato/goshort/internal/config"
|
2023-08-24 22:03:58 -03:00
|
|
|
"git.maronato.dev/maronato/goshort/internal/util/logging"
|
2023-08-17 14:14:59 -03:00
|
|
|
"github.com/peterbourgon/ff/v3/ffcli"
|
|
|
|
)
|
|
|
|
|
2023-08-26 11:47:46 -03:00
|
|
|
var ErrFailedHealthCheck = errors.New("healthcheck failed")
|
|
|
|
|
2023-08-17 14:14:59 -03:00
|
|
|
func New(cfg *config.Config) *ffcli.Command {
|
|
|
|
// Create the flagset and register the flags.
|
|
|
|
fs := flag.NewFlagSet("goshort healthcheck", flag.ContinueOnError)
|
|
|
|
|
|
|
|
shared.RegisterBaseFlags(fs, cfg)
|
|
|
|
|
|
|
|
// Create the command and options
|
|
|
|
cmd := shared.NewCommand(cfg, exec)
|
|
|
|
opts := shared.NewSharedCmdOptions()
|
|
|
|
|
|
|
|
// Return the ffcli command.
|
|
|
|
return &ffcli.Command{
|
|
|
|
Name: "healthcheck",
|
|
|
|
ShortUsage: "goshort healthcheck [flags]",
|
|
|
|
ShortHelp: "Calls the healthcheck endpoint of the server",
|
|
|
|
FlagSet: fs,
|
|
|
|
Exec: cmd.Exec,
|
|
|
|
Options: opts,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// exec makes a request to the healthcheck endpoint.
|
|
|
|
// If the request fails, return an error
|
|
|
|
// Otherwise, return nil.
|
|
|
|
func exec(ctx context.Context, cfg *config.Config) error {
|
2023-08-24 22:03:58 -03:00
|
|
|
l := logging.FromCtx(ctx)
|
|
|
|
l.Debug("Executing healthcheck command", slog.Any("config", cfg))
|
|
|
|
|
2023-08-17 14:14:59 -03:00
|
|
|
addr := url.URL{
|
|
|
|
Host: net.JoinHostPort(cfg.Host, cfg.Port),
|
|
|
|
Scheme: "http",
|
|
|
|
Path: "/healthz",
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, addr.String(), http.NoBody)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error creating request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error making request: %w", err)
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
2023-08-18 14:08:11 -03:00
|
|
|
return fmt.Errorf(
|
2023-08-26 11:47:46 -03:00
|
|
|
"healthcheck endpoint returned status code %d: %w",
|
2023-08-17 14:14:59 -03:00
|
|
|
resp.StatusCode,
|
2023-08-26 11:47:46 -03:00
|
|
|
ErrFailedHealthCheck,
|
2023-08-17 14:14:59 -03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|