goshort/cmd/healthcheck/healthcheck.go
2023-08-26 11:47:46 -03:00

76 lines
1.8 KiB
Go

package healthcheckcmd
import (
"context"
"errors"
"flag"
"fmt"
"log/slog"
"net"
"net/http"
"net/url"
"git.maronato.dev/maronato/goshort/cmd/shared"
"git.maronato.dev/maronato/goshort/internal/config"
"git.maronato.dev/maronato/goshort/internal/util/logging"
"github.com/peterbourgon/ff/v3/ffcli"
)
var ErrFailedHealthCheck = errors.New("healthcheck failed")
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 {
l := logging.FromCtx(ctx)
l.Debug("Executing healthcheck command", slog.Any("config", cfg))
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 {
return fmt.Errorf(
"healthcheck endpoint returned status code %d: %w",
resp.StatusCode,
ErrFailedHealthCheck,
)
}
return nil
}