Skip to content

Commit 200d6bc

Browse files
committed
Proper parrot healthchecks
1 parent 7c476d8 commit 200d6bc

File tree

3 files changed

+57
-28
lines changed

3 files changed

+57
-28
lines changed

parrot/.changeset/v0.5.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Properly configures parrot's health check

parrot/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ COPY parrot /parrot
44
ENV PARROT_PORT=80
55
ENV PARROT_TRACE=true
66
EXPOSE 80
7+
8+
HEALTHCHECK --timeout=3s --start-interval=10ms --start-period=5s CMD [ "/parrot", "health" ]
9+
710
ENTRYPOINT [ "/parrot" ]

parrot/cmd/main.go

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package main
22

33
import (
44
"context"
5+
"fmt"
6+
"net/http"
57
"os"
68
"os/signal"
79
"strconv"
@@ -25,34 +27,36 @@ func main() {
2527
recorders []string
2628
)
2729

28-
rootCmd := &cobra.Command{
29-
Use: "parrot",
30-
Short: "A server that can register and parrot back dynamic requests",
31-
PreRun: func(cmd *cobra.Command, args []string) {
32-
// Check environment variables if flags are not set
33-
if !cmd.Flags().Changed("port") {
34-
if envPort, err := strconv.Atoi(os.Getenv("PARROT_PORT")); err == nil {
35-
port = envPort
36-
}
37-
}
38-
if !cmd.Flags().Changed("debug") {
39-
debug = os.Getenv("PARROT_DEBUG") == "true"
40-
}
41-
if !cmd.Flags().Changed("trace") {
42-
trace = os.Getenv("PARROT_TRACE") == "true"
43-
}
44-
if !cmd.Flags().Changed("silent") {
45-
silent = os.Getenv("PARROT_SILENT") == "true"
30+
preRun := func(cmd *cobra.Command, args []string) {
31+
// Check environment variables if flags are not set
32+
if !cmd.Flags().Changed("port") {
33+
if envPort, err := strconv.Atoi(os.Getenv("PARROT_PORT")); err == nil {
34+
port = envPort
4635
}
47-
if !cmd.Flags().Changed("json") {
48-
json = os.Getenv("PARROT_JSON") == "true"
36+
}
37+
if !cmd.Flags().Changed("debug") {
38+
debug = os.Getenv("PARROT_DEBUG") == "true"
39+
}
40+
if !cmd.Flags().Changed("trace") {
41+
trace = os.Getenv("PARROT_TRACE") == "true"
42+
}
43+
if !cmd.Flags().Changed("silent") {
44+
silent = os.Getenv("PARROT_SILENT") == "true"
45+
}
46+
if !cmd.Flags().Changed("json") {
47+
json = os.Getenv("PARROT_JSON") == "true"
48+
}
49+
if !cmd.Flags().Changed("recorders") {
50+
if envRecorders := os.Getenv("PARROT_RECORDERS"); envRecorders != "" {
51+
recorders = strings.Split(envRecorders, ",")
4952
}
50-
if !cmd.Flags().Changed("recorders") {
51-
if envRecorders := os.Getenv("PARROT_RECORDERS"); envRecorders != "" {
52-
recorders = strings.Split(envRecorders, ",")
53-
}
54-
}
55-
},
53+
}
54+
}
55+
56+
rootCmd := &cobra.Command{
57+
Use: "parrot",
58+
Short: "A server that can register and parrot back dynamic requests",
59+
PreRun: preRun,
5660
RunE: func(cmd *cobra.Command, args []string) error {
5761
options := []parrot.ServerOption{parrot.WithPort(port)}
5862
logLevel := zerolog.InfoLevel
@@ -90,15 +94,36 @@ func main() {
9094
},
9195
}
9296

93-
rootCmd.Flags().IntVarP(&port, "port", "p", 0, "Port to run the parrot on (env: PARROT_PORT)")
97+
rootCmd.PersistentFlags().IntVarP(&port, "port", "p", 0, "Port to run the parrot on (env: PARROT_PORT)")
9498
rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "Enable debug output (env: PARROT_DEBUG)")
9599
rootCmd.Flags().BoolVarP(&trace, "trace", "t", false, "Enable trace and debug output (env: PARROT_TRACE)")
96100
rootCmd.Flags().BoolVarP(&silent, "silent", "s", false, "Disable all output (env: PARROT_SILENT)")
97101
rootCmd.Flags().BoolVarP(&json, "json", "j", false, "Output logs in JSON format (env: PARROT_JSON)")
98102
rootCmd.Flags().StringSliceVarP(&recorders, "recorders", "r", nil, "Existing recorders to use (env: PARROT_RECORDERS)")
99103

104+
healthCheckCmd := &cobra.Command{
105+
Use: "health",
106+
Short: "Check if the parrot server is healthy",
107+
PreRun: preRun,
108+
Run: func(cmd *cobra.Command, args []string) {
109+
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/health", port))
110+
if err != nil {
111+
fmt.Println(err)
112+
os.Exit(1)
113+
}
114+
if resp.StatusCode != 200 {
115+
fmt.Printf("Health check failed with status code %d\n", resp.StatusCode)
116+
os.Exit(1)
117+
}
118+
fmt.Println("Parrot is healthy!")
119+
},
120+
SilenceUsage: true,
121+
}
122+
123+
rootCmd.AddCommand(healthCheckCmd)
124+
100125
if err := rootCmd.Execute(); err != nil {
101-
log.Error().Err(err).Msg("error executing command")
126+
fmt.Printf("Error running parrot:\n%s\n", err)
102127
os.Exit(1)
103128
}
104129
}

0 commit comments

Comments
 (0)