Skip to content

Commit 807f580

Browse files
committed
test(pkg/descheduler): TestPluginPrometheusClientAccess_Secret to test secret based token reconciliation
This test makes sure the secret is reconciled and available in plugins while running the descheduler from its main entry point.
1 parent 643179c commit 807f580

File tree

1 file changed

+187
-1
lines changed

1 file changed

+187
-1
lines changed

pkg/descheduler/descheduler_test.go

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,193 @@ func verifyAllPrometheusClientsEqual(t *testing.T, expected, fromReactor, fromPl
14201420
}
14211421

14221422
// TestPluginPrometheusClientAccess tests that the Prometheus client is accessible through the plugin handle
1423-
func TestPluginPrometheusClientAccess(t *testing.T) {
1423+
func TestPluginPrometheusClientAccess_Secret(t *testing.T) {
1424+
testCases := []struct {
1425+
name string
1426+
dryRun bool
1427+
}{
1428+
{
1429+
name: "dry run disabled",
1430+
dryRun: false,
1431+
},
1432+
{
1433+
name: "dry run enabled",
1434+
dryRun: true,
1435+
},
1436+
}
1437+
1438+
for _, tc := range testCases {
1439+
t.Run(tc.name, func(t *testing.T) {
1440+
ctx := context.Background()
1441+
1442+
initPluginRegistry()
1443+
1444+
newInvoked := false
1445+
reactorInvoked := false
1446+
var prometheusClientFromPluginNewHandle promapi.Client
1447+
var prometheusClientFromReactor promapi.Client
1448+
1449+
fakePlugin := &fakeplugin.FakePlugin{
1450+
PluginName: "TestPluginWithPrometheusClient",
1451+
}
1452+
1453+
fakePlugin.AddReactor(string(frameworktypes.DescheduleExtensionPoint), func(action fakeplugin.Action) (handled, filter bool, err error) {
1454+
if dAction, ok := action.(fakeplugin.DescheduleAction); ok {
1455+
reactorInvoked = true
1456+
prometheusClientFromReactor = dAction.Handle().PrometheusClient()
1457+
return true, false, nil
1458+
}
1459+
return false, false, nil
1460+
})
1461+
1462+
pluginregistry.Register(
1463+
fakePlugin.PluginName,
1464+
fakeplugin.NewPluginFncFromFakeWithReactor(fakePlugin, func(action fakeplugin.ActionImpl) {
1465+
newInvoked = true
1466+
prometheusClientFromPluginNewHandle = action.Handle().PrometheusClient()
1467+
}),
1468+
&fakeplugin.FakePlugin{},
1469+
&fakeplugin.FakePluginArgs{},
1470+
fakeplugin.ValidateFakePluginArgs,
1471+
fakeplugin.SetDefaults_FakePluginArgs,
1472+
pluginregistry.PluginRegistry,
1473+
)
1474+
1475+
deschedulerPolicy := &api.DeschedulerPolicy{
1476+
MetricsProviders: []api.MetricsProvider{
1477+
{
1478+
Source: api.PrometheusMetrics,
1479+
Prometheus: newPrometheusConfig(),
1480+
},
1481+
},
1482+
Profiles: []api.DeschedulerProfile{
1483+
{
1484+
Name: "test-profile",
1485+
PluginConfigs: []api.PluginConfig{
1486+
{
1487+
Name: fakePlugin.PluginName,
1488+
Args: &fakeplugin.FakePluginArgs{},
1489+
},
1490+
},
1491+
Plugins: api.Plugins{
1492+
Deschedule: api.PluginSet{
1493+
Enabled: []string{fakePlugin.PluginName},
1494+
},
1495+
},
1496+
},
1497+
},
1498+
}
1499+
1500+
node1 := test.BuildTestNode("node1", 1000, 2000, 9, nil)
1501+
node2 := test.BuildTestNode("node2", 1000, 2000, 9, nil)
1502+
1503+
_, descheduler, runFnc, fakeClient := initDescheduler(t, ctx, initFeatureGates(), deschedulerPolicy, nil, tc.dryRun, node1, node2)
1504+
1505+
// Test cycles with different Prometheus client values
1506+
cycles := []struct {
1507+
name string
1508+
operation func() error
1509+
skipWaiting bool
1510+
client promapi.Client
1511+
token string
1512+
}{
1513+
{
1514+
name: "no secret initially",
1515+
operation: func() error { return nil },
1516+
skipWaiting: true,
1517+
client: nil,
1518+
token: "",
1519+
},
1520+
{
1521+
name: "add secret",
1522+
operation: func() error {
1523+
secret := newPrometheusAuthSecret(withToken("token-1"))
1524+
_, err := fakeClient.CoreV1().Secrets(secret.Namespace).Create(ctx, secret, metav1.CreateOptions{})
1525+
return err
1526+
},
1527+
client: &mockPrometheusClient{name: "new-init-client"},
1528+
token: "token-1",
1529+
},
1530+
{
1531+
name: "update secret",
1532+
operation: func() error {
1533+
secret := newPrometheusAuthSecret(withToken("token-2"))
1534+
_, err := fakeClient.CoreV1().Secrets(secret.Namespace).Update(ctx, secret, metav1.UpdateOptions{})
1535+
return err
1536+
},
1537+
client: &mockPrometheusClient{name: "new-client"},
1538+
token: "token-2",
1539+
},
1540+
{
1541+
name: "delete secret",
1542+
operation: func() error {
1543+
secret := newPrometheusAuthSecret(withToken("token-3"))
1544+
return fakeClient.CoreV1().Secrets(secret.Namespace).Delete(ctx, secret.Name, metav1.DeleteOptions{})
1545+
},
1546+
client: nil,
1547+
token: "",
1548+
},
1549+
}
1550+
1551+
for i, cycle := range cycles {
1552+
t.Logf("Cycle %d: %s", i+1, cycle.name)
1553+
1554+
// Set the descheduler's Prometheus client
1555+
t.Logf("Setting descheduler.promClientCtrl.promClient from %v to %v", descheduler.promClientCtrl.promClient, cycle.client)
1556+
descheduler.promClientCtrl.createPrometheusClient = func(url, token string) (promapi.Client, *http.Transport, error) {
1557+
if token != cycle.token {
1558+
t.Fatalf("Expected token to be %q, got %q", cycle.token, token)
1559+
}
1560+
if url != prometheusURL {
1561+
t.Fatalf("Expected url to be %q, got %q", prometheusURL, url)
1562+
}
1563+
return cycle.client, &http.Transport{}, nil
1564+
}
1565+
1566+
if err := cycle.operation(); err != nil {
1567+
t.Fatalf("operation failed: %v", err)
1568+
}
1569+
1570+
if !cycle.skipWaiting {
1571+
err := wait.PollUntilContextTimeout(ctx, 50*time.Millisecond, 200*time.Millisecond, true, func(ctx context.Context) (bool, error) {
1572+
currentPromClient := descheduler.promClientCtrl.prometheusClient()
1573+
if currentPromClient != cycle.client {
1574+
t.Logf("Waiting for prometheus client to be set to %v, got %v instead, waiting", cycle.client, currentPromClient)
1575+
return false, nil
1576+
}
1577+
return true, nil
1578+
})
1579+
if err != nil {
1580+
t.Fatalf("Timed out waiting for expected conditions: %v", err)
1581+
}
1582+
}
1583+
1584+
newInvoked = false
1585+
reactorInvoked = false
1586+
prometheusClientFromPluginNewHandle = nil
1587+
prometheusClientFromReactor = nil
1588+
1589+
if err := runFnc(ctx); err != nil {
1590+
t.Fatalf("Unexpected error during running a descheduling cycle: %v", err)
1591+
}
1592+
1593+
t.Logf("After cycle %d: prometheusClientFromReactor=%v, descheduler.promClientCtrl.promClient=%v", i+1, prometheusClientFromReactor, descheduler.promClientCtrl.promClient)
1594+
1595+
if !newInvoked {
1596+
t.Fatalf("Expected plugin new to be invoked during cycle %d", i+1)
1597+
}
1598+
1599+
if !reactorInvoked {
1600+
t.Fatalf("Expected deschedule reactor to be invoked during cycle %d", i+1)
1601+
}
1602+
1603+
verifyAllPrometheusClientsEqual(t, cycle.client, prometheusClientFromReactor, prometheusClientFromPluginNewHandle, descheduler.promClientCtrl.promClient)
1604+
}
1605+
})
1606+
}
1607+
}
1608+
1609+
func TestPluginPrometheusClientAccess_InCluster(t *testing.T) {
14241610
testCases := []struct {
14251611
name string
14261612
dryRun bool

0 commit comments

Comments
 (0)