Skip to content

Commit

Permalink
command to check dataplane api (#63)
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Siwiec <[email protected]>
  • Loading branch information
rizzza authored Sep 5, 2023
1 parent 057a63c commit 9a38420
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 22 deletions.
59 changes: 59 additions & 0 deletions cmd/check_dataplane.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"context"
"time"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.infratographer.com/x/viperx"

"go.infratographer.com/loadbalancer-manager-haproxy/internal/dataplaneapi"
)

// checkDataplaneCmd checks the connection to the dataplaneapi
var checkDataplaneCmd = &cobra.Command{
Use: "check_dataplane",
Short: "checks the connection to the dataplaneapi",
RunE: func(cmd *cobra.Command, args []string) error {
return checkDataPlane(cmd.Context(), viper.GetViper())
},
}

const (
defaultRetryLimit = 3
defaultRetryInterval = 1 * time.Second
)

func init() {
rootCmd.AddCommand(checkDataplaneCmd)

checkDataplaneCmd.PersistentFlags().String("dataplane-user-name", "haproxy", "DataplaneAPI user name")
viperx.MustBindFlag(viper.GetViper(), "dataplane.user.name", checkDataplaneCmd.PersistentFlags().Lookup("dataplane-user-name"))

checkDataplaneCmd.PersistentFlags().String("dataplane-user-pwd", "adminpwd", "DataplaneAPI user password")
viperx.MustBindFlag(viper.GetViper(), "dataplane.user.pwd", checkDataplaneCmd.PersistentFlags().Lookup("dataplane-user-pwd"))

checkDataplaneCmd.PersistentFlags().String("dataplane-url", "http://127.0.0.1:5555/v2/", "DataplaneAPI base url")
viperx.MustBindFlag(viper.GetViper(), "dataplane.url", checkDataplaneCmd.PersistentFlags().Lookup("dataplane-url"))

checkDataplaneCmd.PersistentFlags().Int("retries", defaultRetryLimit, "Number of attempts to verify connection to DataplaneAPI")
viperx.MustBindFlag(viper.GetViper(), "retries", checkDataplaneCmd.PersistentFlags().Lookup("retries"))

checkDataplaneCmd.PersistentFlags().Duration("retry-interval", defaultRetryInterval, "Interval between checks")
viperx.MustBindFlag(viper.GetViper(), "retry-interval", checkDataplaneCmd.PersistentFlags().Lookup("retry-interval"))
}

