Skip to content

Commit

Permalink
Merge pull request #5 from caas-team/feat/cfg-loader
Browse files Browse the repository at this point in the history
Feat/cfg loader
  • Loading branch information
y-eight authored Nov 7, 2023
2 parents a8b4655 + 9475d1e commit b451cd7
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 58 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ jobs:
- name: Test
run: |
go mod download
go install github.com/matryer/[email protected]
go generate ./...
go test --race --coverprofile cover.out -v ./...
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@
# Go workspace file
go.work
gen

# generated interface mock files
*_moq.go
7 changes: 3 additions & 4 deletions cmd/run/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ import (
"context"
"log"

"github.com/caas-team/sparrow/pkg/config"
"github.com/caas-team/sparrow/pkg/sparrow"
)

func main() {

config := sparrow.NewConfig()
sparrow := sparrow.New(config)
cfg := config.NewConfig()
sparrow := sparrow.New(cfg)

log.Println("running sparrow")
if err := sparrow.Run(context.Background()); err != nil {
panic(err)
}

}
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ go 1.20

require github.com/getkin/kin-openapi v0.120.0

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
)

require (
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
Expand All @@ -12,5 +17,6 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v3 v3.0.1
)
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
5 changes: 2 additions & 3 deletions pkg/checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
// Available Checks will be registered in this map
// The key is the name of the Check
// The name needs to map the configuration item key
var RegisteredChecks = map[string]func(string) Check{
var RegisteredChecks = map[string]func() Check{
"rtt": GetRoundtripCheck,
}

//go:generate moq -out checks_moq.go . Check
type Check interface {
// Run is called once per check interval
// this should error if there is a problem running the check
Expand All @@ -29,8 +30,6 @@ type Check interface {
// This is also called while the check is running, if the remote config is updated
// This should return an error if the config is invalid
SetConfig(ctx context.Context, config any) error
// Name returns the name of the check
Name() string
// Should return an openapi3.SchemaRef of the result type returned by the check
Schema() (*openapi3.SchemaRef, error)
}
Expand Down
12 changes: 2 additions & 10 deletions pkg/checks/roundtrip.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@ type roundTripData struct {

// RoundTrip is a check that measures the round trip time of a request
type RoundTrip struct {
name string
c chan<- Result
config RoundTripConfig
}

// Constructor for the RoundtripCheck
func GetRoundtripCheck(name string) Check {
return &RoundTrip{
name: name,
}
func GetRoundtripCheck() Check {
return &RoundTrip{}
}

func (rt *RoundTrip) Run(ctx context.Context) (Result, error) {
Expand All @@ -51,11 +48,6 @@ func (rt *RoundTrip) Shutdown(ctx context.Context) error {
return nil
}

// Name returns the name of the check
func (rt *RoundTrip) Name() string {
return rt.name
}

func (rt *RoundTrip) SetConfig(ctx context.Context, config any) error {
checkConfig, ok := config.(RoundTripConfig)
if !ok {
Expand Down
2 changes: 1 addition & 1 deletion pkg/sparrow/config.go → pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sparrow
package config

type Config struct {
Checks map[string]any
Expand Down
26 changes: 26 additions & 0 deletions pkg/config/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package config

import "context"

type HttpLoader struct {
cfg *Config
cCfgChecks chan<- map[string]any
}

func NewHttpLoader(cfg *Config, cCfgChecks chan<- map[string]any) *HttpLoader {
return &HttpLoader{
cfg: cfg,
cCfgChecks: cCfgChecks,
}
}

func (gl *HttpLoader) Run(ctx context.Context) {
// Get cfg from gitlab
// check cfg has changed
// send signal

// cfg has changed
gl.cCfgChecks <- map[string]any{
"rtt": "check cfg to set dynamically",
}
}
18 changes: 18 additions & 0 deletions pkg/config/loader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package config

import (
"context"
)

const (
gitlabLoader = "GITLAB"
localLoader = "LOCAL"
)

type Loader interface {
Run(context.Context)
}

func NewLoader(cfg *Config, cCfgChecks chan<- map[string]any) Loader {
return NewHttpLoader(cfg, cCfgChecks)
}
94 changes: 64 additions & 30 deletions pkg/sparrow/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,90 @@ package sparrow
import (
"context"
"fmt"
"log"

"github.com/caas-team/sparrow/pkg/checks"
"github.com/caas-team/sparrow/pkg/config"
"github.com/getkin/kin-openapi/openapi3"
)

type Sparrow struct {
checks []checks.Check
config *Config
c chan checks.Result
checks map[string]checks.Check
cResult chan checks.Result

loader config.Loader
cfg *config.Config
cCfgChecks chan map[string]any
}

// New creates a new sparrow from a given configfile
func New(config *Config) *Sparrow {
s := &Sparrow{
config: config,
c: make(chan checks.Result),
func New(cfg *config.Config) *Sparrow {
// TODO read this from config file
sparrow := &Sparrow{
checks: make(map[string]checks.Check),
cResult: make(chan checks.Result),
cfg: cfg,
cCfgChecks: make(chan map[string]any),
}

return s
sparrow.loader = config.NewLoader(cfg, sparrow.cCfgChecks)
return sparrow
}

// Run starts the sparrow
func (s *Sparrow) Run(ctx context.Context) error {
// TODO Setup before checks run
// setup database
// setup http server
for {
select {
case <-ctx.Done():
return nil
case result := <-s.cResult:
// TODO write result to database
fmt.Println(result)
case configChecks := <-s.cCfgChecks:
// Config got updated
// Set checks
s.cfg.Checks = configChecks
s.ReconcileChecks(ctx)
}
}
}

for checkName, checkConfig := range s.config.Checks {
check := checks.RegisteredChecks[checkName](checkName)
s.checks = append(s.checks, check)
// Register new Checks, unregister removed Checks & reset Configs of Checks
func (s *Sparrow) ReconcileChecks(ctx context.Context) {
for name, check := range s.cfg.Checks {
if existingCheck, ok := s.checks[name]; ok {
// Check already registered, reset config
err := existingCheck.SetConfig(ctx, check)
if err != nil {
log.Printf("Failed to reset config for check, check will run with last applies config - %s: %s", name, err.Error())
}
continue
}
// Check is a new Check and needs to be registered
check := checks.RegisteredChecks[name]()
s.checks[name] = check

err := check.SetConfig(ctx, checkConfig)
err := check.SetConfig(ctx, check)
if err != nil {
return fmt.Errorf("failed to set config for check %s: %w", check.Name(), err)
log.Printf("Failed to set config for check %s: %s", name, err.Error())
}
err = check.Startup(ctx, s.c)
err = check.Startup(ctx, s.cResult)
if err != nil {
return fmt.Errorf("failed to startup check %s: %w", check.Name(), err)
log.Printf("Failed to startup check %s: %s", name, err.Error())
}
go check.Run(ctx)
}
for {
select {
case <-ctx.Done():
return nil
case result := <-s.c:
// TODO write result to database
fmt.Println(result)

for existingCheckName, existingCheck := range s.checks {
// Check has been removed from config; shutdown and remove
if _, ok := s.cfg.Checks[existingCheckName]; !ok {
existingCheck.Shutdown(ctx)
delete(s.checks, existingCheckName)
}
}

}

var oapiBoilerplate = openapi3.T{
Expand All @@ -76,19 +110,19 @@ var oapiBoilerplate = openapi3.T{

func (s *Sparrow) Openapi() (openapi3.T, error) {
doc := oapiBoilerplate
for _, c := range s.checks {
for name, c := range s.checks {
ref, err := c.Schema()
if err != nil {
return openapi3.T{}, fmt.Errorf("failed to get schema for check %s: %w", c.Name(), err)
return openapi3.T{}, fmt.Errorf("failed to get schema for check %s: %w", name, err)
}

routeDesc := fmt.Sprintf("Returns the performance data for check %s", c.Name())
bodyDesc := fmt.Sprintf("Metrics for check %s", c.Name())
doc.Paths["/v1/metrics/"+c.Name()] = &openapi3.PathItem{
Description: c.Name(),
routeDesc := fmt.Sprintf("Returns the performance data for check %s", name)
bodyDesc := fmt.Sprintf("Metrics for check %s", name)
doc.Paths["/v1/metrics/"+name] = &openapi3.PathItem{
Description: name,
Get: &openapi3.Operation{
Description: routeDesc,
Tags: []string{"Metrics", c.Name()},
Tags: []string{"Metrics", name},
Responses: openapi3.Responses{
"200": &openapi3.ResponseRef{
Value: &openapi3.Response{
Expand Down
Loading

0 comments on commit b451cd7

Please sign in to comment.