diff --git a/internal/controller/authenticator/jwtcachefiller/jwtcachefiller_test.go b/internal/controller/authenticator/jwtcachefiller/jwtcachefiller_test.go index 7b0a01ffe..3f3d7b408 100644 --- a/internal/controller/authenticator/jwtcachefiller/jwtcachefiller_test.go +++ b/internal/controller/authenticator/jwtcachefiller/jwtcachefiller_test.go @@ -17,7 +17,6 @@ import ( "fmt" "net/http" "net/url" - "sort" "strings" "testing" "time" @@ -42,6 +41,7 @@ import ( "go.pinniped.dev/internal/mocks/mocktokenauthenticatorcloser" "go.pinniped.dev/internal/plog" "go.pinniped.dev/internal/testutil" + "go.pinniped.dev/internal/testutil/status" "go.pinniped.dev/internal/testutil/tlsserver" ) @@ -446,31 +446,9 @@ func TestController(t *testing.T) { // } // sadJWKSURLValidResponse := func() metav1.Condition {} - // TODO: extract to a helper since copied from FederationDomain - sortConditionsByType := func(c []metav1.Condition) []metav1.Condition { - cp := make([]metav1.Condition, len(c)) - copy(cp, c) - sort.SliceStable(cp, func(i, j int) bool { - return cp[i].Type < cp[j].Type - }) - return cp - } - - replaceConditions := func(conditions []metav1.Condition, sadConditions []metav1.Condition) []metav1.Condition { - for _, sadReplaceCondition := range sadConditions { - for origIndex, origCondition := range conditions { - if origCondition.Type == sadReplaceCondition.Type { - conditions[origIndex] = sadReplaceCondition - break - } - } - } - return conditions - } - // condition collections allHappyConditionsSuccess := func(issuer string, time metav1.Time, observedGeneration int64) []metav1.Condition { - return sortConditionsByType([]metav1.Condition{ + return status.SortConditionsByType([]metav1.Condition{ happyAuthenticatorValid(time, observedGeneration), happyDiscoveryURLValid(time, observedGeneration), happyIssuerURLValid(issuer, time, observedGeneration), @@ -732,7 +710,7 @@ func TestController(t *testing.T) { }, // no explicit logs, this is an issue of config, the user must provide TLS config for the // custom cert provided for this server. - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(goodIssuer, frozenMetav1Now, 0), []metav1.Condition{ sadReadyCondition(frozenMetav1Now, 0), @@ -758,7 +736,7 @@ func TestController(t *testing.T) { }, // no explicit logs, this is an issue of config, the user must provide TLS config that // isn't incorrect due to mistyping or other issues - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(someOtherIssuer, frozenMetav1Now, 0), []metav1.Condition{ sadReadyCondition(frozenMetav1Now, 0), @@ -781,7 +759,7 @@ func TestController(t *testing.T) { }, }, syncKey: controllerlib.Key{Name: "test-name"}, - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(goodIssuer, frozenMetav1Now, 0), []metav1.Condition{ sadReadyCondition(frozenMetav1Now, 0), @@ -803,7 +781,7 @@ func TestController(t *testing.T) { }, }, syncKey: controllerlib.Key{Name: "test-name"}, - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(goodIssuer, frozenMetav1Now, 0), []metav1.Condition{ sadReadyCondition(frozenMetav1Now, 0), @@ -825,7 +803,7 @@ func TestController(t *testing.T) { }, }, syncKey: controllerlib.Key{Name: "test-name"}, - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(goodIssuer, frozenMetav1Now, 0), []metav1.Condition{ happyIssuerURLValid(someOtherLocalhostIssuer, frozenMetav1Now, 0), @@ -853,7 +831,7 @@ func TestController(t *testing.T) { }, }, syncKey: controllerlib.Key{Name: "test-name"}, - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(goodIssuer, frozenMetav1Now, 0), []metav1.Condition{ happyIssuerURLValid(badIssuerInvalidJWKSURI, frozenMetav1Now, 0), @@ -875,7 +853,7 @@ func TestController(t *testing.T) { }, }, syncKey: controllerlib.Key{Name: "test-name"}, - wantStatusConditions: replaceConditions( + wantStatusConditions: status.ReplaceConditions( allHappyConditionsSuccess(goodIssuer, frozenMetav1Now, 0), []metav1.Condition{ happyIssuerURLValid(badIssuerInvalidJWKSURIScheme, frozenMetav1Now, 0), diff --git a/internal/controller/supervisorconfig/federation_domain_watcher_test.go b/internal/controller/supervisorconfig/federation_domain_watcher_test.go index ba6055b58..57fe396e3 100644 --- a/internal/controller/supervisorconfig/federation_domain_watcher_test.go +++ b/internal/controller/supervisorconfig/federation_domain_watcher_test.go @@ -32,6 +32,7 @@ import ( "go.pinniped.dev/internal/here" "go.pinniped.dev/internal/idtransform" "go.pinniped.dev/internal/testutil" + "go.pinniped.dev/internal/testutil/status" ) func TestFederationDomainWatcherControllerInformerFilters(t *testing.T) { @@ -490,29 +491,8 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { } } - sortConditionsByType := func(c []metav1.Condition) []metav1.Condition { - cp := make([]metav1.Condition, len(c)) - copy(cp, c) - sort.SliceStable(cp, func(i, j int) bool { - return cp[i].Type < cp[j].Type - }) - return cp - } - - replaceConditions := func(conditions []metav1.Condition, sadConditions []metav1.Condition) []metav1.Condition { - for _, sadReplaceCondition := range sadConditions { - for origIndex, origCondition := range conditions { - if origCondition.Type == sadReplaceCondition.Type { - conditions[origIndex] = sadReplaceCondition - break - } - } - } - return conditions - } - allHappyConditionsSuccess := func(issuer string, time metav1.Time, observedGeneration int64) []metav1.Condition { - return sortConditionsByType([]metav1.Condition{ + return status.SortConditionsByType([]metav1.Condition{ happyTransformationExamplesCondition(frozenMetav1Now, 123), happyTransformationExpressionsCondition(frozenMetav1Now, 123), happyKindCondition(frozenMetav1Now, 123), @@ -527,7 +507,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { } allHappyConditionsLegacyConfigurationSuccess := func(issuer string, idpName string, time metav1.Time, observedGeneration int64) []metav1.Condition { - return replaceConditions( + return status.ReplaceConditions( allHappyConditionsSuccess(issuer, time, observedGeneration), []metav1.Condition{ happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(idpName, time, observedGeneration), @@ -736,7 +716,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { wantStatusUpdates: []*configv1alpha1.FederationDomain{ expectedFederationDomainStatusUpdate(invalidIssuerURLFederationDomain, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ sadIssuerURLValidConditionCannotHaveQuery(frozenMetav1Now, 123), @@ -778,7 +758,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { wantStatusUpdates: []*configv1alpha1.FederationDomain{ expectedFederationDomainStatusUpdate(invalidIssuerURLFederationDomain, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ sadIssuerURLValidConditionCannotHaveQuery(frozenMetav1Now, 123), @@ -818,7 +798,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "duplicate1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess("https://iSSueR-duPlicAte.cOm/a", oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ sadIssuerIsUniqueCondition(frozenMetav1Now, 123), @@ -830,7 +810,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "duplicate2", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess("https://issuer-duplicate.com/a", oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ sadIssuerIsUniqueCondition(frozenMetav1Now, 123), @@ -891,7 +871,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "fd1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess("https://iSSueR-duPlicAte-adDress.cOm/path1", oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ sadOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), @@ -903,7 +883,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "fd2", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess("https://issuer-duplicate-address.com:1234/path2", oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ sadOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), @@ -915,7 +895,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "invalidIssuerURLFederationDomain", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess(invalidIssuerURL, oidcIdentityProvider.Name, frozenMetav1Now, 123), []metav1.Condition{ unknownIssuerIsUniqueCondition(frozenMetav1Now, 123), @@ -943,7 +923,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { wantStatusUpdates: []*configv1alpha1.FederationDomain{ expectedFederationDomainStatusUpdate(federationDomain1, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, "", frozenMetav1Now, 123), []metav1.Condition{ sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound(frozenMetav1Now, 123), @@ -952,7 +932,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ), expectedFederationDomainStatusUpdate(federationDomain2, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, "", frozenMetav1Now, 123), []metav1.Condition{ sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound(frozenMetav1Now, 123), @@ -973,7 +953,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { wantStatusUpdates: []*configv1alpha1.FederationDomain{ expectedFederationDomainStatusUpdate(federationDomain1, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, "", frozenMetav1Now, 123), []metav1.Condition{ sadIdentityProvidersFoundConditionIdentityProviderNotSpecified(3, frozenMetav1Now, 123), @@ -1025,7 +1005,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadIdentityProvidersFoundConditionIdentityProvidersObjectRefsNotFound(here.Doc( @@ -1179,7 +1159,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadDisplayNamesUniqueCondition(`"duplicate1", "duplicate2"`, frozenMetav1Now, 123), @@ -1242,7 +1222,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadAPIGroupSuffixCondition(`"", "", "wrong.example.com"`, frozenMetav1Now, 123), @@ -1304,7 +1284,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadKindCondition(`"", "wrong"`, frozenMetav1Now, 123), @@ -1354,7 +1334,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadTransformationExpressionsCondition(here.Doc( @@ -1500,7 +1480,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadTransformationExamplesCondition(here.Doc( @@ -1599,7 +1579,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123), []metav1.Condition{ sadTransformationExamplesCondition(here.Doc( @@ -1746,7 +1726,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://not-unique.com", frozenMetav1Now, 123), []metav1.Condition{ sadAPIGroupSuffixCondition(`"this is wrong"`, frozenMetav1Now, 123), @@ -1806,7 +1786,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "config2", Namespace: namespace, Generation: 123}, }, configv1alpha1.FederationDomainPhaseError, - replaceConditions( + status.ReplaceConditions( allHappyConditionsSuccess("https://not-unique.com", frozenMetav1Now, 123), []metav1.Condition{ sadIssuerIsUniqueCondition(frozenMetav1Now, 123), diff --git a/internal/testutil/status/condition.go b/internal/testutil/status/condition.go new file mode 100644 index 000000000..4f7e1bb13 --- /dev/null +++ b/internal/testutil/status/condition.go @@ -0,0 +1,31 @@ +// Copyright 2024 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package status + +import ( + "sort" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func SortConditionsByType(c []metav1.Condition) []metav1.Condition { + cp := make([]metav1.Condition, len(c)) + copy(cp, c) + sort.SliceStable(cp, func(i, j int) bool { + return cp[i].Type < cp[j].Type + }) + return cp +} + +func ReplaceConditions(conditions []metav1.Condition, sadConditions []metav1.Condition) []metav1.Condition { + for _, sadReplaceCondition := range sadConditions { + for origIndex, origCondition := range conditions { + if origCondition.Type == sadReplaceCondition.Type { + conditions[origIndex] = sadReplaceCondition + break + } + } + } + return conditions +}