Skip to content

Commit 054de34

Browse files
committed
Add healthcheck subcommand; close #60
1 parent 06cc7c7 commit 054de34

File tree

3 files changed

+103
-3
lines changed

3 files changed

+103
-3
lines changed

internal/ctrl/rules-registry.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import (
88
"fmt"
99
"net/http"
1010

11+
"github.com/nextmn/srv6/internal/database"
12+
1113
"github.com/gin-gonic/gin"
1214
"github.com/gofrs/uuid"
1315
"github.com/nextmn/json-api/jsonapi"
14-
"github.com/nextmn/srv6/internal/database"
1516
"github.com/sirupsen/logrus"
1617
)
1718

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2024 Louis Royer and the NextMN-SRv6 contributors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style license that can be
3+
// found in the LICENSE file.
4+
// SPDX-License-Identifier: MIT
5+
package healthcheck
6+
7+
import (
8+
"context"
9+
"encoding/json"
10+
"fmt"
11+
"net/http"
12+
"time"
13+
14+
"github.com/sirupsen/logrus"
15+
16+
"github.com/nextmn/srv6/internal/config"
17+
)
18+
19+
type Healthcheck struct {
20+
uri string
21+
}
22+
23+
// TODO: move this in json-api
24+
type Status struct {
25+
Ready bool `json:"ready"`
26+
}
27+
28+
func NewHealthcheck(conf *config.SRv6Config) *Healthcheck {
29+
httpPort := "80" // default http port
30+
if conf.HTTPPort != nil {
31+
httpPort = *conf.HTTPPort
32+
}
33+
httpURI := "http://"
34+
if conf.HTTPAddress.Is6() {
35+
httpURI = httpURI + "[" + conf.HTTPAddress.String() + "]:" + httpPort
36+
} else {
37+
httpURI = httpURI + conf.HTTPAddress.String() + ":" + httpPort
38+
}
39+
return &Healthcheck{
40+
uri: httpURI,
41+
}
42+
}
43+
func (h *Healthcheck) Run(ctx context.Context) error {
44+
client := http.Client{
45+
Timeout: 100 * time.Millisecond,
46+
}
47+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, h.uri+"/status", nil)
48+
if err != nil {
49+
logrus.WithError(err).Error("Error while creating http get request")
50+
return err
51+
}
52+
req.Header.Add("User-Agent", "go-github-nextmn-srv6")
53+
req.Header.Set("Accept", "application/json")
54+
req.Header.Set("Accept-Charset", "utf-8")
55+
resp, err := client.Do(req)
56+
if err != nil {
57+
logrus.WithFields(logrus.Fields{"remote-server": h.uri}).WithError(err).Info("No http response")
58+
return err
59+
}
60+
defer resp.Body.Close()
61+
if resp.StatusCode != 200 {
62+
logrus.WithFields(logrus.Fields{"remote-server": h.uri}).WithError(err).Info("Http response is not 200 OK")
63+
return err
64+
}
65+
decoder := json.NewDecoder(resp.Body)
66+
var status Status
67+
if err := decoder.Decode(&status); err != nil {
68+
logrus.WithFields(logrus.Fields{"remote-server": h.uri}).WithError(err).Info("Could not decode json response")
69+
return err
70+
}
71+
if !status.Ready {
72+
err := fmt.Errorf("Server is not ready")
73+
logrus.WithFields(logrus.Fields{"remote-server": h.uri}).WithError(err).Info("Server is not ready")
74+
return err
75+
}
76+
return nil
77+
}

main.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/nextmn/srv6/internal/app"
1616
"github.com/nextmn/srv6/internal/config"
17+
"github.com/nextmn/srv6/internal/healthcheck"
1718

1819
"github.com/adrg/xdg"
1920
"github.com/sirupsen/logrus"
@@ -41,7 +42,7 @@ func main() {
4142
EnvVars: []string{"CONFIG_FILE"},
4243
},
4344
},
44-
Action: func(ctx *cli.Context) error {
45+
Before: func(ctx *cli.Context) error {
4546
if ctx.Path("config") == "" {
4647
if xdgPath, err := xdg.SearchConfigFile("nextmn-srv6/config.yaml"); err != nil {
4748
cli.ShowAppHelp(ctx)
@@ -50,19 +51,40 @@ func main() {
5051
ctx.Set("config", xdgPath)
5152
}
5253
}
54+
return nil
55+
},
56+
Action: func(ctx *cli.Context) error {
5357
conf, err := config.ParseConf(ctx.Path("config"))
5458
if err != nil {
5559
logrus.WithContext(ctx.Context).WithError(err).Fatal("Error loading config, exiting…")
5660
}
5761
if conf.Logger != nil {
5862
logrus.SetLevel(conf.Logger.Level)
5963
}
60-
6164
if err := app.NewSetup(conf).Run(ctx.Context); err != nil {
6265
logrus.WithError(err).Fatal("Error while running, exiting…")
6366
}
6467
return nil
6568
},
69+
Commands: []*cli.Command{
70+
{
71+
Name: "healthcheck",
72+
Usage: "check status of the node",
73+
Action: func(ctx *cli.Context) error {
74+
conf, err := config.ParseConf(ctx.Path("config"))
75+
if err != nil {
76+
logrus.WithContext(ctx.Context).WithError(err).Fatal("Error loading config, exiting…")
77+
}
78+
if conf.Logger != nil {
79+
logrus.SetLevel(conf.Logger.Level)
80+
}
81+
if err := healthcheck.NewHealthcheck(conf).Run(ctx.Context); err != nil {
82+
os.Exit(1)
83+
}
84+
return nil
85+
},
86+
},
87+
},
6688
}
6789
if err := app.RunContext(ctx, os.Args); err != nil {
6890
logrus.Fatal(err)

0 commit comments

Comments
 (0)