Skip to content

Commit

Permalink
refactoring: context, types, etc
Browse files Browse the repository at this point in the history
  • Loading branch information
sio4 committed Apr 28, 2022
1 parent 606cfde commit 92d3b3e
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 75 deletions.
6 changes: 0 additions & 6 deletions checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@ package checks

import (
"reflect"
"time"

"github.com/hyeoncheon/bogo/internal/common"
)

const (
checkSleep = 100 * time.Millisecond
)

// Checker couples the name and the runner of each checker.
type Checker struct {
name string
Expand All @@ -37,7 +32,6 @@ func StartAll(c common.Context, opts *common.Options, ch chan interface{}) int {
n := 0

for _, x := range common.Plugins(reflect.TypeOf(&Checker{})) {
x, _ := x.(common.Plugin)
if len(opts.Checkers) > 0 && !common.Contains(opts.Checkers, x.Name()) {
logger.Debugf("%v is not on the checker list. skipping...", x.Name())
continue //nolint
Expand Down
1 change: 0 additions & 1 deletion checks/heartbeat.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func heartbeatRunner(c common.Context, opts common.PluginOptions, out chan inter
break infinite
case <-ticker.C:
out <- "heartbeat"
case <-time.After(checkSleep):
}
}
logger.Infof("%s checker exited", heartbeatChecker)
Expand Down
2 changes: 1 addition & 1 deletion checks/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ func pingRunner(c common.Context, opts common.PluginOptions, out chan interface{
m, err := doPing(host, pingInterval)
if err != nil {
logger.Error(err)
// TODO: sending error message?

break infinite
}
out <- m
case <-time.After(checkSleep):
}
}
logger.Infof("%s checker for %s exited", pingChecker, host)
Expand Down
19 changes: 19 additions & 0 deletions checks/ping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package checks

import (
"testing"
"time"

"github.com/hyeoncheon/bogo"
"github.com/hyeoncheon/bogo/internal/common"
Expand Down Expand Up @@ -90,6 +91,24 @@ func TestPingRunner_EmptyTarget(t *testing.T) {
r.ErrorContains(err, "target string should not be empty")
}

func TestPingRunner_WrongTarget(t *testing.T) {
r := require.New(t)

opts := common.DefaultOptions()
c, _ := common.NewDefaultContext(&opts)

o := common.PluginOptions{
"targets": []string{"badaddress"},
"ping_interval": []string{"100"},
"check_interval": []string{"1"},
}

r.NoError(pingRunner(c, o, c.Channel()))
time.Sleep(1100 * time.Millisecond)

c.Cancel()
}

func TestPingRunner_InvalidOptionValueCheckInterval(t *testing.T) {
r := require.New(t)

Expand Down
4 changes: 3 additions & 1 deletion cmd/bogo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/hyeoncheon/bogo/checks"
"github.com/hyeoncheon/bogo/exporters"
"github.com/hyeoncheon/bogo/internal/common"
"github.com/hyeoncheon/bogo/internal/defaults"
"github.com/hyeoncheon/bogo/meari"

getopt "github.com/pborman/getopt/v2"
Expand Down Expand Up @@ -105,7 +106,8 @@ func run(c common.Context, opts *common.Options) {

logger.Info("shutting down webserver...")

ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
ctx, cancel := context.WithTimeout(context.Background(),
defaults.ShutdownTimeoutSec*time.Second)
defer cancel()

if err := server.Shutdown(ctx); err != nil {
Expand Down
1 change: 0 additions & 1 deletion exporters/exporters.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func StartAll(c common.Context, opts *common.Options, ch chan interface{}) int {
n := 0

for _, x := range common.Plugins(reflect.TypeOf(&Exporter{})) {
x, _ := x.(common.Plugin)
if len(opts.Exporters) > 0 && !common.Contains(opts.Exporters, x.Name()) {
logger.Debugf("%v is not on the exporter list. skipping...", x.Name())
continue //nolint
Expand Down
2 changes: 1 addition & 1 deletion internal/common/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (m *GCEClient) WhereAmI() string {
return GOOGLE
}

return NOWHERE
return UNKNOWN
}

// gceMetaInstanceName is a function pointer to metadata.InstanceName().
Expand Down
2 changes: 1 addition & 1 deletion internal/common/gcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func TestNewGCEMetaClient_NoGCE(t *testing.T) {
// actually this could be separated test but just keep it here
m = &GCEClient{Client: nil, logger: nil}
res := m.WhereAmI()
r.Equal(NOWHERE, res)
r.Equal(UNKNOWN, res)
}

func TestGCEClient_InstanceName(t *testing.T) {
Expand Down
10 changes: 5 additions & 5 deletions internal/common/meta.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package common

const (
// NOWHERE is a kind of "I don't care" from the perspective of a specific
// driver. For example, GCE meta client can answer with NOWHERE if they
// UNKNOWN is a kind of "I don't know" from the perspective of a specific
// driver. For example, GCE meta client can answer with UNKNOWN if they
// could not detect as they are on GCE.
NOWHERE = "Nowhere"
// UNKNOWN has different meaning. For example, if this keyword is used,
// it should indicate that the environment is explicitly not supported.
UNKNOWN = "Unknown"
// NOWHERE has different meaning. For example, if this keyword is used,
// it should indicate that the environment is explicitly not supported.
NOWHERE = "Nowhere"
)

// MetaClient is an interface to be implemented for each cloud provider.
Expand Down
8 changes: 5 additions & 3 deletions internal/common/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ type Plugin interface {
// Plugins returns the plugin list for the given type. All register function
// of the type which is prefixed with "Register" will executed during the
// registration.
func Plugins(t reflect.Type) []interface{} {
plugins := [](interface{}){}
func Plugins(t reflect.Type) []Plugin {
plugins := [](Plugin){}

for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
Expand All @@ -43,7 +43,9 @@ func Plugins(t reflect.Type) []interface{} {
y := m.Func.Call([]reflect.Value{reflect.ValueOf(x)})[0].Interface()
// fmt.Println("plugin found:", reflect.TypeOf(y), y)

plugins = append(plugins, y)
if plugin, ok := y.(Plugin); ok {
plugins = append(plugins, plugin)
}
}

return plugins
Expand Down
7 changes: 2 additions & 5 deletions internal/common/plugins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ func TestPlugins(t *testing.T) {
r := require.New(t)

plugins := Plugins(reflect.TypeOf(&Plugger{}))
r.IsType([]interface{}{}, plugins)
r.NotEmpty(plugins)
r.Equal(2, len(plugins))

e1 := plugins[0].(Plugin)
r.IsType(&Plugger{}, e1)
e1 := plugins[0]
r.Equal("dummy", e1.Name())
r.Nil(e1.Run(nil, nil, nil))

e2 := plugins[1].(Plugin)
r.IsType(&Plugger{}, e2)
e2 := plugins[1]
r.Equal("mummy", e2.Name())
r.Error(e2.Run(nil, nil, nil))
}
Expand Down
8 changes: 6 additions & 2 deletions internal/defaults/defaults.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Package defaults provides the default values.
package defaults

// ServerAddress is the default listen address for the webserver.
const ServerAddress = "127.0.0.1:6090"
const (
// ServerAddress is the default listen address for the webserver.
ServerAddress = "127.0.0.1:6090"
// ShutdownTimeoutSec is the timeout for webserver shutdown in seconds.
ShutdownTimeoutSec = 30
)
45 changes: 21 additions & 24 deletions meari/default_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,55 @@ import (
"github.com/labstack/echo/v4/middleware"
)

// defaultServer is a "echo" based simple webserver that implements the
// DefaultServer is a "echo" based simple webserver that implements the
// Server interface.
type defaultServer struct {
type DefaultServer struct {
*echo.Echo
address string
}

var _ Server = &defaultServer{}
var _ Server = &DefaultServer{}

// NewDefaultServer initializes an instance of defaultServer, registers
// the "root" handler, and returns it as a Server. Currently, Server works as
// a singleton.
func NewDefaultServer(opts *Options) Server {
serverOnce.Do(func() {
s := &defaultServer{
Echo: echo.New(),
address: defaults.ServerAddress,
}
s.Echo.HideBanner = true
s.Echo.Debug = true
func NewDefaultServer(opts *Options) *DefaultServer {
s := &DefaultServer{
Echo: echo.New(),
address: defaults.ServerAddress,
}
s.Echo.HideBanner = true
s.Echo.Debug = true

if opts.Address != "" {
s.address = opts.Address
}
if opts.Address != "" {
s.address = opts.Address
}

s.Echo.Use(middleware.Logger())
s.Echo.Use(middleware.Logger())

s.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hey, Bulldog!")
})
server = s
s.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hey, Bulldog!")
})

return server
return s
}

// Address implements the Server interface.
func (s *defaultServer) Address() string {
func (s *DefaultServer) Address() string {
return s.address
}

// Serve implements the Server interface.
func (s *defaultServer) Serve() error {
func (s *DefaultServer) Serve() error {
return s.Echo.Start(s.address)
}

// Shutdown implements the Server interface.
func (s *defaultServer) Shutdown(c context.Context) error {
func (s *DefaultServer) Shutdown(c context.Context) error {
return s.Echo.Shutdown(c)
}

// GET implements the Server interface.
func (s *defaultServer) GET(path string, handler echo.HandlerFunc) {
func (s *DefaultServer) GET(path string, handler echo.HandlerFunc) {
s.Echo.GET(path, handler)
}
16 changes: 2 additions & 14 deletions meari/default_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,28 @@ package meari

import (
"net/http"
"sync"
"testing"
"time"

"github.com/hyeoncheon/bogo/internal/defaults"

"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)

// TestNewDefaultServer tests the generator and if the singleton works fine.
// TestNewDefaultServer tests the NewDefaultServer function.
func TestNewDefaultServer(t *testing.T) {
r := require.New(t)

s1 := NewDefaultServer(&Options{})
r.NotNil(s1)

s := NewDefaultServer(&Options{})
r.NotNil(s)
r.Equal(s1, s) // singleton by Once
r.Equal(defaults.ServerAddress, s.Address())

r.Nil(nil)
}

// TestNewDefaultServer_Address tests if Options.Address is working.
func TestNewDefaultServer_Address(t *testing.T) {
r := require.New(t)

serverOnce = sync.Once{}
server = nil

s := NewDefaultServer(&Options{Address: ":80"})
r.NotNil(s)
r.Equal(":80", s.Address())
Expand All @@ -45,9 +36,6 @@ func TestDefaultServer_Functions(t *testing.T) {
r := require.New(t)
r.Nil(nil)

serverOnce = sync.Once{}
server = nil

s := NewDefaultServer(&Options{})
r.NotNil(s)
r.Equal(defaults.ServerAddress, s.Address())
Expand Down
24 changes: 14 additions & 10 deletions meari/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var errUnsupportedMethod = errors.New("unsupported method")
var (
serverOnce sync.Once
server Server
serverErr error // nolint
)

// Options is a basic structure that contains all options for the Server
Expand Down Expand Up @@ -55,17 +56,20 @@ func NewServer(c common.Context, opts *common.Options) (Server, error) {
Address: opts.Address,
}

server := NewDefaultServer(serverOpts)
serverOnce.Do(func() {
server = NewDefaultServer(serverOpts)
serverErr = nil

for p, handler := range handlers.AllHandlers() {
switch handler.Method {
case http.MethodGet:
logger.Debugf("register handler for 'GET %v'...", p)
server.GET(p, handler.Handler)
default:
return nil, fmt.Errorf("%w: %v", errUnsupportedMethod, handler)
for p, handler := range handlers.AllHandlers() {
switch handler.Method {
case http.MethodGet:
logger.Debugf("register handler for 'GET %v'...", p)
server.GET(p, handler.Handler)
default:
serverErr = fmt.Errorf("%w: %v", errUnsupportedMethod, handler)
}
}
}
})

return server, nil
return server, serverErr
}
Loading

0 comments on commit 92d3b3e

Please sign in to comment.