f4fcb9bde6
This updates our issuerconfig.UpdateStrategy to sort strategies according to a weighted preference. The TokenCredentialRequest API strategy is preffered, followed by impersonation proxy, followed by any other unknown types. Signed-off-by: Matt Moyer <moyerm@vmware.com>
219 lines
6.4 KiB
Go
219 lines
6.4 KiB
Go
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package issuerconfig
|
|
|
|
import (
|
|
"math/rand"
|
|
"sort"
|
|
"testing"
|
|
"testing/quick"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
|
)
|
|
|
|
func TestMergeStrategy(t *testing.T) {
|
|
t1 := metav1.Now()
|
|
t2 := metav1.NewTime(metav1.Now().Add(-1 * time.Hour))
|
|
|
|
tests := []struct {
|
|
name string
|
|
configToUpdate v1alpha1.CredentialIssuerStatus
|
|
strategy v1alpha1.CredentialIssuerStrategy
|
|
expected v1alpha1.CredentialIssuerStatus
|
|
}{
|
|
{
|
|
name: "new entry",
|
|
configToUpdate: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: nil,
|
|
},
|
|
strategy: v1alpha1.CredentialIssuerStrategy{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
},
|
|
expected: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
|
{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "new entry updating deprecated kubeConfigInfo",
|
|
configToUpdate: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: nil,
|
|
},
|
|
strategy: v1alpha1.CredentialIssuerStrategy{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
Frontend: &v1alpha1.CredentialIssuerFrontend{
|
|
Type: "TokenCredentialRequestAPI",
|
|
TokenCredentialRequestAPIInfo: &v1alpha1.TokenCredentialRequestAPIInfo{
|
|
Server: "https://test-server",
|
|
CertificateAuthorityData: "test-ca-bundle",
|
|
},
|
|
},
|
|
},
|
|
expected: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
|
{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
Frontend: &v1alpha1.CredentialIssuerFrontend{
|
|
Type: "TokenCredentialRequestAPI",
|
|
TokenCredentialRequestAPIInfo: &v1alpha1.TokenCredentialRequestAPIInfo{
|
|
Server: "https://test-server",
|
|
CertificateAuthorityData: "test-ca-bundle",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
KubeConfigInfo: &v1alpha1.CredentialIssuerKubeConfigInfo{
|
|
Server: "https://test-server",
|
|
CertificateAuthorityData: "test-ca-bundle",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "existing entry to update",
|
|
configToUpdate: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
|
{
|
|
Type: "Type1",
|
|
Status: v1alpha1.ErrorStrategyStatus,
|
|
Reason: "some starting reason",
|
|
Message: "some starting message",
|
|
LastUpdateTime: t2,
|
|
},
|
|
},
|
|
},
|
|
strategy: v1alpha1.CredentialIssuerStrategy{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
},
|
|
expected: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
|
{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "new entry among others",
|
|
configToUpdate: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
|
{
|
|
Type: "Type0",
|
|
Status: v1alpha1.ErrorStrategyStatus,
|
|
Reason: "some starting reason 0",
|
|
Message: "some starting message 0",
|
|
LastUpdateTime: t2,
|
|
},
|
|
{
|
|
Type: "Type2",
|
|
Status: v1alpha1.ErrorStrategyStatus,
|
|
Reason: "some starting reason 0",
|
|
Message: "some starting message 0",
|
|
LastUpdateTime: t2,
|
|
},
|
|
},
|
|
},
|
|
strategy: v1alpha1.CredentialIssuerStrategy{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
},
|
|
expected: v1alpha1.CredentialIssuerStatus{
|
|
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
|
{
|
|
Type: "Type0",
|
|
Status: v1alpha1.ErrorStrategyStatus,
|
|
Reason: "some starting reason 0",
|
|
Message: "some starting message 0",
|
|
LastUpdateTime: t2,
|
|
},
|
|
// Expect the Type1 entry to be sorted alphanumerically between the existing entries.
|
|
{
|
|
Type: "Type1",
|
|
Status: v1alpha1.SuccessStrategyStatus,
|
|
Reason: "some reason",
|
|
Message: "some message",
|
|
LastUpdateTime: t1,
|
|
},
|
|
{
|
|
Type: "Type2",
|
|
Status: v1alpha1.ErrorStrategyStatus,
|
|
Reason: "some starting reason 0",
|
|
Message: "some starting message 0",
|
|
LastUpdateTime: t2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
updated := tt.configToUpdate.DeepCopy()
|
|
mergeStrategy(updated, tt.strategy)
|
|
require.Equal(t, &tt.expected, updated)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStrategySorting(t *testing.T) {
|
|
expected := []v1alpha1.CredentialIssuerStrategy{
|
|
{Type: v1alpha1.KubeClusterSigningCertificateStrategyType},
|
|
{Type: v1alpha1.ImpersonationProxyStrategyType},
|
|
{Type: "Type1"},
|
|
{Type: "Type2"},
|
|
{Type: "Type3"},
|
|
}
|
|
require.NoError(t, quick.Check(func(seed int64) bool {
|
|
// Create a randomly shuffled copy of the expected output.
|
|
//nolint:gosec // this is not meant to be a secure random, just a seeded RNG for shuffling deterministically
|
|
rng := rand.New(rand.NewSource(seed))
|
|
output := make([]v1alpha1.CredentialIssuerStrategy, len(expected))
|
|
copy(output, expected)
|
|
rng.Shuffle(
|
|
len(output),
|
|
func(i, j int) { output[i], output[j] = output[j], output[i] },
|
|
)
|
|
|
|
// Sort it using the code under test.
|
|
sort.Stable(sortableStrategies(output))
|
|
|
|
// Assert that it's sorted back to the expected output order.
|
|
return assert.Equal(t, expected, output)
|
|
}, nil))
|
|
}
|