Skip to content

Commit

Permalink
Merge pull request #50 from caas-team/feat/target-passdown
Browse files Browse the repository at this point in the history
Global target pass-down to the Checks
  • Loading branch information
puffitos authored Dec 20, 2023
2 parents c4cbe10 + 33c2363 commit 73b2382
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 2 deletions.
58 changes: 56 additions & 2 deletions pkg/sparrow/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"
"fmt"
"net/http"
"slices"

targets "github.com/caas-team/sparrow/pkg/sparrow/targets"

Expand Down Expand Up @@ -117,17 +118,18 @@ func (s *Sparrow) ReconcileChecks(ctx context.Context) {
name := name
log := logger.FromContext(ctx).With("name", name)

c := s.updateCheckTargets(checkCfg)
if existingCheck, ok := s.checks[name]; ok {
// Check already registered, reset config
err := existingCheck.SetConfig(ctx, checkCfg)
err := existingCheck.SetConfig(ctx, c)
if err != nil {
log.ErrorContext(ctx, "Failed to reset config for check, check will run with last applies config", "error", err)
}
continue
}

// Check is a new Check and needs to be registered
s.registerCheck(ctx, name, checkCfg)
s.registerCheck(ctx, name, c)
}

for existingCheckName, existingCheck := range s.checks {
Expand All @@ -141,6 +143,58 @@ func (s *Sparrow) ReconcileChecks(ctx context.Context) {
}
}

// updateCheckTargets updates the targets of a check with the
// global targets. The targets are merged per default, if found in the
// passed config.
func (s *Sparrow) updateCheckTargets(cfg any) any {
if cfg == nil {
return nil
}

// check if map with targets
checkCfg, ok := cfg.(map[string]any)
if !ok {
return checkCfg
}
if _, ok = checkCfg["targets"]; !ok {
return checkCfg
}

// Check if targets is a slice
actuali, ok := checkCfg["targets"].([]any)
if !ok {
return checkCfg
}
if len(actuali) == 0 {
return checkCfg
}

// convert to string slice
var actual []string
for _, v := range actuali {
if _, ok := v.(string); !ok {
return checkCfg
}
actual = append(actual, v.(string))
}
var urls []string
gt := s.targets.GetTargets()

// filter out globalTargets that are already in the config and self
for _, t := range gt {
if slices.Contains(actual, t.Url) {
continue
}
if t.Url == fmt.Sprintf("https://%s", s.cfg.SparrowName) {
continue
}
urls = append(urls, t.Url)
}

checkCfg["targets"] = append(actual, urls...)
return checkCfg
}

// registerCheck registers and executes a new check
func (s *Sparrow) registerCheck(ctx context.Context, name string, checkCfg any) {
log := logger.FromContext(ctx).With("name", name)
Expand Down
124 changes: 124 additions & 0 deletions pkg/sparrow/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"testing"
"time"

gitlabmock "github.com/caas-team/sparrow/pkg/sparrow/targets/test"

"github.com/getkin/kin-openapi/openapi3"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -221,3 +223,125 @@ func TestSparrow_Run(t *testing.T) {
t.Log("Letting API run shortly")
time.Sleep(time.Millisecond * 150)
}

// TestSparrow_updateCheckTargets tests that the updateCheckTargets method
// updates the check targets, if they exists in the config of the checks.
func TestSparrow_updateCheckTargets(t *testing.T) {
now := time.Now()
gt := []checks.GlobalTarget{
{
Url: "https://localhost.de",
LastSeen: now,
},
}
tests := []struct {
name string
config any
globalTargets []checks.GlobalTarget
expected any
}{
{
name: "no config",
config: nil,
globalTargets: gt,
expected: nil,
},
{
name: "config with no targets",
config: map[string]any{
"targets": nil,
},
globalTargets: gt,
expected: map[string]any{
"targets": nil,
},
},
{
name: "config with non-expected targets type",
config: map[string]any{
"targets": "not a slice",
},
globalTargets: gt,
expected: map[string]any{
"targets": "not a slice",
},
},
{
name: "config with empty targets",
config: map[string]any{
"targets": []any{},
},
globalTargets: gt,
expected: map[string]any{
"targets": []any{},
},
},
{
name: "config with non string target slice",
config: map[string]any{
"targets": []any{1, 2, 3},
},
globalTargets: gt,
expected: map[string]any{
"targets": []any{1, 2, 3},
},
},
{
name: "config with mixed target slice",
config: map[string]any{
"targets": []any{"https://gitlab.com", 1, 3},
},
globalTargets: gt,
expected: map[string]any{
"targets": []any{"https://gitlab.com", 1, 3},
},
},
{
name: "config with targets",
config: map[string]any{
"targets": []any{"https://gitlab.com"},
},
globalTargets: gt,
expected: map[string]any{
"targets": []string{"https://gitlab.com", "https://localhost.de"},
},
},
{
name: "config has a target already present in global targets - no duplicates",
config: map[string]any{
"targets": []any{"https://localhost.de"},
},
globalTargets: gt,
expected: map[string]any{
"targets": []string{"https://localhost.de"},
},
},
{
name: "global targets contains self - do not add to config",
config: map[string]any{
"targets": []any{"https://localhost.de"},
},
globalTargets: append(gt, checks.GlobalTarget{
Url: "https://wonderhost.usa",
}),
expected: map[string]any{
"targets": []string{"https://localhost.de"},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Sparrow{
targets: &gitlabmock.MockTargetManager{
Targets: tt.globalTargets,
},
cfg: &config.Config{
SparrowName: "wonderhost.usa",
},
}
got := s.updateCheckTargets(tt.config)
assert.Equal(t, tt.expected, got)
})
}
}
30 changes: 30 additions & 0 deletions pkg/sparrow/targets/test/mocktargets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package gitlabmock

import (
"context"

"github.com/caas-team/sparrow/internal/logger"
"github.com/caas-team/sparrow/pkg/checks"
)

// MockTargetManager is a mock implementation of the TargetManager interface
type MockTargetManager struct {
Targets []checks.GlobalTarget
}

func (m *MockTargetManager) Reconcile(ctx context.Context) {
log := logger.FromContext(ctx)
log.Info("MockReconcile called")
}

func (m *MockTargetManager) Shutdown(ctx context.Context) error {
log := logger.FromContext(ctx)
log.Info("MockShutdown called")
return nil
}

func (m *MockTargetManager) GetTargets() []checks.GlobalTarget {
log := logger.FromContext(context.Background())
log.Info("MockGetTargets called, returning", "targets", len(m.Targets))
return m.Targets
}

0 comments on commit 73b2382

Please sign in to comment.