2023-06-05 21:40:39 +00:00
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
2020-10-09 00:40:58 +00:00
// SPDX-License-Identifier: Apache-2.0
package supervisorconfig
import (
"context"
2020-10-09 14:39:17 +00:00
"errors"
2021-02-05 17:56:05 +00:00
"fmt"
2020-10-23 23:25:44 +00:00
"net/url"
2023-07-07 21:10:07 +00:00
"sort"
2020-10-09 00:40:58 +00:00
"testing"
"time"
"github.com/stretchr/testify/require"
2023-07-05 20:33:21 +00:00
corev1 "k8s.io/api/core/v1"
2020-10-09 00:40:58 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020-10-09 14:39:17 +00:00
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
coretesting "k8s.io/client-go/testing"
2021-12-10 22:22:36 +00:00
clocktesting "k8s.io/utils/clock/testing"
2023-07-10 21:09:19 +00:00
"k8s.io/utils/pointer"
2020-10-09 00:40:58 +00:00
2023-07-05 20:33:21 +00:00
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
idpv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
2021-02-16 19:00:08 +00:00
pinnipedfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
pinnipedinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions"
2020-10-09 00:40:58 +00:00
"go.pinniped.dev/internal/controllerlib"
2023-06-22 22:12:33 +00:00
"go.pinniped.dev/internal/federationdomain/federationdomainproviders"
2023-07-07 21:10:07 +00:00
"go.pinniped.dev/internal/idtransform"
2020-10-09 00:40:58 +00:00
"go.pinniped.dev/internal/testutil"
)
2023-07-05 20:33:21 +00:00
func TestFederationDomainWatcherControllerInformerFilters ( t * testing . T ) {
t . Parallel ( )
federationDomainInformer := pinnipedinformers . NewSharedInformerFactoryWithOptions ( nil , 0 ) . Config ( ) . V1alpha1 ( ) . FederationDomains ( )
oidcIdentityProviderInformer := pinnipedinformers . NewSharedInformerFactoryWithOptions ( nil , 0 ) . IDP ( ) . V1alpha1 ( ) . OIDCIdentityProviders ( )
ldapIdentityProviderInformer := pinnipedinformers . NewSharedInformerFactoryWithOptions ( nil , 0 ) . IDP ( ) . V1alpha1 ( ) . LDAPIdentityProviders ( )
adIdentityProviderInformer := pinnipedinformers . NewSharedInformerFactoryWithOptions ( nil , 0 ) . IDP ( ) . V1alpha1 ( ) . ActiveDirectoryIdentityProviders ( )
tests := [ ] struct {
name string
obj metav1 . Object
informer controllerlib . InformerGetter
wantAdd bool
wantUpdate bool
wantDelete bool
} {
{
name : "any FederationDomain changes" ,
obj : & configv1alpha1 . FederationDomain { } ,
informer : federationDomainInformer ,
wantAdd : true ,
wantUpdate : true ,
wantDelete : true ,
} ,
{
name : "any OIDCIdentityProvider adds or deletes, but updates are ignored" ,
obj : & idpv1alpha1 . OIDCIdentityProvider { } ,
informer : oidcIdentityProviderInformer ,
wantAdd : true ,
wantUpdate : false ,
wantDelete : true ,
} ,
{
name : "any LDAPIdentityProvider adds or deletes, but updates are ignored" ,
obj : & idpv1alpha1 . LDAPIdentityProvider { } ,
informer : ldapIdentityProviderInformer ,
wantAdd : true ,
wantUpdate : false ,
wantDelete : true ,
} ,
{
name : "any ActiveDirectoryIdentityProvider adds or deletes, but updates are ignored" ,
obj : & idpv1alpha1 . ActiveDirectoryIdentityProvider { } ,
informer : adIdentityProviderInformer ,
wantAdd : true ,
wantUpdate : false ,
wantDelete : true ,
} ,
}
for _ , test := range tests {
test := test
t . Run ( test . name , func ( t * testing . T ) {
t . Parallel ( )
withInformer := testutil . NewObservableWithInformerOption ( )
NewFederationDomainWatcherController (
2020-10-09 00:40:58 +00:00
nil ,
nil ,
nil ,
2020-12-17 19:34:49 +00:00
federationDomainInformer ,
2023-06-05 21:40:39 +00:00
oidcIdentityProviderInformer ,
ldapIdentityProviderInformer ,
adIdentityProviderInformer ,
2023-07-05 20:33:21 +00:00
withInformer . WithInformer , // make it possible to observe the behavior of the Filters
2020-10-09 00:40:58 +00:00
)
2023-07-05 20:33:21 +00:00
unrelatedObj := corev1 . Secret { }
filter := withInformer . GetFilterForInformer ( test . informer )
require . Equal ( t , test . wantAdd , filter . Add ( test . obj ) )
require . Equal ( t , test . wantUpdate , filter . Update ( & unrelatedObj , test . obj ) )
require . Equal ( t , test . wantUpdate , filter . Update ( test . obj , & unrelatedObj ) )
require . Equal ( t , test . wantDelete , filter . Delete ( test . obj ) )
2020-10-09 00:40:58 +00:00
} )
2023-07-05 20:33:21 +00:00
}
2020-10-09 00:40:58 +00:00
}
2023-06-13 21:20:39 +00:00
type fakeFederationDomainsSetter struct {
SetFederationDomainsWasCalled bool
2023-06-22 20:12:50 +00:00
FederationDomainsReceived [ ] * federationdomainproviders . FederationDomainIssuer
2020-10-09 00:40:58 +00:00
}
2023-06-22 20:12:50 +00:00
func ( f * fakeFederationDomainsSetter ) SetFederationDomains ( federationDomains ... * federationdomainproviders . FederationDomainIssuer ) {
2023-06-13 21:20:39 +00:00
f . SetFederationDomainsWasCalled = true
2020-12-16 22:27:09 +00:00
f . FederationDomainsReceived = federationDomains
2020-10-09 00:40:58 +00:00
}
2023-07-05 20:33:21 +00:00
func TestTestFederationDomainWatcherControllerSync ( t * testing . T ) {
2023-07-06 00:41:27 +00:00
t . Parallel ( )
2020-10-09 00:40:58 +00:00
2023-07-06 00:41:27 +00:00
const namespace = "some-namespace"
2023-07-10 21:09:19 +00:00
const apiGroupSupervisor = "idp.supervisor.pinniped.dev"
2020-10-09 00:40:58 +00:00
2023-07-06 00:41:27 +00:00
frozenNow := time . Date ( 2020 , time . September , 23 , 7 , 42 , 0 , 0 , time . Local )
frozenMetav1Now := metav1 . NewTime ( frozenNow )
2020-10-09 00:40:58 +00:00
2023-07-06 00:41:27 +00:00
federationDomainGVR := schema . GroupVersionResource {
Group : configv1alpha1 . SchemeGroupVersion . Group ,
Version : configv1alpha1 . SchemeGroupVersion . Version ,
Resource : "federationdomains" ,
}
2020-10-09 00:40:58 +00:00
2023-07-10 21:09:19 +00:00
identityProvider1 := & idpv1alpha1 . OIDCIdentityProvider {
2023-07-07 21:10:07 +00:00
ObjectMeta : metav1 . ObjectMeta {
2023-07-10 21:09:19 +00:00
Name : "some-name1" ,
UID : "some-uid1" ,
} ,
}
identityProvider2 := & idpv1alpha1 . OIDCIdentityProvider {
ObjectMeta : metav1 . ObjectMeta {
Name : "some-name2" ,
UID : "some-uid2" ,
2023-07-07 21:10:07 +00:00
} ,
}
2023-07-06 00:41:27 +00:00
federationDomain1 := & configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "config1" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://issuer1.com" } ,
}
2020-10-09 00:40:58 +00:00
2023-07-06 00:41:27 +00:00
federationDomain2 := & configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "config2" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://issuer2.com" } ,
}
2020-10-09 14:39:17 +00:00
2023-07-06 00:41:27 +00:00
invalidFederationDomain := & configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "invalid-config" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://invalid-issuer.com?some=query" } ,
}
2023-06-30 20:43:40 +00:00
2023-07-07 21:10:07 +00:00
federationDomainIssuerWithDefaultIDP := func ( t * testing . T , fedDomainIssuer string , idpObjectMeta metav1 . ObjectMeta ) * federationdomainproviders . FederationDomainIssuer {
fdIDP := & federationdomainproviders . FederationDomainIdentityProvider {
DisplayName : idpObjectMeta . Name ,
UID : idpObjectMeta . UID ,
Transforms : idtransform . NewTransformationPipeline ( ) ,
}
fdIssuer , err := federationdomainproviders . NewFederationDomainIssuerWithDefaultIDP ( fedDomainIssuer , fdIDP )
require . NoError ( t , err )
return fdIssuer
}
2023-07-06 00:41:27 +00:00
happyReadyCondition := func ( issuer string , time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "Ready" ,
Status : "True" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "Success" ,
Message : fmt . Sprintf ( "the FederationDomain is ready and its endpoints are available: " +
"the discovery endpoint is %s/.well-known/openid-configuration" , issuer ) ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
sadReadyCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "Ready" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "NotReady" ,
Message : "the FederationDomain is not ready: see other conditions for details" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
happyIssuerIsUniqueCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IssuerIsUnique" ,
Status : "True" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "Success" ,
Message : "spec.issuer is unique among all FederationDomains" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
unknownIssuerIsUniqueCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IssuerIsUnique" ,
Status : "Unknown" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "UnableToValidate" ,
Message : "unable to check if spec.issuer is unique among all FederationDomains because URL cannot be parsed" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
sadIssuerIsUniqueCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IssuerIsUnique" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "DuplicateIssuer" ,
Message : "multiple FederationDomains have the same spec.issuer URL: these URLs must be unique (can use different hosts or paths)" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
happyOneTLSSecretPerIssuerHostnameCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "OneTLSSecretPerIssuerHostname" ,
Status : "True" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "Success" ,
Message : "all FederationDomains are using the same TLS secret when using the same hostname in the spec.issuer URL" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
unknownOneTLSSecretPerIssuerHostnameCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "OneTLSSecretPerIssuerHostname" ,
Status : "Unknown" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "UnableToValidate" ,
Message : "unable to check if all FederationDomains are using the same TLS secret when using the same hostname in the spec.issuer URL because URL cannot be parsed" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
sadOneTLSSecretPerIssuerHostnameCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "OneTLSSecretPerIssuerHostname" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "DifferentSecretRefsFound" ,
Message : "when different FederationDomains are using the same hostname in the spec.issuer URL then they must also use the same TLS secretRef: different secretRefs found" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
happyIssuerURLValidCondition := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IssuerURLValid" ,
Status : "True" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "Success" ,
Message : "spec.issuer is a valid URL" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
sadIssuerURLValidConditionCannotHaveQuery := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IssuerURLValid" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "InvalidIssuerURL" ,
Message : "issuer must not have query" ,
}
}
2023-06-30 20:43:40 +00:00
2023-07-06 00:41:27 +00:00
sadIssuerURLValidConditionCannotParse := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IssuerURLValid" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "InvalidIssuerURL" ,
Message : ` could not parse issuer as URL: parse ":/host//path": missing protocol scheme ` ,
}
}
2020-10-09 00:40:58 +00:00
2023-07-07 21:10:07 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess := func ( idpName string , time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IdentityProvidersFound" ,
Status : "True" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "LegacyConfigurationSuccess" ,
Message : fmt . Sprintf ( "no resources were specified by .spec.identityProviders[].objectRef but exactly one " +
"identity provider resource has been found: using %q as " +
"identity provider: please explicitly list identity providers in .spec.identityProviders " +
"(this legacy configuration mode may be removed in a future version of Pinniped)" , idpName ) ,
}
}
2023-07-10 21:09:19 +00:00
sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound := func ( time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IdentityProvidersFound" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "LegacyConfigurationIdentityProviderNotFound" ,
Message : "no resources were specified by .spec.identityProviders[].objectRef and no identity provider " +
"resources have been found: please create an identity provider resource" ,
}
}
sadIdentityProvidersFoundConditionIdentityProviderNotSpecified := func ( idpCRsCount int , time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IdentityProvidersFound" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "IdentityProviderNotSpecified" ,
Message : fmt . Sprintf ( "no resources were specified by .spec.identityProviders[].objectRef " +
"and %q identity provider resources have been found: " +
"please update .spec.identityProviders to specify which identity providers " +
"this federation domain should use" , idpCRsCount ) ,
}
}
sadIdentityProvidersFoundConditionIdentityProvidersObjectRefsNotFound := func ( msg string , time metav1 . Time , observedGeneration int64 ) configv1alpha1 . Condition {
return configv1alpha1 . Condition {
Type : "IdentityProvidersFound" ,
Status : "False" ,
ObservedGeneration : observedGeneration ,
LastTransitionTime : time ,
Reason : "IdentityProvidersObjectRefsNotFound" ,
Message : msg ,
}
}
2023-07-07 21:10:07 +00:00
allHappyConditionsLegacyConfigurationSuccess := func ( issuer , idpName string , time metav1 . Time , observedGeneration int64 ) [ ] configv1alpha1 . Condition {
2023-07-06 00:41:27 +00:00
return [ ] configv1alpha1 . Condition {
2023-07-07 21:10:07 +00:00
// sorted alphabetically by type
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( idpName , time , observedGeneration ) ,
2023-07-06 00:41:27 +00:00
happyIssuerIsUniqueCondition ( time , observedGeneration ) ,
happyIssuerURLValidCondition ( time , observedGeneration ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( time , observedGeneration ) ,
happyReadyCondition ( issuer , time , observedGeneration ) ,
}
}
2020-10-09 00:40:58 +00:00
2023-07-06 00:41:27 +00:00
invalidIssuerURL := ":/host//path"
2023-07-07 21:10:07 +00:00
_ , err := url . Parse ( invalidIssuerURL ) //nolint:staticcheck // Yes, this URL is intentionally invalid.
2023-07-06 00:41:27 +00:00
require . Error ( t , err )
newCopyWithStatus := func (
fd * configv1alpha1 . FederationDomain ,
phase configv1alpha1 . FederationDomainPhase ,
conditions [ ] configv1alpha1 . Condition ,
) * configv1alpha1 . FederationDomain {
fdCopy := fd . DeepCopy ( )
fdCopy . Status . Phase = phase
fdCopy . Status . Conditions = conditions
return fdCopy
}
2020-10-09 14:39:17 +00:00
2023-07-06 00:41:27 +00:00
tests := [ ] struct {
name string
inputObjects [ ] runtime . Object
configPinnipedClient func ( * pinnipedfake . Clientset )
wantErr string
wantActions func ( t * testing . T ) [ ] coretesting . Action
wantFederationDomainIssuers func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer
} {
{
2023-07-07 21:10:07 +00:00
name : "when there are no FederationDomains, nothing happens" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object { } ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer { }
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action { }
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "legacy config: when no identity provider is specified on federation domains, but exactly one identity " +
"provider resource exists on cluster, the controller will set a default IDP on each federation domain " +
"matching the only identity provider found" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
federationDomain1 ,
federationDomain2 ,
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , federationDomain1 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
federationDomainIssuerWithDefaultIDP ( t , federationDomain2 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain1 . Namespace ,
newCopyWithStatus ( federationDomain1 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain1 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
) ,
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus ( federationDomain2 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain2 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
) ,
2020-10-09 00:40:58 +00:00
}
2023-07-06 00:41:27 +00:00
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "when there are two valid FederationDomains, but one is already up to date, the sync loop only updates " +
"the out-of-date FederationDomain" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
newCopyWithStatus ( federationDomain1 , configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain1 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
federationDomain2 ,
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , federationDomain1 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
federationDomainIssuerWithDefaultIDP ( t , federationDomain2 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus ( federationDomain2 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain2 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
) ,
2020-10-09 00:40:58 +00:00
}
2023-07-06 00:41:27 +00:00
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "when there are two valid FederationDomains, but updating one fails, the status on the FederationDomain will not change" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
federationDomain1 ,
federationDomain2 ,
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
} ,
configPinnipedClient : func ( client * pinnipedfake . Clientset ) {
client . PrependReactor (
"update" ,
"federationdomains" ,
func ( action coretesting . Action ) ( bool , runtime . Object , error ) {
fd := action . ( coretesting . UpdateAction ) . GetObject ( ) . ( * configv1alpha1 . FederationDomain )
if fd . Name == federationDomain1 . Name {
return true , nil , errors . New ( "some update error" )
}
return false , nil , nil
2020-10-09 14:39:17 +00:00
} ,
)
2023-07-06 00:41:27 +00:00
} ,
wantErr : "could not update status: some update error" ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-07 21:10:07 +00:00
// federationDomain1 is not included because it encountered an error
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , federationDomain2 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain1 . Namespace ,
newCopyWithStatus ( federationDomain1 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain1 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
2020-10-09 14:39:17 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus ( federationDomain2 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain2 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
2020-10-09 14:39:17 +00:00
) ,
}
2023-07-06 00:41:27 +00:00
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "when there are both valid and invalid FederationDomains, the status will be correctly set on each " +
"FederationDomain individually" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
invalidFederationDomain ,
federationDomain2 ,
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-07 21:10:07 +00:00
// only the valid FederationDomain
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , federationDomain2 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus ( invalidFederationDomain ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
sadIssuerURLValidConditionCannotHaveQuery ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
2020-10-09 14:39:17 +00:00
) ,
2023-07-06 00:41:27 +00:00
) ,
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus ( federationDomain2 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain2 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2020-10-09 14:39:17 +00:00
) ,
2023-07-06 00:41:27 +00:00
) ,
2020-10-09 14:39:17 +00:00
}
2023-07-06 00:41:27 +00:00
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "when there are both valid and invalid FederationDomains, but updating the invalid one fails, the " +
"existing status will be unchanged" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
invalidFederationDomain ,
federationDomain2 ,
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
} ,
configPinnipedClient : func ( client * pinnipedfake . Clientset ) {
client . PrependReactor (
"update" ,
"federationdomains" ,
func ( action coretesting . Action ) ( bool , runtime . Object , error ) {
fd := action . ( coretesting . UpdateAction ) . GetObject ( ) . ( * configv1alpha1 . FederationDomain )
if fd . Name == invalidFederationDomain . Name {
2020-10-09 14:39:17 +00:00
return true , nil , errors . New ( "some update error" )
2023-07-06 00:41:27 +00:00
}
return false , nil , nil
2020-10-09 14:39:17 +00:00
} ,
)
2023-07-06 00:41:27 +00:00
} ,
wantErr : "could not update status: some update error" ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-07 21:10:07 +00:00
// only the valid FederationDomain
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , federationDomain2 . Spec . Issuer , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus ( invalidFederationDomain ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
sadIssuerURLValidConditionCannotHaveQuery ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
2020-10-09 14:39:17 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus ( federationDomain2 ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( federationDomain2 . Spec . Issuer , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
2020-10-09 14:39:17 +00:00
) ,
}
2023-07-06 00:41:27 +00:00
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "when there are FederationDomains with duplicate issuer strings these particular FederationDomains " +
"will report error on IssuerUnique conditions" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "duplicate1" , Namespace : namespace , Generation : 123 } ,
2023-07-05 20:33:21 +00:00
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://iSSueR-duPlicAte.cOm/a" } ,
2023-07-06 00:41:27 +00:00
} ,
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "duplicate2" , Namespace : namespace , Generation : 123 } ,
2023-07-05 20:33:21 +00:00
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://issuer-duplicate.com/a" } ,
2023-07-06 00:41:27 +00:00
} ,
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "not-duplicate" , Namespace : namespace , Generation : 123 } ,
2023-07-06 00:41:27 +00:00
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://issuer-duplicate.com/A" } , // different path (paths are case-sensitive)
} ,
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-07 21:10:07 +00:00
// different path (paths are case-sensitive)
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , "https://issuer-duplicate.com/A" , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "duplicate1" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://iSSueR-duPlicAte.cOm/a" } ,
} ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
sadIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
2020-10-09 14:39:17 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "duplicate2" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://issuer-duplicate.com/a" } ,
} ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
sadIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
2020-10-09 14:39:17 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "not-duplicate" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec { Issuer : "https://issuer-duplicate.com/A" } ,
} ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( "https://issuer-duplicate.com/A" , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
) ,
2020-10-09 14:39:17 +00:00
) ,
}
2023-07-06 00:41:27 +00:00
} ,
} ,
{
2023-07-07 21:10:07 +00:00
name : "when there are FederationDomains with the same issuer DNS hostname using different secretNames these " +
"particular FederationDomains will report errors on OneTLSSecretPerIssuerHostname conditions" ,
2023-07-06 00:41:27 +00:00
inputObjects : [ ] runtime . Object {
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "fd1" , Namespace : namespace , Generation : 123 } ,
2023-07-05 20:33:21 +00:00
Spec : configv1alpha1 . FederationDomainSpec {
2020-11-02 22:55:29 +00:00
Issuer : "https://iSSueR-duPlicAte-adDress.cOm/path1" ,
2023-07-05 20:33:21 +00:00
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret1" } ,
2020-10-23 23:25:44 +00:00
} ,
2023-07-06 00:41:27 +00:00
} ,
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "fd2" , Namespace : namespace , Generation : 123 } ,
2023-07-05 20:33:21 +00:00
Spec : configv1alpha1 . FederationDomainSpec {
2020-10-27 00:03:26 +00:00
// Validation treats these as the same DNS hostname even though they have different port numbers,
// because SNI information on the incoming requests is not going to include port numbers.
2020-11-02 22:55:29 +00:00
Issuer : "https://issuer-duplicate-address.com:1234/path2" ,
2023-07-05 20:33:21 +00:00
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret2" } ,
2020-10-23 23:25:44 +00:00
} ,
2023-07-06 00:41:27 +00:00
} ,
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "differentIssuerAddressFederationDomain" , Namespace : namespace , Generation : 123 } ,
2023-07-05 20:33:21 +00:00
Spec : configv1alpha1 . FederationDomainSpec {
2020-11-02 22:55:29 +00:00
Issuer : "https://issuer-not-duplicate.com" ,
2023-07-05 20:33:21 +00:00
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret1" } ,
2020-10-23 23:25:44 +00:00
} ,
2023-07-06 00:41:27 +00:00
} ,
& configv1alpha1 . FederationDomain {
2023-06-30 20:43:40 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "invalidIssuerURLFederationDomain" , Namespace : namespace , Generation : 123 } ,
2023-07-05 20:33:21 +00:00
Spec : configv1alpha1 . FederationDomainSpec {
2020-11-02 22:55:29 +00:00
Issuer : invalidIssuerURL ,
2023-07-05 20:33:21 +00:00
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret1" } ,
2020-10-23 23:25:44 +00:00
} ,
2023-07-06 00:41:27 +00:00
} ,
2023-07-10 21:09:19 +00:00
identityProvider1 ,
2023-07-06 00:41:27 +00:00
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer {
2023-07-10 21:09:19 +00:00
federationDomainIssuerWithDefaultIDP ( t , "https://issuer-not-duplicate.com" , identityProvider1 . ObjectMeta ) ,
2023-07-06 00:41:27 +00:00
}
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "fd1" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec {
Issuer : "https://iSSueR-duPlicAte-adDress.cOm/path1" ,
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret1" } ,
} ,
} ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
sadOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
2020-10-23 23:25:44 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "fd2" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec {
Issuer : "https://issuer-duplicate-address.com:1234/path2" ,
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret2" } ,
} ,
} ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
sadOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
2020-10-23 23:25:44 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , invalidFederationDomain . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "invalidIssuerURLFederationDomain" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec {
Issuer : invalidIssuerURL ,
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret1" } ,
} ,
} ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
2023-07-10 21:09:19 +00:00
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess ( identityProvider1 . Name , frozenMetav1Now , 123 ) ,
2023-07-06 00:41:27 +00:00
unknownIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
sadIssuerURLValidConditionCannotParse ( frozenMetav1Now , 123 ) ,
unknownOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
2020-10-23 23:25:44 +00:00
) ,
2023-07-06 00:41:27 +00:00
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "differentIssuerAddressFederationDomain" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec {
Issuer : "https://issuer-not-duplicate.com" ,
TLS : & configv1alpha1 . FederationDomainTLSSpec { SecretName : "secret1" } ,
} ,
} ,
configv1alpha1 . FederationDomainPhaseReady ,
2023-07-10 21:09:19 +00:00
allHappyConditionsLegacyConfigurationSuccess ( "https://issuer-not-duplicate.com" , identityProvider1 . Name , frozenMetav1Now , 123 ) ,
) ,
) ,
}
} ,
} ,
{
name : "legacy config: no identity provider specified in federation domain and no identity providers found results in not found status" ,
inputObjects : [ ] runtime . Object {
federationDomain1 ,
federationDomain2 ,
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer { }
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain1 . Namespace ,
newCopyWithStatus ( federationDomain1 ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound ( frozenMetav1Now , 123 ) ,
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
) ,
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain2 . Namespace ,
newCopyWithStatus ( federationDomain2 ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound ( frozenMetav1Now , 123 ) ,
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
) ,
}
} ,
} ,
{
name : "legacy config: no identity provider specified in federation domain and multiple identity providers found results in not specified status" ,
inputObjects : [ ] runtime . Object {
federationDomain1 ,
identityProvider1 ,
identityProvider2 ,
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer { }
} ,
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , federationDomain1 . Namespace ,
newCopyWithStatus ( federationDomain1 ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
sadIdentityProvidersFoundConditionIdentityProviderNotSpecified ( 2 , frozenMetav1Now , 123 ) ,
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
) ,
) ,
}
} ,
} ,
{
name : "the federation domain specifies identity providers that cannot be found" ,
inputObjects : [ ] runtime . Object {
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "config1" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec {
Issuer : "https://issuer1.com" ,
IdentityProviders : [ ] configv1alpha1 . FederationDomainIdentityProvider {
{
DisplayName : "cant-find-me" ,
ObjectRef : corev1 . TypedLocalObjectReference {
APIGroup : pointer . String ( apiGroupSupervisor ) ,
Kind : "OIDCIdentityProvider" ,
Name : "cant-find-me" ,
} ,
} ,
} ,
} ,
} ,
} ,
wantFederationDomainIssuers : func ( t * testing . T ) [ ] * federationdomainproviders . FederationDomainIssuer {
return [ ] * federationdomainproviders . FederationDomainIssuer { }
} ,
// TODO: sketch out a way to eliminate the whole wantActions and be more precise
// if not wantActions, might wantStatusUpdate?
// wantStatusUpdate: func(t *testing.T, []configv1alpha1.FederationDomain) {
// {
// Name: "foo",
// Namespace: "bar",
// Phase: "Happy",
// Conditions: []metav1.Condition{},
// }
// },
wantActions : func ( t * testing . T ) [ ] coretesting . Action {
return [ ] coretesting . Action {
coretesting . NewUpdateSubresourceAction ( federationDomainGVR , "status" , namespace ,
newCopyWithStatus (
& configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta { Name : "config1" , Namespace : namespace , Generation : 123 } ,
Spec : configv1alpha1 . FederationDomainSpec {
Issuer : "https://issuer1.com" ,
IdentityProviders : [ ] configv1alpha1 . FederationDomainIdentityProvider {
{
DisplayName : "cant-find-me" ,
ObjectRef : corev1 . TypedLocalObjectReference {
APIGroup : pointer . String ( apiGroupSupervisor ) ,
Kind : "OIDCIdentityProvider" ,
Name : "cant-find-me" ,
} ,
} ,
} ,
} ,
} ,
configv1alpha1 . FederationDomainPhaseError ,
[ ] configv1alpha1 . Condition {
sadIdentityProvidersFoundConditionIdentityProvidersObjectRefsNotFound (
` .spec.identityProviders[].objectRef identifies resource(s) that cannot be found: ` +
` IDP with displayName "cant-find-me" at index 0 ` , frozenMetav1Now , 123 ) ,
happyIssuerIsUniqueCondition ( frozenMetav1Now , 123 ) ,
happyIssuerURLValidCondition ( frozenMetav1Now , 123 ) ,
happyOneTLSSecretPerIssuerHostnameCondition ( frozenMetav1Now , 123 ) ,
sadReadyCondition ( frozenMetav1Now , 123 ) ,
} ,
2023-07-06 00:41:27 +00:00
) ,
2020-10-23 23:25:44 +00:00
) ,
}
2023-07-06 00:41:27 +00:00
} ,
} ,
2023-07-07 21:10:07 +00:00
// {
2023-07-10 21:09:19 +00:00
// name: "the federation domain specifies identity providers that exist",
2023-07-07 21:10:07 +00:00
// wantErr: "", // n/a
// },
2023-07-06 00:41:27 +00:00
}
2020-10-23 23:25:44 +00:00
2023-07-06 00:41:27 +00:00
for _ , tt := range tests {
tt := tt
t . Run ( tt . name , func ( t * testing . T ) {
t . Parallel ( )
federationDomainsSetter := & fakeFederationDomainsSetter { }
pinnipedAPIClient := pinnipedfake . NewSimpleClientset ( )
pinnipedInformerClient := pinnipedfake . NewSimpleClientset ( )
for _ , o := range tt . inputObjects {
require . NoError ( t , pinnipedAPIClient . Tracker ( ) . Add ( o ) )
require . NoError ( t , pinnipedInformerClient . Tracker ( ) . Add ( o ) )
}
if tt . configPinnipedClient != nil {
tt . configPinnipedClient ( pinnipedAPIClient )
}
pinnipedInformers := pinnipedinformers . NewSharedInformerFactory ( pinnipedInformerClient , 0 )
controller := NewFederationDomainWatcherController (
federationDomainsSetter ,
clocktesting . NewFakeClock ( frozenNow ) ,
pinnipedAPIClient ,
pinnipedInformers . Config ( ) . V1alpha1 ( ) . FederationDomains ( ) ,
pinnipedInformers . IDP ( ) . V1alpha1 ( ) . OIDCIdentityProviders ( ) ,
pinnipedInformers . IDP ( ) . V1alpha1 ( ) . LDAPIdentityProviders ( ) ,
pinnipedInformers . IDP ( ) . V1alpha1 ( ) . ActiveDirectoryIdentityProviders ( ) ,
controllerlib . WithInformer ,
)
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
pinnipedInformers . Start ( ctx . Done ( ) )
controllerlib . TestRunSynchronously ( t , controller )
syncCtx := controllerlib . Context { Context : ctx , Key : controllerlib . Key { Namespace : namespace , Name : "config-name" } }
if err := controllerlib . TestSync ( t , controller , syncCtx ) ; tt . wantErr != "" {
require . EqualError ( t , err , tt . wantErr )
} else {
require . NoError ( t , err )
}
if tt . wantFederationDomainIssuers != nil {
require . True ( t , federationDomainsSetter . SetFederationDomainsWasCalled )
require . ElementsMatch ( t , tt . wantFederationDomainIssuers ( t ) , federationDomainsSetter . FederationDomainsReceived )
} else {
require . False ( t , federationDomainsSetter . SetFederationDomainsWasCalled )
}
2023-07-07 21:10:07 +00:00
if tt . wantActions != nil {
// In this controller we don't actually care about the order of the actions, the FederationDomains
// can be updated in any order. Therefore, we are sorting here to make the test output easier to read.
// Unfortunately the timezone nested in the condition still makes it pretty ugly.
actualActions := pinnipedAPIClient . Actions ( )
sortActions ( t , actualActions )
wantedActions := tt . wantActions ( t )
sortActions ( t , wantedActions )
require . Equal ( t , wantedActions , actualActions )
} else {
require . Empty ( t , pinnipedAPIClient . Actions ( ) )
}
2020-10-09 00:40:58 +00:00
} )
2023-07-06 00:41:27 +00:00
}
2020-10-09 00:40:58 +00:00
}
2023-07-07 21:10:07 +00:00
func sortActions ( t * testing . T , actions [ ] coretesting . Action ) {
sort . SliceStable ( actions , func ( prev , next int ) bool {
updateAction1 , ok := actions [ prev ] . ( coretesting . UpdateAction )
require . True ( t , ok , "failed to cast an action as an coretesting.UpdateAction for sort comparison %#v" , actions [ prev ] )
obj1 , ok := updateAction1 . GetObject ( ) . ( metav1 . Object )
require . True ( t , ok , "failed to cast an action as a metav1.Object for sort comparison %#v" , actions [ prev ] )
updateAction2 , ok := actions [ next ] . ( coretesting . UpdateAction )
require . True ( t , ok , "failed to cast an action as an coretesting.UpdateAction for sort comparison %#v" , actions [ next ] )
obj2 , ok := updateAction2 . GetObject ( ) . ( metav1 . Object )
require . True ( t , ok , "failed to cast an action as a metav1.Object for sort comparison %#v" , actions [ next ] )
return obj1 . GetName ( ) < obj2 . GetName ( )
} )
}