func checkDataPlane(ctx context.Context, viper *viper.Viper) error {
client := dataplaneapi.NewClient(viper.GetString("dataplane.url"))

if err := client.WaitForDataPlaneReady(
ctx,
viper.GetInt("retries"),
viper.GetDuration("retry-interval"),
); err != nil {
logger.Fatalw("dataplane api is not ready", "error", err)
}

return nil
}
2 changes: 1 addition & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func run(cmdCtx context.Context, v *viper.Viper) error {
mgr := &manager.Manager{
Context: ctx,
Logger: logger,
DataPlaneClient: dataplaneapi.NewClient(viper.GetString("dataplane.url")),
DataPlaneClient: dataplaneapi.NewClient(viper.GetString("dataplane.url"), dataplaneapi.WithLogger(logger)),
LBClient: lbapi.NewClient(viper.GetString("loadbalancerapi.url")),
ManagedLBID: managedLBID,
BaseCfgPath: viper.GetString("haproxy.config.base"),
Expand Down
38 changes: 36 additions & 2 deletions internal/dataplaneapi/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/spf13/viper"
"go.uber.org/zap"
)

var dataPlaneClientTimeout = 2 * time.Second
Expand All @@ -15,15 +16,33 @@ var dataPlaneClientTimeout = 2 * time.Second
type Client struct {
client *http.Client
baseURL string
logger *zap.SugaredLogger
}

// Option configures a connection option.
type Option func(c *Client)

// NewClient returns an http client for Data Plane API
func NewClient(url string) *Client {
return &Client{
func NewClient(url string, options ...Option) *Client {
c := &Client{
client: &http.Client{
Timeout: dataPlaneClientTimeout,
},
baseURL: url,
logger: zap.NewNop().Sugar(),
}

for _, opt := range options {
opt(c)
}

return c
}

// WithLogger sets the logger for the client
func WithLogger(logger *zap.SugaredLogger) Option {
return func(c *Client) {
c.logger = logger
}
}

Expand Down Expand Up @@ -102,3 +121,18 @@ func (c *Client) PostConfig(ctx context.Context, config string) error {
return ErrDataPlaneHTTPError
}
}

// WaitForDataPlaneReady waits for the DataPlane API to be ready
func (c Client) WaitForDataPlaneReady(ctx context.Context, retries int, sleep time.Duration) error {
for i := 0; i < retries; i++ {
if c.APIIsReady(ctx) {
c.logger.Info("dataplaneapi is ready")
return nil
}

c.logger.Info("waiting for dataplaneapi to become ready")
time.Sleep(sleep)
}

return ErrDataPlaneNotReady
}
18 changes: 2 additions & 16 deletions internal/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/haproxytech/config-parser/v4/options"
"github.com/haproxytech/config-parser/v4/types"

"go.infratographer.com/loadbalancer-manager-haproxy/internal/dataplaneapi"
"go.infratographer.com/loadbalancer-manager-haproxy/pkg/lbapi"

"go.infratographer.com/x/events"
Expand All @@ -30,6 +29,7 @@ type dataPlaneAPI interface {
PostConfig(ctx context.Context, config string) error
CheckConfig(ctx context.Context, config string) error
APIIsReady(ctx context.Context) bool
WaitForDataPlaneReady(ctx context.Context, retries int, sleep time.Duration) error
}

type eventSubscriber interface {
Expand Down Expand Up @@ -68,7 +68,7 @@ func (m *Manager) Run() error {
}

// wait until the Data Plane API is running
if err := m.waitForDataPlaneReady(dataPlaneAPIRetryLimit, dataPlaneAPIRetrySleep); err != nil {
if err := m.DataPlaneClient.WaitForDataPlaneReady(m.Context, dataPlaneAPIRetryLimit, dataPlaneAPIRetrySleep); err != nil {
m.Logger.Fatal("unable to reach dataplaneapi. is it running?")
}

Expand Down Expand Up @@ -187,20 +187,6 @@ func (m *Manager) updateConfigToLatest() error {
return nil
}

func (m Manager) waitForDataPlaneReady(retries int, sleep time.Duration) error {
for i := 0; i < retries; i++ {
if m.DataPlaneClient.APIIsReady(m.Context) {
m.Logger.Info("dataplaneapi is ready")
return nil
}

m.Logger.Info("waiting for dataplaneapi to become ready")
time.Sleep(sleep)
}

return dataplaneapi.ErrDataPlaneNotReady
}

// mergeConfig takes the response from lb api, merges with the base haproxy config and returns it
func mergeConfig(cfg parser.Parser, lb *lbapi.GetLoadBalancer) (parser.Parser, error) {
for _, p := range lb.LoadBalancer.Ports.Edges {
Expand Down
12 changes: 9 additions & 3 deletions internal/manager/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package mock

import (
"context"
"time"

"go.infratographer.com/loadbalancer-manager-haproxy/pkg/lbapi"
)
Expand All @@ -17,9 +18,10 @@ func (c LBAPIClient) GetLoadBalancer(ctx context.Context, id string) (*lbapi.Get

// DataplaneAPIClient mock client
type DataplaneAPIClient struct {
DoPostConfig func(ctx context.Context, config string) error
DoCheckConfig func(ctx context.Context, config string) error
DoAPIIsReady func(ctx context.Context) bool
DoPostConfig func(ctx context.Context, config string) error
DoCheckConfig func(ctx context.Context, config string) error
DoAPIIsReady func(ctx context.Context) bool
DoWaitForDataPlaneReady func(ctx context.Context, retries int, sleep time.Duration) error
}

func (c *DataplaneAPIClient) PostConfig(ctx context.Context, config string) error {
Expand All @@ -34,6 +36,10 @@ func (c DataplaneAPIClient) CheckConfig(ctx context.Context, config string) erro
return c.DoCheckConfig(ctx, config)
}

func (c DataplaneAPIClient) WaitForDataPlaneReady(ctx context.Context, retries int, sleep time.Duration) error {
return c.DoWaitForDataPlaneReady(ctx, retries, sleep)
}

// Subscriber mock client
type Subscriber struct {
DoClose func() error
Expand Down

0 comments on commit 9a38420

Please sign in to comment.