Skip to content
Snippets Groups Projects
Commit aca8f856 authored by Krasi Georgiev's avatar Krasi Georgiev
Browse files

fixed the tests

parent fe6c5445
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -15,9 +15,9 @@ package discovery
 
import (
"context"
"fmt"
"reflect"
"sync"
"sync/atomic"
"strconv"
"testing"
"time"
 
Loading
Loading
@@ -26,20 +26,23 @@ import (
yaml "gopkg.in/yaml.v2"
)
 
func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
// TestDiscoveryManagerSyncCalls checks that the target updates are received in the expected order.
func TestDiscoveryManagerSyncCalls(t *testing.T) {
// The order by which the updates are send is detirmened by the interval passed to the mock discovery adapter
// Final targets array is ordered alphabetically by the name of the discoverer.
// For example discoverer "A" with targets "t2,t3" and discoverer "B" with targets "t1,t2" will result in "t2,t3,t1,t2" after the merge.
testCases := []struct {
title string
updates map[string][]update
expectedSyncCalls [][]string
title string
updates map[string][]update
expectedTargets [][]*config.TargetGroup
}{
{
title: "Single TP no updates",
updates: map[string][]update{
"tp1": {},
},
expectedSyncCalls: [][]string{
{},
},
expectedTargets: nil,
},
{
title: "Multips TPs no updates",
Loading
Loading
@@ -48,9 +51,7 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
"tp2": {},
"tp3": {},
},
expectedSyncCalls: [][]string{
{},
},
expectedTargets: nil,
},
{
title: "Single TP empty initials",
Loading
Loading
@@ -62,7 +63,7 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
},
},
},
expectedSyncCalls: [][]string{
expectedTargets: [][]*config.TargetGroup{
{},
},
},
Loading
Loading
@@ -78,7 +79,7 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
"tp2": {
{
targetGroups: []config.TargetGroup{},
interval: 500,
interval: 200,
},
},
"tp3": {
Loading
Loading
@@ -88,27 +89,9 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
},
},
},
expectedSyncCalls: [][]string{
expectedTargets: [][]*config.TargetGroup{
{},
{},
},
},
{
title: "Multiple TPs empty initials with a delay",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{},
interval: 6000,
},
},
"tp2": {
{
targetGroups: []config.TargetGroup{},
interval: 6500,
},
},
},
expectedSyncCalls: [][]string{
{},
},
},
Loading
Loading
@@ -117,13 +100,26 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 0,
targetGroups: []config.TargetGroup{
{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
}},
},
},
},
expectedSyncCalls: [][]string{
{"initial1", "initial2"},
expectedTargets: [][]*config.TargetGroup{
{{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
}, {
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
}},
},
},
{
Loading
Loading
@@ -131,64 +127,67 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "tp1-initial1"}, {Source: "tp1-initial2"}},
interval: 0,
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
}, {
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
},
},
"tp2": {
{
targetGroups: []config.TargetGroup{{Source: "tp2-initial1"}},
interval: 0,
targetGroups: []config.TargetGroup{{
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "3"}},
}},
interval: 10,
},
},
},
expectedSyncCalls: [][]string{
{"tp1-initial1", "tp1-initial2", "tp2-initial1"},
},
},
{
title: "Single TP delayed initials only",
updates: map[string][]update{
"tp1": {
expectedTargets: [][]*config.TargetGroup{
{
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 6000,
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
}, {
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
},
expectedSyncCalls: [][]string{
{},
{"initial1", "initial2"},
},
},
{
title: "Multiple TPs with some delayed initials",
updates: map[string][]update{
"tp1": {
}, {
{
targetGroups: []config.TargetGroup{{Source: "tp1-initial1"}, {Source: "tp1-initial2"}},
interval: 100,
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
}, {
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
"tp2": {
{
targetGroups: []config.TargetGroup{{Source: "tp2-initial1"}, {Source: "tp2-initial2"}, {Source: "tp2-initial3"}},
interval: 6000,
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
},
},
expectedSyncCalls: [][]string{
{"tp1-initial1", "tp1-initial2"},
{"tp1-initial1", "tp1-initial2", "tp2-initial1", "tp2-initial2", "tp2-initial3"},
},
},
{
title: "Single TP initials followed by empty updates",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 0,
targetGroups: []config.TargetGroup{
{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
interval: 0,
},
{
targetGroups: []config.TargetGroup{},
Loading
Loading
@@ -196,816 +195,498 @@ func TestTargetSetThrottlesTheSyncCalls(t *testing.T) {
},
},
},
expectedSyncCalls: [][]string{
{"initial1", "initial2"},
},
},
{
title: "Single TP initials and new groups",
updates: map[string][]update{
"tp1": {
expectedTargets: [][]*config.TargetGroup{
{
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 0,
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{{Source: "update1"}, {Source: "update2"}},
interval: 10,
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
},
expectedSyncCalls: [][]string{
{"initial1", "initial2"},
{"initial1", "initial2", "update1", "update2"},
{},
},
},
{
title: "Multiple TPs initials and new groups",
title: "Single TP initials and new groups",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "tp1-initial1"}, {Source: "tp1-initial2"}},
interval: 10,
},
{
targetGroups: []config.TargetGroup{{Source: "tp1-update1"}, {Source: "tp1-update2"}},
interval: 1500,
},
},
"tp2": {
{
targetGroups: []config.TargetGroup{{Source: "tp2-initial1"}, {Source: "tp2-initial2"}},
interval: 100,
targetGroups: []config.TargetGroup{
{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
interval: 0,
},
{
targetGroups: []config.TargetGroup{{Source: "tp2-update1"}, {Source: "tp2-update2"}},
interval: 10,
targetGroups: []config.TargetGroup{
{
Source: "update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
Source: "update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
interval: 10,
},
},
},
expectedSyncCalls: [][]string{
{"tp1-initial1", "tp1-initial2", "tp2-initial1", "tp2-initial2"},
{"tp1-initial1", "tp1-initial2", "tp2-initial1", "tp2-initial2", "tp1-update1", "tp1-update2", "tp2-update1", "tp2-update2"},
},
},
{
title: "One tp initials arrive after other tp updates but still within 5 seconds",
updates: map[string][]update{
"tp1": {
expectedTargets: [][]*config.TargetGroup{
{
{
targetGroups: []config.TargetGroup{{Source: "tp1-initial1"}, {Source: "tp1-initial2"}},
interval: 10,
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{{Source: "tp1-update1"}, {Source: "tp1-update2"}},
interval: 1500,
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
"tp2": {
{
{
targetGroups: []config.TargetGroup{{Source: "tp2-initial1"}, {Source: "tp2-initial2"}},
interval: 2000,
Source: "update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
targetGroups: []config.TargetGroup{{Source: "tp2-update1"}, {Source: "tp2-update2"}},
interval: 1000,
Source: "update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
},
expectedSyncCalls: [][]string{
{"tp1-initial1", "tp1-initial2", "tp1-update1", "tp1-update2", "tp2-initial1", "tp2-initial2"},
{"tp1-initial1", "tp1-initial2", "tp1-update1", "tp1-update2", "tp2-initial1", "tp2-initial2", "tp2-update1", "tp2-update2"},
},
},
{
title: "One tp initials arrive after other tp updates and after 5 seconds",
title: "Multiple TPs initials and new groups",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "tp1-initial1"}, {Source: "tp1-initial2"}},
interval: 10,
},
{
targetGroups: []config.TargetGroup{{Source: "tp1-update1"}, {Source: "tp1-update2"}},
interval: 1500,
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
interval: 10,
},
{
targetGroups: []config.TargetGroup{{Source: "tp1-update3"}},
interval: 5000,
targetGroups: []config.TargetGroup{
{
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
interval: 500,
},
},
"tp2": {
{
targetGroups: []config.TargetGroup{{Source: "tp2-initial1"}, {Source: "tp2-initial2"}},
interval: 6000,
},
},
},
expectedSyncCalls: [][]string{
{"tp1-initial1", "tp1-initial2", "tp1-update1", "tp1-update2"},
{"tp1-initial1", "tp1-initial2", "tp1-update1", "tp1-update2", "tp2-initial1", "tp2-initial2", "tp1-update3"},
},
},
{
title: "Single TP initials and new groups after a delay",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 6000,
},
{
targetGroups: []config.TargetGroup{{Source: "update1"}, {Source: "update2"}},
interval: 10,
},
},
},
expectedSyncCalls: [][]string{
{},
{"initial1", "initial2", "update1", "update2"},
},
},
{
title: "Single TP initial and successive updates",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "initial1"}},
interval: 100,
},
{
targetGroups: []config.TargetGroup{{Source: "update1"}},
interval: 100,
},
{
targetGroups: []config.TargetGroup{{Source: "update2"}},
interval: 10,
targetGroups: []config.TargetGroup{
{
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "5"}},
},
{
Source: "tp2-initial2",
Targets: []model.LabelSet{{"__instance__": "6"}},
},
},
interval: 100,
},
{
targetGroups: []config.TargetGroup{{Source: "update3"}},
interval: 10,
targetGroups: []config.TargetGroup{
{
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "7"}},
},
{
Source: "tp2-update2",
Targets: []model.LabelSet{{"__instance__": "8"}},
},
},
interval: 10,
},
},
},
expectedSyncCalls: [][]string{
{"initial1"},
{"initial1", "update1", "update2", "update3"},
},
},
{
title: "Multiple TPs initials and successive updates",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{{Source: "tp1-initial1"}},
interval: 1000,
},
{
targetGroups: []config.TargetGroup{{Source: "tp1-update1"}},
interval: 1000,
},
expectedTargets: [][]*config.TargetGroup{
{
{
targetGroups: []config.TargetGroup{{Source: "tp1-update2"}},
interval: 2000,
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{{Source: "tp1-update3"}},
interval: 2000,
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
"tp2": {
{
{
targetGroups: []config.TargetGroup{{Source: "tp2-initial1"}},
interval: 3000,
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{{Source: "tp2-update1"}},
interval: 1000,
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
{
targetGroups: []config.TargetGroup{{Source: "tp2-update2"}},
interval: 3000,
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "5"}},
},
{
targetGroups: []config.TargetGroup{{Source: "tp2-update3"}},
interval: 2000,
Source: "tp2-initial2",
Targets: []model.LabelSet{{"__instance__": "6"}},
},
},
},
expectedSyncCalls: [][]string{
{"tp1-initial1", "tp1-update1", "tp2-initial1"},
{"tp1-initial1", "tp1-update1", "tp2-initial1", "tp1-update2", "tp1-update3", "tp2-update1", "tp2-update2"},
{"tp1-initial1", "tp1-update1", "tp2-initial1", "tp1-update2", "tp1-update3", "tp2-update1", "tp2-update2", "tp2-update3"},
},
},
{
title: "Single TP Multiple updates 5 second window",
updates: map[string][]update{
"tp1": {
{
{
targetGroups: []config.TargetGroup{{Source: "initial1"}},
interval: 10,
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{{Source: "update1"}},
interval: 25,
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
{
targetGroups: []config.TargetGroup{{Source: "update2"}, {Source: "update3"}, {Source: "update4"}},
interval: 10,
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "7"}},
},
{
targetGroups: []config.TargetGroup{{Source: "update5"}},
interval: 0,
},
{
targetGroups: []config.TargetGroup{{Source: "update6"}, {Source: "update7"}, {Source: "update8"}},
interval: 70,
Source: "tp2-update2",
Targets: []model.LabelSet{{"__instance__": "8"}},
},
},
},
expectedSyncCalls: [][]string{
{"initial1"},
{"initial1", "update1", "update2", "update3", "update4", "update5", "update6", "update7", "update8"},
},
},
{
title: "Single TP Single provider empty update in between",
updates: map[string][]update{
"tp1": {
{
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 30,
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
targetGroups: []config.TargetGroup{{Source: "update1"}, {Source: "update2"}},
interval: 300,
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
{
targetGroups: []config.TargetGroup{},
interval: 10,
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "7"}},
},
{
targetGroups: []config.TargetGroup{{Source: "update3"}, {Source: "update4"}, {Source: "update5"}, {Source: "update6"}},
interval: 6000,
Source: "tp2-update2",
Targets: []model.LabelSet{{"__instance__": "8"}},
},
},
},
expectedSyncCalls: [][]string{
{"initial1", "initial2"},
{"initial1", "initial2", "update1", "update2"},
{"initial1", "initial2", "update1", "update2", "update3", "update4", "update5", "update6"},
},
},
}
for i, testCase := range testCases {
finalize := make(chan bool)
syncCallCount := 0
syncedGroups := make([][]string, 0)
targetSet := NewTargetSet(&mockSyncer{
sync: func(tgs []*config.TargetGroup) {
currentCallGroup := make([]string, len(tgs))
for i, tg := range tgs {
currentCallGroup[i] = tg.Source
}
syncedGroups = append(syncedGroups, currentCallGroup)
syncCallCount++
if syncCallCount == len(testCase.expectedSyncCalls) {
// All the groups are sent, we can start asserting.
close(finalize)
}
},
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
targetProviders := map[string]TargetProvider{}
for tpName, tpUpdates := range testCase.updates {
tp := newMockTargetProvider(tpUpdates)
targetProviders[tpName] = tp
}
go targetSet.Run(ctx)
targetSet.UpdateProviders(targetProviders)
select {
case <-time.After(20 * time.Second):
t.Errorf("%d. %q: Test timed out after 20 seconds. All targets should be sent within the timeout", i, testCase.title)
case <-finalize:
for name, tp := range targetProviders {
runCallCount := tp.(mockTargetProvider).callCount()
if runCallCount != 1 {
t.Errorf("%d. %q: TargetProvider Run should be called once for each target provider. For %q was called %d times", i, testCase.title, name, runCallCount)
}
}
if len(syncedGroups) != len(testCase.expectedSyncCalls) {
t.Errorf("%d. %q: received sync calls: \n %v \n do not match expected calls: \n %v \n", i, testCase.title, syncedGroups, testCase.expectedSyncCalls)
}
for j := range syncedGroups {
if len(syncedGroups[j]) != len(testCase.expectedSyncCalls[j]) {
t.Errorf("%d. %q: received sync calls in call [%v]: \n %v \n do not match expected calls: \n %v \n", i, testCase.title, j, syncedGroups[j], testCase.expectedSyncCalls[j])
}
expectedGroupsMap := make(map[string]struct{})
for _, expectedGroup := range testCase.expectedSyncCalls[j] {
expectedGroupsMap[expectedGroup] = struct{}{}
}
for _, syncedGroup := range syncedGroups[j] {
if _, ok := expectedGroupsMap[syncedGroup]; !ok {
t.Errorf("%d. %q: '%s' does not exist in expected target groups: %s", i, testCase.title, syncedGroup, testCase.expectedSyncCalls[j])
} else {
delete(expectedGroupsMap, syncedGroup) // Remove used targets from the map.
}
}
}
}
}
}
func TestTargetSetConsolidatesToTheLatestState(t *testing.T) {
testCases := []struct {
title string
updates map[string][]update
}{
{
title: "Single TP update same initial group multiple times",
title: "One tp initials arrive after other tp updates.",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{
{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.11:6003"}},
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
},
interval: 100,
},
{
targetGroups: []config.TargetGroup{
{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.11:6003"}, {"__instance__": "10.11.122.12:6003"}},
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
interval: 250,
interval: 10,
},
{
targetGroups: []config.TargetGroup{
{
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.12:6003"}},
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
interval: 250,
interval: 150,
},
},
},
},
{
title: "Multiple TPs update",
updates: map[string][]update{
"tp1": {
"tp2": {
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.11:6003"}},
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "5"}},
},
},
interval: 3,
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.12:6003"}},
Source: "tp2-initial2",
Targets: []model.LabelSet{{"__instance__": "6"}},
},
},
interval: 10,
interval: 200,
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-update1",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.12:6003"},
{"__instance__": "10.11.122.13:6003"},
{"__instance__": "10.11.122.14:6003"},
},
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "7"}},
},
{
Source: "tp2-update2",
Targets: []model.LabelSet{{"__instance__": "8"}},
},
},
interval: 10,
interval: 100,
},
},
"tp2": {
},
expectedTargets: [][]*config.TargetGroup{
{
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.11:6003"}},
},
},
interval: 3,
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.12:6003"}},
},
},
interval: 10,
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
{
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-update1",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.12:6003"},
{"__instance__": "10.11.122.13:6003"},
{"__instance__": "10.11.122.14:6003"},
},
},
},
interval: 10,
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
},
},
{
title: "Multiple TPs update II",
updates: map[string][]update{
"tp1": {
{
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.11:6003"}},
},
{
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "10.11.122.12:6003"}},
},
},
interval: 100,
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.13:6003"}},
},
{
Source: "tp1-initial2",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.12:6003"},
{"__instance__": "10.11.122.14:6003"},
},
},
},
interval: 100,
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "10.11.122.15:6003"}},
},
{
Source: "tp1-initial1",
Targets: []model.LabelSet{},
},
},
interval: 100,
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "5"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-update1",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.16:6003"},
{"__instance__": "10.11.122.17:6003"},
{"__instance__": "10.11.122.18:6003"},
},
},
},
interval: 100,
Source: "tp2-initial2",
Targets: []model.LabelSet{{"__instance__": "6"}},
},
},
"tp2": {
{
{
targetGroups: []config.TargetGroup{},
interval: 100,
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.13:6003"}},
},
},
interval: 100,
Source: "tp1-update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-update2",
Targets: []model.LabelSet{{"__instance__": "10.11.122.15:6003"}},
},
{
Source: "tp2-update1",
Targets: []model.LabelSet{},
},
},
interval: 300,
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "7"}},
},
{
Source: "tp2-update2",
Targets: []model.LabelSet{{"__instance__": "8"}},
},
},
},
},
{
title: "Three rounds of sync call",
title: "Single TP Single provider empty update in between",
updates: map[string][]update{
"tp1": {
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.11:6003"},
{"__instance__": "10.11.122.12:6003"},
{"__instance__": "10.11.122.13:6003"},
},
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
Source: "tp1-initial2",
Targets: []model.LabelSet{{"__instance__": "10.11.122.14:6003"}},
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
interval: 1000,
interval: 30,
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.12:6003"}},
},
{
Source: "tp1-update1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.15:6003"}},
},
},
interval: 3000,
targetGroups: []config.TargetGroup{},
interval: 10,
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp1-initial1",
Targets: []model.LabelSet{},
Source: "update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
Source: "tp1-update1",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.15:6003"},
{"__instance__": "10.11.122.16:6003"},
},
Source: "update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
interval: 3000,
interval: 300,
},
},
"tp2": {
},
expectedTargets: [][]*config.TargetGroup{
{
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-initial1",
Targets: []model.LabelSet{
{"__instance__": "10.11.122.11:6003"},
},
},
{
Source: "tp2-initial2",
Targets: []model.LabelSet{{"__instance__": "10.11.122.14:6003"}},
},
{
Source: "tp2-initial3",
Targets: []model.LabelSet{{"__instance__": "10.11.122.15:6003"}},
},
},
interval: 6000,
Source: "initial1",
Targets: []model.LabelSet{{"__instance__": "1"}},
},
{
targetGroups: []config.TargetGroup{
{
Source: "tp2-initial1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.11:6003"}, {"__instance__": "10.11.122.12:6003"}},
},
{
Source: "tp2-update1",
Targets: []model.LabelSet{{"__instance__": "10.11.122.15:6003"}},
},
},
interval: 3000,
Source: "initial2",
Targets: []model.LabelSet{{"__instance__": "2"}},
},
},
{},
{
{
Source: "update1",
Targets: []model.LabelSet{{"__instance__": "3"}},
},
{
Source: "update2",
Targets: []model.LabelSet{{"__instance__": "4"}},
},
},
},
},
}
 
