Skip to content

Commit

Permalink
Merge pull request #426 from nkryuchkov/feature/health-check
Browse files Browse the repository at this point in the history
Health checks for services

Former-commit-id: 78b18d1
  • Loading branch information
nkryuchkov authored Jul 2, 2020
2 parents 491292f + b0a2842 commit 3d7621c
Show file tree
Hide file tree
Showing 54 changed files with 540 additions and 293 deletions.
2 changes: 1 addition & 1 deletion cmd/hypervisor/statik/statik.go

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions internal/utclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/SkycoinProject/skywire-mainnet/internal/httpauth"
)

//go:generate mockery -name APIClient -case underscore -inpkg

var log = logging.MustGetLogger("utclient")

// Error is the object returned to the client when there's an error.
Expand All @@ -27,6 +29,7 @@ type Error struct {
// APIClient implements uptime tracker API client.
type APIClient interface {
UpdateVisorUptime(context.Context) error
Health(ctx context.Context) (int, error)
}

// httpClient implements Client for uptime tracker API.
Expand Down Expand Up @@ -81,6 +84,23 @@ func (c *httpClient) UpdateVisorUptime(ctx context.Context) error {
return nil
}

// UpdateVisorUptime updates visor uptime.
func (c *httpClient) Health(ctx context.Context) (int, error) {
resp, err := c.Get(ctx, "/health")
if err != nil {
return 0, err
}

defer func() {
if err := resp.Body.Close(); err != nil {
log.WithError(err).Warn("Failed to close response body")
}
}()

return resp.StatusCode, nil

}

// extractError returns the decoded error message from Body.
func extractError(r io.Reader) error {
var apiError Error
Expand Down
49 changes: 49 additions & 0 deletions internal/utclient/mock_api_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 11 additions & 30 deletions internal/vpn/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func NewClient(cfg ClientConfig, l logrus.FieldLogger, conn net.Conn) (*Client,
return nil, fmt.Errorf("error getting TP IP: %w", err)
}

arIP, err := addressResolverIPFromEnv()
if err != nil {
return nil, fmt.Errorf("error getting TP IP: %w", err)
}

rfIP, err := rfIPFromEnv()
if err != nil {
return nil, fmt.Errorf("error getting RF IP: %w", err)
Expand All @@ -58,34 +63,14 @@ func NewClient(cfg ClientConfig, l logrus.FieldLogger, conn net.Conn) (*Client,
return nil, fmt.Errorf("error getting STCP entities: %w", err)
}

var stcprARip net.IP
if _, ok := os.LookupEnv(STCPRAddressResolverAddrEnvKey); ok {
stcprARip, err = stcprAddressResolverIPFromEnv()
if err != nil {
return nil, fmt.Errorf("error getting stcpr AR IP: %w", err)
}
}

var sudphARip net.IP
if _, ok := os.LookupEnv(SUDPHAddressResolverAddrEnvKey); ok {
sudphARip, err = sudphAddressResolverIPFromEnv()
if err != nil {
return nil, fmt.Errorf("error getting sudph AR IP: %w", err)
}
}

requiredDirectIPs := []net.IP{dmsgDiscIP, tpDiscIP, rfIP}
directIPs := make([]net.IP, 0, len(requiredDirectIPs)+len(dmsgSrvAddrs)+len(stcpEntities))
directIPs = append(directIPs, requiredDirectIPs...)
directIPs = append(directIPs, dmsgSrvAddrs...)
directIPs = append(directIPs, stcpEntities...)

if stcprARip != nil {
directIPs = append(directIPs, stcprARip)
}

if sudphARip != nil {
directIPs = append(directIPs, sudphARip)
if arIP != nil {
directIPs = append(directIPs, arIP)
}

defaultGateway, err := DefaultNetworkGateway()
Expand Down Expand Up @@ -281,6 +266,10 @@ func tpDiscIPFromEnv() (net.IP, error) {
return ipFromEnv(TPDiscAddrEnvKey)
}

func addressResolverIPFromEnv() (net.IP, error) {
return ipFromEnv(AddressResolverAddrEnvKey)
}

func rfIPFromEnv() (net.IP, error) {
return ipFromEnv(RFAddrEnvKey)
}
Expand Down Expand Up @@ -313,14 +302,6 @@ func stcpEntitiesFromEnv() ([]net.IP, error) {
return stcpEntities, nil
}

func stcprAddressResolverIPFromEnv() (net.IP, error) {
return ipFromEnv(STCPRAddressResolverAddrEnvKey)
}

func sudphAddressResolverIPFromEnv() (net.IP, error) {
return ipFromEnv(SUDPHAddressResolverAddrEnvKey)
}

func (c *Client) shakeHands() (TUNIP, TUNGateway net.IP, encrypt bool, err error) {
unavailableIPs, err := LocalNetworkInterfaceIPs()
if err != nil {
Expand Down
33 changes: 13 additions & 20 deletions internal/vpn/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ const (
DmsgDiscAddrEnvKey = "ADDR_DMSG_DISC"
// TPDiscAddrEnvKey is env arg holding TP discovery address.
TPDiscAddrEnvKey = "ADDR_TP_DISC"
// AddressResolverAddrEnvKey is env arg holding address resolver address.
AddressResolverAddrEnvKey = "ADDR_ADDRESS_RESOLVER"
// RFAddrEnvKey is env arg holding RF address.
RFAddrEnvKey = "ADDR_RF"
// UptimeTrackerAddrEnvKey is env arg holding uptime tracker address.
UptimeTrackerAddrEnvKey = "ADDR_UPTIME_TRACKER"
// STCPRAddressResolverAddrEnvKey is env arg holding stcpr address resolver address.
STCPRAddressResolverAddrEnvKey = "ADDR_STCPR_ADDRESS_RESOLVER"
// SUDPHAddressResolverAddrEnvKey is env arg holding sudph address resolver address.
SUDPHAddressResolverAddrEnvKey = "ADDR_SUDPH_ADDRESS_RESOLVER"

// STCPTableLenEnvKey is env arg holding Stcp table length.
STCPTableLenEnvKey = "STCP_TABLE_LEN"
Expand All @@ -41,14 +39,13 @@ const (
// DirectRoutesEnvConfig contains all the addresses which need to be communicated directly,
// not through the VPN service.
type DirectRoutesEnvConfig struct {
DmsgDiscovery string
DmsgServers []string
TPDiscovery string
RF string
UptimeTracker string
STCPRAddressResolver string
SUDPHAddressResolver string
STCPTable map[cipher.PubKey]string
DmsgDiscovery string
DmsgServers []string
TPDiscovery string
RF string
UptimeTracker string
AddressResolver string
STCPTable map[cipher.PubKey]string
}

// AppEnvArgs forms env args to pass to the app process.
Expand All @@ -63,6 +60,10 @@ func AppEnvArgs(config DirectRoutesEnvConfig) map[string]string {
envs[TPDiscAddrEnvKey] = config.TPDiscovery
}

if config.AddressResolver != "" {
envs[AddressResolverAddrEnvKey] = config.AddressResolver
}

if config.RF != "" {
envs[RFAddrEnvKey] = config.RF
}
Expand All @@ -71,14 +72,6 @@ func AppEnvArgs(config DirectRoutesEnvConfig) map[string]string {
envs[UptimeTrackerAddrEnvKey] = config.UptimeTracker
}

if config.STCPRAddressResolver != "" {
envs[STCPRAddressResolverAddrEnvKey] = config.STCPRAddressResolver
}

if config.SUDPHAddressResolver != "" {
envs[SUDPHAddressResolverAddrEnvKey] = config.SUDPHAddressResolver
}

if len(config.STCPTable) != 0 {
envs[STCPTableLenEnvKey] = strconv.FormatInt(int64(len(config.STCPTable)), 10)

Expand Down
23 changes: 23 additions & 0 deletions pkg/routefinder/rfclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type HTTPError struct {
// Client implements route finding operations.
type Client interface {
FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][][]routing.Hop, error)
Health(ctx context.Context) (int, error)
}

// APIClient implements Client interface
Expand Down Expand Up @@ -85,9 +86,12 @@ func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opt
if err != nil {
return nil, err
}

req.Header.Set("Content-Type", "application/json")

ctx, cancel := context.WithTimeout(ctx, c.apiTimeout)
defer cancel()

req = req.WithContext(ctx)

res, err := c.client.Do(req)
Expand All @@ -98,6 +102,7 @@ func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opt
}
}()
}

if err != nil {
return nil, err
}
Expand All @@ -122,6 +127,24 @@ func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opt
return paths, nil
}

// Health checks route finder health.
func (c *apiClient) Health(_ context.Context) (int, error) {
res, err := http.Get(c.addr + "/health")
if err != nil {
return 0, err
}

if res != nil {
defer func() {
if err := res.Body.Close(); err != nil {
log.WithError(err).Warn("Failed to close HTTP response body")
}
}()
}

return res.StatusCode, nil
}

func sanitizedAddr(addr string) string {
if addr == "" {
return "http://localhost"
Expand Down
6 changes: 6 additions & 0 deletions pkg/routefinder/rfclient/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package rfclient

import (
"fmt"
"net/http"

"github.com/SkycoinProject/dmsg/cipher"
"golang.org/x/net/context"
Expand Down Expand Up @@ -48,3 +49,8 @@ func (r *mockClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, op
},
}, nil
}

// Health implements Client for MockClient
func (r *mockClient) Health(_ context.Context) (int, error) {
return http.StatusOK, nil
}
19 changes: 19 additions & 0 deletions pkg/router/mock_router.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions pkg/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ type router struct {
trustedVisors map[cipher.PubKey]struct{}
tm *transport.Manager
rt routing.Table
rfc rfclient.Client // route finder client
rgs map[routing.RouteDescriptor]*RouteGroup // route groups to push incoming reads from transports.
rpcSrv *rpc.Server
accept chan routing.EdgeRules
Expand Down Expand Up @@ -167,7 +166,6 @@ func New(n *snet.Network, config *Config) (Router, error) {
tm: config.TransportManager,
rt: routing.NewTable(),
sl: sl,
rfc: config.RouteFinder,
rgs: make(map[routing.RouteDescriptor]*RouteGroup),
rpcSrv: rpc.NewServer(),
accept: make(chan routing.EdgeRules, acceptSize),
Expand Down
Loading

0 comments on commit 3d7621c

Please sign in to comment.