// Function to determine if the sync call received the latest state of
// all the target groups that came out of the target provider.
endStateAchieved := func(groupsSentToSyc []*config.TargetGroup, endState map[string]config.TargetGroup) bool {
for testIndex, testCase := range testCases {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
discoveryManager := NewManager(ctx, nil)
go discoveryManager.Run()
 
if len(groupsSentToSyc) != len(endState) {
return false
}
var totalUpdatesCount int
for tpName, update := range testCase.updates {
provider := newMockDiscoveryProvider(update)
discoveryManager.startProvider(strconv.Itoa(testIndex), tpName, provider)
 
for _, tg := range groupsSentToSyc {
if _, ok := endState[tg.Source]; ok == false {
// The target group does not exist in the end state.
return false
if len(update) > 0 {
totalUpdatesCount = totalUpdatesCount + len(update)
}
if reflect.DeepEqual(endState[tg.Source], *tg) == false {
// The target group has not reached its final state yet.
return false
}
delete(endState, tg.Source) // Remove used target groups.
}
 
return true
}
for i, testCase := range testCases {
expectedGroups := make(map[string]config.TargetGroup)
for _, tpUpdates := range testCase.updates {
for _, update := range tpUpdates {
for _, targetGroup := range update.targetGroups {
expectedGroups[targetGroup.Source] = targetGroup
Loop:
for x := 0; x < totalUpdatesCount; x++ {
select {
case <-time.After(10 * time.Second):
t.Errorf("%v. %q: no update arrived within the timeout limit", x, testCase.title)
break Loop
case tsetMap := <-discoveryManager.SyncCh():
for _, received := range tsetMap {
if !reflect.DeepEqual(received, testCase.expectedTargets[x]) {
var receivedFormated string
for _, receivedTargets := range received {
receivedFormated = receivedFormated + receivedTargets.Source + ":" + fmt.Sprint(receivedTargets.Targets)
}
var expectedFormated string
for _, receivedTargets := range testCase.expectedTargets[x] {
expectedFormated = expectedFormated + receivedTargets.Source + ":" + fmt.Sprint(receivedTargets.Targets)
}
t.Errorf("%v. %v: \ntargets mismatch \nreceived: %v \nexpected: %v",
x, testCase.title,
receivedFormated,
expectedFormated)
}
}
}
}
}
}
 
finalize := make(chan bool)
targetSet := NewTargetSet(&mockSyncer{
sync: func(tgs []*config.TargetGroup) {
endState := make(map[string]config.TargetGroup)
for k, v := range expectedGroups {
endState[k] = v
}
if endStateAchieved(tgs, endState) == false {
return
}
close(finalize)
},
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
targetProviders := map[string]TargetProvider{}
for tpName, tpUpdates := range testCase.updates {
tp := newMockTargetProvider(tpUpdates)
targetProviders[tpName] = tp
func TestTargetSetRecreatesTargetGroupsEveryRun(t *testing.T) {
verifyPresence := func(tSets map[string]map[string][]*config.TargetGroup, tSetName string, provName, label string, present bool) {
if _, ok := tSets[tSetName]; !ok {
t.Fatalf("'%s' should be present in TargetSets: %v", tSetName, tSets)
return
}
if _, ok := tSets[tSetName][provName]; !ok {
t.Fatalf("'%s' should be present in Discovery providers: %v", provName, tSets[tSetName])
return
}
 
go targetSet.Run(ctx)
targetSet.UpdateProviders(targetProviders)
match := false
var mergedTargets string
for _, targetGroup := range tSets[tSetName][provName] {
 
select {
case <-time.After(20 * time.Second):
t.Errorf("%d. %q: Test timed out after 20 seconds. All targets should be sent within the timeout", i, testCase.title)
for _, l := range targetGroup.Targets {
mergedTargets = mergedTargets + " " + l.String()
if l.String() == label {
match = true
}
}
 
case <-finalize:
// System successfully reached to the end state.
}
}
}
func TestTargetSetRecreatesTargetGroupsEveryRun(t *testing.T) {
verifyPresence := func(tgroups map[string]*config.TargetGroup, name string, present bool) {
if _, ok := tgroups[name]; ok != present {
if match != present {
msg := ""
if !present {
msg = "not "
msg = "not"
}
t.Fatalf("'%s' should %sbe present in TargetSet.tgroups: %s", name, msg, tgroups)
t.Fatalf("'%s' should %s be present in Targets labels: %v", label, msg, mergedTargets)
}
}
 
cfg := &config.ServiceDiscoveryConfig{}
cfg := &config.Config{}
 
sOne := `
static_configs:
- targets: ["foo:9090"]
- targets: ["bar:9090"]
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ["foo:9090"]
- targets: ["bar:9090"]
`
if err := yaml.Unmarshal([]byte(sOne), cfg); err != nil {
t.Fatalf("Unable to load YAML config sOne: %s", err)
}
called := make(chan struct{})
ts := NewTargetSet(&mockSyncer{
sync: func([]*config.TargetGroup) { called <- struct{}{} },
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
discoveryManager := NewManager(ctx, nil)
go discoveryManager.Run()
 
go ts.Run(ctx)
ts.UpdateProviders(ProvidersFromConfig(*cfg, nil))
<-called
discoveryManager.ApplyConfig(cfg)
 
verifyPresence(ts.tgroups, "static/0/0", true)
verifyPresence(ts.tgroups, "static/0/1", true)
_ = <-discoveryManager.SyncCh()
verifyPresence(discoveryManager.targets, "prometheus", "static/0", "{__address__=\"foo:9090\"}", true)
verifyPresence(discoveryManager.targets, "prometheus", "static/0", "{__address__=\"bar:9090\"}", true)
 
sTwo := `
static_configs:
- targets: ["foo:9090"]
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ["foo:9090"]
`
if err := yaml.Unmarshal([]byte(sTwo), cfg); err != nil {
t.Fatalf("Unable to load YAML config sTwo: %s", err)
}
ts.UpdateProviders(ProvidersFromConfig(*cfg, nil))
<-called
verifyPresence(ts.tgroups, "static/0/0", true)
verifyPresence(ts.tgroups, "static/0/1", false)
}
func TestTargetSetRunsSameTargetProviderMultipleTimes(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
ts1 := NewTargetSet(&mockSyncer{
sync: func([]*config.TargetGroup) { wg.Done() },
})
ts2 := NewTargetSet(&mockSyncer{
sync: func([]*config.TargetGroup) { wg.Done() },
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
updates := []update{
{
targetGroups: []config.TargetGroup{{Source: "initial1"}, {Source: "initial2"}},
interval: 10,
},
}
tp := newMockTargetProvider(updates)
targetProviders := map[string]TargetProvider{}
targetProviders["testProvider"] = tp
go ts1.Run(ctx)
go ts2.Run(ctx)
ts1.UpdateProviders(targetProviders)
ts2.UpdateProviders(targetProviders)
finalize := make(chan struct{})
go func() {
defer close(finalize)
wg.Wait()
}()
select {
case <-time.After(20 * time.Second):
t.Error("Test timed out after 20 seconds. All targets should be sent within the timeout")
case <-finalize:
if tp.callCount() != 2 {
t.Errorf("Was expecting 2 calls, received %d", tp.callCount())
}
t.Fatalf("Unable to load YAML config sOne: %s", err)
}
}
discoveryManager.ApplyConfig(cfg)
 
type mockSyncer struct {
sync func(tgs []*config.TargetGroup)
}
func (s *mockSyncer) Sync(tgs []*config.TargetGroup) {
if s.sync != nil {
s.sync(tgs)
}
_ = <-discoveryManager.SyncCh()
verifyPresence(discoveryManager.targets, "prometheus", "static/0", "{__address__=\"foo:9090\"}", true)
verifyPresence(discoveryManager.targets, "prometheus", "static/0", "{__address__=\"bar:9090\"}", false)
}
 
type update struct {
Loading
Loading
@@ -1013,30 +694,25 @@ type update struct {
interval time.Duration
}
 
type mockTargetProvider struct {
_callCount *int32
updates []update
up chan<- []*config.TargetGroup
type mockdiscoveryProvider struct {
updates []update
up chan<- []*config.TargetGroup
}
 
func newMockTargetProvider(updates []update) mockTargetProvider {
var callCount int32
func newMockDiscoveryProvider(updates []update) mockdiscoveryProvider {
 
tp := mockTargetProvider{
_callCount: &callCount,
updates: updates,
tp := mockdiscoveryProvider{
updates: updates,
}
return tp
}
 
func (tp mockTargetProvider) Run(ctx context.Context, up chan<- []*config.TargetGroup) {
atomic.AddInt32(tp._callCount, 1)
func (tp mockdiscoveryProvider) Run(ctx context.Context, up chan<- []*config.TargetGroup) {
tp.up = up
tp.sendUpdates()
}
 
func (tp mockTargetProvider) sendUpdates() {
func (tp mockdiscoveryProvider) sendUpdates() {
for _, update := range tp.updates {
 
time.Sleep(update.interval * time.Millisecond)
Loading
Loading
@@ -1045,11 +721,6 @@ func (tp mockTargetProvider) sendUpdates() {
for i := range update.targetGroups {
tgs[i] = &update.targetGroups[i]
}
tp.up <- tgs
}
}
func (tp mockTargetProvider) callCount() int {
return int(atomic.LoadInt32(tp._callCount))
}
Loading
Loading
@@ -96,7 +96,7 @@ func TestReadyAndHealthy(t *testing.T) {
Context: nil,
Storage: &tsdb.ReadyStorage{},
QueryEngine: nil,
TargetManager: nil,
ScrapeManager: nil,
RuleManager: nil,
Notifier: nil,
RoutePrefix: "/",
Loading
Loading
@@ -187,7 +187,7 @@ func TestRoutePrefix(t *testing.T) {
Context: nil,
Storage: &tsdb.ReadyStorage{},
QueryEngine: nil,
TargetManager: nil,
ScrapeManager: nil,
RuleManager: nil,
Notifier: nil,
RoutePrefix: "/prometheus",
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment