Refactor federation_domain_watcher_test.go and add new test to its table

This commit is contained in:
Ryan Richard 2023-07-10 15:41:48 -07:00
parent fe9364c58b
commit 97a374c00b
2 changed files with 392 additions and 405 deletions

View File

@ -402,15 +402,14 @@ func (c *federationDomainWatcherController) Sync(ctx controllerlib.Context) erro
Message: fmt.Sprintf(".spec.identityProviders[].objectRef identifies resource(s) that cannot be found: %s", strings.Join(msgs, ", ")), Message: fmt.Sprintf(".spec.identityProviders[].objectRef identifies resource(s) that cannot be found: %s", strings.Join(msgs, ", ")),
}) })
} else { } else {
// TODO: write tests for this case. if len(federationDomain.Spec.IdentityProviders) != 0 {
// if len(federationDomain.Spec.IdentityProviders) != 0 { conditions = append(conditions, &configv1alpha1.Condition{
// conditions = append(conditions, &configv1alpha1.Condition{ Type: typeIdentityProvidersFound,
// Type: typeIdentityProvidersFound, Status: configv1alpha1.ConditionTrue,
// Status: configv1alpha1.ConditionTrue, Reason: reasonSuccess,
// Reason: reasonSuccess, Message: "the resources specified by .spec.identityProviders[].objectRef were found",
// Message: "the resources specified by .spec.identityProviders[].objectRef were found", })
// }) }
// }
} }
// Now that we have the list of IDPs for this FederationDomain, create the issuer. // Now that we have the list of IDPs for this FederationDomain, create the issuer.
@ -450,10 +449,7 @@ func (c *federationDomainWatcherController) Sync(ctx controllerlib.Context) erro
federationDomainIssuers = append(federationDomainIssuers, federationDomainIssuer) federationDomainIssuers = append(federationDomainIssuers, federationDomainIssuer)
} }
} }
// BEN: notes:
// implementer of this function is the endpoint manager.
// it should re-setup all of the endpoints for the specified federation domains.
// (in test, this is wantFederationDomainIssues)
c.federationDomainsSetter.SetFederationDomains(federationDomainIssuers...) c.federationDomainsSetter.SetFederationDomains(federationDomainIssuers...)
return errorsutil.NewAggregate(errs) return errorsutil.NewAggregate(errs)

View File

@ -118,6 +118,12 @@ func (f *fakeFederationDomainsSetter) SetFederationDomains(federationDomains ...
f.FederationDomainsReceived = federationDomains f.FederationDomainsReceived = federationDomains
} }
var federationDomainGVR = schema.GroupVersionResource{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Resource: "federationdomains",
}
func TestTestFederationDomainWatcherControllerSync(t *testing.T) { func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
t.Parallel() t.Parallel()
@ -127,22 +133,18 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
frozenNow := time.Date(2020, time.September, 23, 7, 42, 0, 0, time.Local) frozenNow := time.Date(2020, time.September, 23, 7, 42, 0, 0, time.Local)
frozenMetav1Now := metav1.NewTime(frozenNow) frozenMetav1Now := metav1.NewTime(frozenNow)
federationDomainGVR := schema.GroupVersionResource{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Resource: "federationdomains",
}
identityProvider1 := &idpv1alpha1.OIDCIdentityProvider{ identityProvider1 := &idpv1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "some-name1", Name: "some-name1",
UID: "some-uid1", Namespace: namespace,
UID: "some-uid1",
}, },
} }
identityProvider2 := &idpv1alpha1.OIDCIdentityProvider{ identityProvider2 := &idpv1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "some-name2", Name: "some-name2",
UID: "some-uid2", Namespace: namespace,
UID: "some-uid2",
}, },
} }
@ -156,11 +158,17 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
Spec: configv1alpha1.FederationDomainSpec{Issuer: "https://issuer2.com"}, Spec: configv1alpha1.FederationDomainSpec{Issuer: "https://issuer2.com"},
} }
invalidFederationDomain := &configv1alpha1.FederationDomain{ invalidIssuerURLFederationDomain := &configv1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{Name: "invalid-config", Namespace: namespace, Generation: 123}, ObjectMeta: metav1.ObjectMeta{Name: "invalid-config", Namespace: namespace, Generation: 123},
Spec: configv1alpha1.FederationDomainSpec{Issuer: "https://invalid-issuer.com?some=query"}, Spec: configv1alpha1.FederationDomainSpec{Issuer: "https://invalid-issuer.com?some=query"},
} }
federationDomainIssuerWithIDPs := func(t *testing.T, fedDomainIssuer string, fdIDPs []*federationdomainproviders.FederationDomainIdentityProvider) *federationdomainproviders.FederationDomainIssuer {
fdIssuer, err := federationdomainproviders.NewFederationDomainIssuer(fedDomainIssuer, fdIDPs)
require.NoError(t, err)
return fdIssuer
}
federationDomainIssuerWithDefaultIDP := func(t *testing.T, fedDomainIssuer string, idpObjectMeta metav1.ObjectMeta) *federationdomainproviders.FederationDomainIssuer { federationDomainIssuerWithDefaultIDP := func(t *testing.T, fedDomainIssuer string, idpObjectMeta metav1.ObjectMeta) *federationdomainproviders.FederationDomainIssuer {
fdIDP := &federationdomainproviders.FederationDomainIdentityProvider{ fdIDP := &federationdomainproviders.FederationDomainIdentityProvider{
DisplayName: idpObjectMeta.Name, DisplayName: idpObjectMeta.Name,
@ -308,6 +316,17 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
} }
} }
happyIdentityProvidersFoundConditionSuccess := func(time metav1.Time, observedGeneration int64) configv1alpha1.Condition {
return configv1alpha1.Condition{
Type: "IdentityProvidersFound",
Status: "True",
ObservedGeneration: observedGeneration,
LastTransitionTime: time,
Reason: "Success",
Message: "the resources specified by .spec.identityProviders[].objectRef were found",
}
}
sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound := func(time metav1.Time, observedGeneration int64) configv1alpha1.Condition { sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound := func(time metav1.Time, observedGeneration int64) configv1alpha1.Condition {
return configv1alpha1.Condition{ return configv1alpha1.Condition{
Type: "IdentityProvidersFound", Type: "IdentityProvidersFound",
@ -345,9 +364,9 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
} }
} }
allHappyConditionsLegacyConfigurationSuccess := func(issuer, idpName string, time metav1.Time, observedGeneration int64) []configv1alpha1.Condition { allHappyConditionsLegacyConfigurationSuccess := func(issuer string, idpName string, time metav1.Time, observedGeneration int64) []configv1alpha1.Condition {
return []configv1alpha1.Condition{ return []configv1alpha1.Condition{
// sorted alphabetically by type // expect them to be sorted alphabetically by type
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(idpName, time, observedGeneration), happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(idpName, time, observedGeneration),
happyIssuerIsUniqueCondition(time, observedGeneration), happyIssuerIsUniqueCondition(time, observedGeneration),
happyIssuerURLValidCondition(time, observedGeneration), happyIssuerURLValidCondition(time, observedGeneration),
@ -356,38 +375,33 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
} }
} }
allHappyConditionsSuccess := func(issuer string, time metav1.Time, observedGeneration int64) []configv1alpha1.Condition {
return []configv1alpha1.Condition{
// expect them to be sorted alphabetically by type
happyIdentityProvidersFoundConditionSuccess(frozenMetav1Now, 123),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
happyIssuerURLValidCondition(frozenMetav1Now, 123),
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
happyReadyCondition(issuer, frozenMetav1Now, 123),
}
}
invalidIssuerURL := ":/host//path" invalidIssuerURL := ":/host//path"
_, err := url.Parse(invalidIssuerURL) //nolint:staticcheck // Yes, this URL is intentionally invalid. _, err := url.Parse(invalidIssuerURL) //nolint:staticcheck // Yes, this URL is intentionally invalid.
require.Error(t, err) 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
}
tests := []struct { tests := []struct {
name string name string
inputObjects []runtime.Object inputObjects []runtime.Object
configPinnipedClient func(*pinnipedfake.Clientset) configPinnipedClient func(*pinnipedfake.Clientset)
wantErr string wantErr string
wantActions func(t *testing.T) []coretesting.Action wantStatusUpdates []*configv1alpha1.FederationDomain
wantFederationDomainIssuers func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer wantFederationDomainIssuers []*federationdomainproviders.FederationDomainIssuer
}{ }{
{ {
name: "when there are no FederationDomains, nothing happens", name: "when there are no FederationDomains, no update actions happen and the list of FederationDomainIssuers is set to the empty list",
inputObjects: []runtime.Object{}, inputObjects: []runtime.Object{},
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{},
return []*federationdomainproviders.FederationDomainIssuer{}
},
wantActions: func(t *testing.T) []coretesting.Action {
return []coretesting.Action{}
},
}, },
{ {
name: "legacy config: when no identity provider is specified on federation domains, but exactly one identity " + name: "legacy config: when no identity provider is specified on federation domains, but exactly one identity " +
@ -398,27 +412,19 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
federationDomain2, federationDomain2,
identityProvider1, identityProvider1,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ federationDomainIssuerWithDefaultIDP(t, federationDomain1.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain1.Spec.Issuer, identityProvider1.ObjectMeta), federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ expectedFederationDomainStatusUpdate(federationDomain1,
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain1.Namespace, configv1alpha1.FederationDomainPhaseReady,
newCopyWithStatus(federationDomain1, allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseReady, ),
allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123), expectedFederationDomainStatusUpdate(federationDomain2,
), configv1alpha1.FederationDomainPhaseReady,
), allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain2.Namespace, ),
newCopyWithStatus(federationDomain2,
configv1alpha1.FederationDomainPhaseReady,
allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
),
),
}
}, },
}, },
{ {
@ -426,26 +432,26 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
"the out-of-date FederationDomain", "the out-of-date FederationDomain",
inputObjects: []runtime.Object{ inputObjects: []runtime.Object{
identityProvider1, identityProvider1,
newCopyWithStatus(federationDomain1, configv1alpha1.FederationDomainPhaseReady, &configv1alpha1.FederationDomain{
allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123), ObjectMeta: metav1.ObjectMeta{Name: federationDomain1.Name, Namespace: federationDomain1.Namespace, Generation: 123},
), Spec: configv1alpha1.FederationDomainSpec{Issuer: federationDomain1.Spec.Issuer},
Status: configv1alpha1.FederationDomainStatus{
Phase: configv1alpha1.FederationDomainPhaseReady,
Conditions: allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
},
},
federationDomain2, federationDomain2,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ federationDomainIssuerWithDefaultIDP(t, federationDomain1.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain1.Spec.Issuer, identityProvider1.ObjectMeta), federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ // only one update, because the other FederationDomain already had the right status
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain2.Namespace, expectedFederationDomainStatusUpdate(federationDomain2,
newCopyWithStatus(federationDomain2, configv1alpha1.FederationDomainPhaseReady,
configv1alpha1.FederationDomainPhaseReady, allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123), ),
),
),
}
}, },
}, },
{ {
@ -469,71 +475,55 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
) )
}, },
wantErr: "could not update status: some update error", wantErr: "could not update status: some update error",
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ // federationDomain1 is not included because it encountered an error
// federationDomain1 is not included because it encountered an error federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ expectedFederationDomainStatusUpdate(federationDomain1,
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain1.Namespace, configv1alpha1.FederationDomainPhaseReady,
newCopyWithStatus(federationDomain1, allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseReady, ),
allHappyConditionsLegacyConfigurationSuccess(federationDomain1.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123), expectedFederationDomainStatusUpdate(federationDomain2,
), configv1alpha1.FederationDomainPhaseReady,
), allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain2.Namespace, ),
newCopyWithStatus(federationDomain2,
configv1alpha1.FederationDomainPhaseReady,
allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
),
),
}
}, },
}, },
{ {
name: "when there are both valid and invalid FederationDomains, the status will be correctly set on each " + name: "when there are both valid and invalid FederationDomains, the status will be correctly set on each " +
"FederationDomain individually", "FederationDomain individually",
inputObjects: []runtime.Object{ inputObjects: []runtime.Object{
invalidFederationDomain, invalidIssuerURLFederationDomain,
federationDomain2, federationDomain2,
identityProvider1, identityProvider1,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ // only the valid FederationDomain
// only the valid FederationDomain federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ expectedFederationDomainStatusUpdate(invalidIssuerURLFederationDomain,
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, configv1alpha1.FederationDomainPhaseError,
newCopyWithStatus(invalidFederationDomain, []configv1alpha1.Condition{
configv1alpha1.FederationDomainPhaseError, happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
[]configv1alpha1.Condition{ happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123), sadIssuerURLValidConditionCannotHaveQuery(frozenMetav1Now, 123),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123), happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadIssuerURLValidConditionCannotHaveQuery(frozenMetav1Now, 123), sadReadyCondition(frozenMetav1Now, 123),
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), },
sadReadyCondition(frozenMetav1Now, 123), ),
}, expectedFederationDomainStatusUpdate(federationDomain2,
), configv1alpha1.FederationDomainPhaseReady,
), allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain2.Namespace, ),
newCopyWithStatus(federationDomain2,
configv1alpha1.FederationDomainPhaseReady,
allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
),
),
}
}, },
}, },
{ {
name: "when there are both valid and invalid FederationDomains, but updating the invalid one fails, the " + name: "when there are both valid and invalid FederationDomains, but updating the invalid one fails, the " +
"existing status will be unchanged", "existing status will be unchanged",
inputObjects: []runtime.Object{ inputObjects: []runtime.Object{
invalidFederationDomain, invalidIssuerURLFederationDomain,
federationDomain2, federationDomain2,
identityProvider1, identityProvider1,
}, },
@ -543,7 +533,7 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
"federationdomains", "federationdomains",
func(action coretesting.Action) (bool, runtime.Object, error) { func(action coretesting.Action) (bool, runtime.Object, error) {
fd := action.(coretesting.UpdateAction).GetObject().(*configv1alpha1.FederationDomain) fd := action.(coretesting.UpdateAction).GetObject().(*configv1alpha1.FederationDomain)
if fd.Name == invalidFederationDomain.Name { if fd.Name == invalidIssuerURLFederationDomain.Name {
return true, nil, errors.New("some update error") return true, nil, errors.New("some update error")
} }
return false, nil, nil return false, nil, nil
@ -551,33 +541,25 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
) )
}, },
wantErr: "could not update status: some update error", wantErr: "could not update status: some update error",
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ // only the valid FederationDomain
// only the valid FederationDomain federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, federationDomain2.Spec.Issuer, identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ expectedFederationDomainStatusUpdate(invalidIssuerURLFederationDomain,
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, configv1alpha1.FederationDomainPhaseError,
newCopyWithStatus(invalidFederationDomain, []configv1alpha1.Condition{
configv1alpha1.FederationDomainPhaseError, happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
[]configv1alpha1.Condition{ happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123), sadIssuerURLValidConditionCannotHaveQuery(frozenMetav1Now, 123),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123), happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadIssuerURLValidConditionCannotHaveQuery(frozenMetav1Now, 123), sadReadyCondition(frozenMetav1Now, 123),
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), },
sadReadyCondition(frozenMetav1Now, 123), ),
}, expectedFederationDomainStatusUpdate(federationDomain2,
), configv1alpha1.FederationDomainPhaseReady,
), allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain2.Namespace, ),
newCopyWithStatus(federationDomain2,
configv1alpha1.FederationDomainPhaseReady,
allHappyConditionsLegacyConfigurationSuccess(federationDomain2.Spec.Issuer, identityProvider1.Name, frozenMetav1Now, 123),
),
),
}
}, },
}, },
{ {
@ -598,57 +580,43 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
}, },
identityProvider1, identityProvider1,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ federationDomainIssuerWithDefaultIDP(t, "https://issuer-duplicate.com/A", identityProvider1.ObjectMeta),
// different path (paths are case-sensitive)
federationDomainIssuerWithDefaultIDP(t, "https://issuer-duplicate.com/A", identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ expectedFederationDomainStatusUpdate(
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, &configv1alpha1.FederationDomain{
newCopyWithStatus( ObjectMeta: metav1.ObjectMeta{Name: "duplicate1", Namespace: namespace, Generation: 123},
&configv1alpha1.FederationDomain{ },
ObjectMeta: metav1.ObjectMeta{Name: "duplicate1", Namespace: namespace, Generation: 123}, configv1alpha1.FederationDomainPhaseError,
Spec: configv1alpha1.FederationDomainSpec{Issuer: "https://iSSueR-duPlicAte.cOm/a"}, []configv1alpha1.Condition{
}, happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseError, sadIssuerIsUniqueCondition(frozenMetav1Now, 123),
[]configv1alpha1.Condition{ happyIssuerURLValidCondition(frozenMetav1Now, 123),
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123), happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadIssuerIsUniqueCondition(frozenMetav1Now, 123), sadReadyCondition(frozenMetav1Now, 123),
happyIssuerURLValidCondition(frozenMetav1Now, 123), },
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), ),
sadReadyCondition(frozenMetav1Now, 123), expectedFederationDomainStatusUpdate(
}, &configv1alpha1.FederationDomain{
), ObjectMeta: metav1.ObjectMeta{Name: "duplicate2", Namespace: namespace, Generation: 123},
), },
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, configv1alpha1.FederationDomainPhaseError,
newCopyWithStatus( []configv1alpha1.Condition{
&configv1alpha1.FederationDomain{ happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
ObjectMeta: metav1.ObjectMeta{Name: "duplicate2", Namespace: namespace, Generation: 123}, sadIssuerIsUniqueCondition(frozenMetav1Now, 123),
Spec: configv1alpha1.FederationDomainSpec{Issuer: "https://issuer-duplicate.com/a"}, happyIssuerURLValidCondition(frozenMetav1Now, 123),
}, happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseError, sadReadyCondition(frozenMetav1Now, 123),
[]configv1alpha1.Condition{ },
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123), ),
sadIssuerIsUniqueCondition(frozenMetav1Now, 123), expectedFederationDomainStatusUpdate(
happyIssuerURLValidCondition(frozenMetav1Now, 123), &configv1alpha1.FederationDomain{
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), ObjectMeta: metav1.ObjectMeta{Name: "not-duplicate", Namespace: namespace, Generation: 123},
sadReadyCondition(frozenMetav1Now, 123), },
}, configv1alpha1.FederationDomainPhaseReady,
), allHappyConditionsLegacyConfigurationSuccess("https://issuer-duplicate.com/A", identityProvider1.Name, frozenMetav1Now, 123),
), ),
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,
allHappyConditionsLegacyConfigurationSuccess("https://issuer-duplicate.com/A", identityProvider1.Name, frozenMetav1Now, 123),
),
),
}
}, },
}, },
{ {
@ -687,84 +655,56 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
}, },
identityProvider1, identityProvider1,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
return []*federationdomainproviders.FederationDomainIssuer{ federationDomainIssuerWithDefaultIDP(t, "https://issuer-not-duplicate.com", identityProvider1.ObjectMeta),
federationDomainIssuerWithDefaultIDP(t, "https://issuer-not-duplicate.com", identityProvider1.ObjectMeta),
}
}, },
wantActions: func(t *testing.T) []coretesting.Action { wantStatusUpdates: []*configv1alpha1.FederationDomain{
return []coretesting.Action{ expectedFederationDomainStatusUpdate(
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, &configv1alpha1.FederationDomain{
newCopyWithStatus( ObjectMeta: metav1.ObjectMeta{Name: "fd1", Namespace: namespace, Generation: 123},
&configv1alpha1.FederationDomain{ },
ObjectMeta: metav1.ObjectMeta{Name: "fd1", Namespace: namespace, Generation: 123}, configv1alpha1.FederationDomainPhaseError,
Spec: configv1alpha1.FederationDomainSpec{ []configv1alpha1.Condition{
Issuer: "https://iSSueR-duPlicAte-adDress.cOm/path1", happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
TLS: &configv1alpha1.FederationDomainTLSSpec{SecretName: "secret1"}, happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
}, happyIssuerURLValidCondition(frozenMetav1Now, 123),
}, sadOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseError, sadReadyCondition(frozenMetav1Now, 123),
[]configv1alpha1.Condition{ },
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123), ),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123), expectedFederationDomainStatusUpdate(
happyIssuerURLValidCondition(frozenMetav1Now, 123), &configv1alpha1.FederationDomain{
sadOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), ObjectMeta: metav1.ObjectMeta{Name: "fd2", Namespace: namespace, Generation: 123},
sadReadyCondition(frozenMetav1Now, 123), },
}, configv1alpha1.FederationDomainPhaseError,
), []configv1alpha1.Condition{
), happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
newCopyWithStatus( happyIssuerURLValidCondition(frozenMetav1Now, 123),
&configv1alpha1.FederationDomain{ sadOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
ObjectMeta: metav1.ObjectMeta{Name: "fd2", Namespace: namespace, Generation: 123}, sadReadyCondition(frozenMetav1Now, 123),
Spec: configv1alpha1.FederationDomainSpec{ },
Issuer: "https://issuer-duplicate-address.com:1234/path2", ),
TLS: &configv1alpha1.FederationDomainTLSSpec{SecretName: "secret2"}, expectedFederationDomainStatusUpdate(
}, &configv1alpha1.FederationDomain{
}, ObjectMeta: metav1.ObjectMeta{Name: "invalidIssuerURLFederationDomain", Namespace: namespace, Generation: 123},
configv1alpha1.FederationDomainPhaseError, },
[]configv1alpha1.Condition{ configv1alpha1.FederationDomainPhaseError,
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123), []configv1alpha1.Condition{
happyIssuerIsUniqueCondition(frozenMetav1Now, 123), happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
happyIssuerURLValidCondition(frozenMetav1Now, 123), unknownIssuerIsUniqueCondition(frozenMetav1Now, 123),
sadOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), sadIssuerURLValidConditionCannotParse(frozenMetav1Now, 123),
sadReadyCondition(frozenMetav1Now, 123), unknownOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
}, sadReadyCondition(frozenMetav1Now, 123),
), },
), ),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", invalidFederationDomain.Namespace, expectedFederationDomainStatusUpdate(
newCopyWithStatus( &configv1alpha1.FederationDomain{
&configv1alpha1.FederationDomain{ ObjectMeta: metav1.ObjectMeta{Name: "differentIssuerAddressFederationDomain", Namespace: namespace, Generation: 123},
ObjectMeta: metav1.ObjectMeta{Name: "invalidIssuerURLFederationDomain", Namespace: namespace, Generation: 123}, },
Spec: configv1alpha1.FederationDomainSpec{ configv1alpha1.FederationDomainPhaseReady,
Issuer: invalidIssuerURL, allHappyConditionsLegacyConfigurationSuccess("https://issuer-not-duplicate.com", identityProvider1.Name, frozenMetav1Now, 123),
TLS: &configv1alpha1.FederationDomainTLSSpec{SecretName: "secret1"}, ),
},
},
configv1alpha1.FederationDomainPhaseError,
[]configv1alpha1.Condition{
happyIdentityProvidersFoundConditionLegacyConfigurationSuccess(identityProvider1.Name, frozenMetav1Now, 123),
unknownIssuerIsUniqueCondition(frozenMetav1Now, 123),
sadIssuerURLValidConditionCannotParse(frozenMetav1Now, 123),
unknownOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadReadyCondition(frozenMetav1Now, 123),
},
),
),
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,
allHappyConditionsLegacyConfigurationSuccess("https://issuer-not-duplicate.com", identityProvider1.Name, frozenMetav1Now, 123),
),
),
}
}, },
}, },
{ {
@ -773,36 +713,28 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
federationDomain1, federationDomain1,
federationDomain2, federationDomain2,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{},
return []*federationdomainproviders.FederationDomainIssuer{} wantStatusUpdates: []*configv1alpha1.FederationDomain{
}, expectedFederationDomainStatusUpdate(federationDomain1,
wantActions: func(t *testing.T) []coretesting.Action { configv1alpha1.FederationDomainPhaseError,
return []coretesting.Action{ []configv1alpha1.Condition{
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain1.Namespace, sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound(frozenMetav1Now, 123),
newCopyWithStatus(federationDomain1, happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseError, happyIssuerURLValidCondition(frozenMetav1Now, 123),
[]configv1alpha1.Condition{ happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound(frozenMetav1Now, 123), sadReadyCondition(frozenMetav1Now, 123),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123), },
happyIssuerURLValidCondition(frozenMetav1Now, 123), ),
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), expectedFederationDomainStatusUpdate(federationDomain2,
sadReadyCondition(frozenMetav1Now, 123), configv1alpha1.FederationDomainPhaseError,
}, []configv1alpha1.Condition{
), sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound(frozenMetav1Now, 123),
), happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain2.Namespace, happyIssuerURLValidCondition(frozenMetav1Now, 123),
newCopyWithStatus(federationDomain2, happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseError, sadReadyCondition(frozenMetav1Now, 123),
[]configv1alpha1.Condition{ },
sadIdentityProvidersFoundConditionLegacyConfigurationIdentityProviderNotFound(frozenMetav1Now, 123), ),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
happyIssuerURLValidCondition(frozenMetav1Now, 123),
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadReadyCondition(frozenMetav1Now, 123),
},
),
),
}
}, },
}, },
{ {
@ -812,24 +744,18 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
identityProvider1, identityProvider1,
identityProvider2, identityProvider2,
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{},
return []*federationdomainproviders.FederationDomainIssuer{} wantStatusUpdates: []*configv1alpha1.FederationDomain{
}, expectedFederationDomainStatusUpdate(federationDomain1,
wantActions: func(t *testing.T) []coretesting.Action { configv1alpha1.FederationDomainPhaseError,
return []coretesting.Action{ []configv1alpha1.Condition{
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", federationDomain1.Namespace, sadIdentityProvidersFoundConditionIdentityProviderNotSpecified(2, frozenMetav1Now, 123),
newCopyWithStatus(federationDomain1, happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
configv1alpha1.FederationDomainPhaseError, happyIssuerURLValidCondition(frozenMetav1Now, 123),
[]configv1alpha1.Condition{ happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadIdentityProvidersFoundConditionIdentityProviderNotSpecified(2, frozenMetav1Now, 123), sadReadyCondition(frozenMetav1Now, 123),
happyIssuerIsUniqueCondition(frozenMetav1Now, 123), },
happyIssuerURLValidCondition(frozenMetav1Now, 123), ),
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
sadReadyCondition(frozenMetav1Now, 123),
},
),
),
}
}, },
}, },
{ {
@ -848,62 +774,93 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
Name: "cant-find-me", Name: "cant-find-me",
}, },
}, },
{
DisplayName: "cant-find-me-either",
ObjectRef: corev1.TypedLocalObjectReference{
APIGroup: pointer.String(apiGroupSupervisor),
Kind: "OIDCIdentityProvider",
Name: "cant-find-me-either",
},
},
}, },
}, },
}, },
}, },
wantFederationDomainIssuers: func(t *testing.T) []*federationdomainproviders.FederationDomainIssuer { wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{},
return []*federationdomainproviders.FederationDomainIssuer{} wantStatusUpdates: []*configv1alpha1.FederationDomain{
}, expectedFederationDomainStatusUpdate(
// TODO: sketch out a way to eliminate the whole wantActions and be more precise &configv1alpha1.FederationDomain{
// if not wantActions, might wantStatusUpdate? ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123},
// wantStatusUpdate: func(t *testing.T, []configv1alpha1.FederationDomain) { },
// { configv1alpha1.FederationDomainPhaseError,
// Name: "foo", []configv1alpha1.Condition{
// Namespace: "bar", sadIdentityProvidersFoundConditionIdentityProvidersObjectRefsNotFound(
// Phase: "Happy", `.spec.identityProviders[].objectRef identifies resource(s) that cannot be found: `+
// Conditions: []metav1.Condition{}, `IDP with displayName "cant-find-me" at index 0, IDP with displayName "cant-find-me-either" at index 1`,
// } frozenMetav1Now, 123),
// }, happyIssuerIsUniqueCondition(frozenMetav1Now, 123),
wantActions: func(t *testing.T) []coretesting.Action { happyIssuerURLValidCondition(frozenMetav1Now, 123),
return []coretesting.Action{ happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123),
coretesting.NewUpdateSubresourceAction(federationDomainGVR, "status", namespace, sadReadyCondition(frozenMetav1Now, 123),
newCopyWithStatus( },
&configv1alpha1.FederationDomain{ ),
ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123}, },
Spec: configv1alpha1.FederationDomainSpec{ },
Issuer: "https://issuer1.com", {
IdentityProviders: []configv1alpha1.FederationDomainIdentityProvider{ name: "the federation domain specifies identity providers that all exist",
{ inputObjects: []runtime.Object{
DisplayName: "cant-find-me", identityProvider1,
ObjectRef: corev1.TypedLocalObjectReference{ identityProvider2,
APIGroup: pointer.String(apiGroupSupervisor), &configv1alpha1.FederationDomain{
Kind: "OIDCIdentityProvider", ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123},
Name: "cant-find-me", Spec: configv1alpha1.FederationDomainSpec{
}, Issuer: "https://issuer1.com",
}, IdentityProviders: []configv1alpha1.FederationDomainIdentityProvider{
}, {
}, DisplayName: "can-find-me",
}, ObjectRef: corev1.TypedLocalObjectReference{
configv1alpha1.FederationDomainPhaseError, APIGroup: pointer.String(apiGroupSupervisor),
[]configv1alpha1.Condition{ Kind: "OIDCIdentityProvider",
sadIdentityProvidersFoundConditionIdentityProvidersObjectRefsNotFound( Name: identityProvider1.Name,
`.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), DisplayName: "can-find-me-too",
happyOneTLSSecretPerIssuerHostnameCondition(frozenMetav1Now, 123), ObjectRef: corev1.TypedLocalObjectReference{
sadReadyCondition(frozenMetav1Now, 123), APIGroup: pointer.String(apiGroupSupervisor),
}, Kind: "OIDCIdentityProvider",
), Name: identityProvider2.Name,
), },
} },
},
},
},
},
wantFederationDomainIssuers: []*federationdomainproviders.FederationDomainIssuer{
federationDomainIssuerWithIDPs(t, "https://issuer1.com",
[]*federationdomainproviders.FederationDomainIdentityProvider{
{
DisplayName: "can-find-me",
UID: identityProvider1.UID,
Transforms: idtransform.NewTransformationPipeline(),
},
{
DisplayName: "can-find-me-too",
UID: identityProvider2.UID,
Transforms: idtransform.NewTransformationPipeline(),
},
}),
},
wantStatusUpdates: []*configv1alpha1.FederationDomain{
expectedFederationDomainStatusUpdate(
&configv1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: namespace, Generation: 123},
},
configv1alpha1.FederationDomainPhaseReady,
allHappyConditionsSuccess("https://issuer1.com", frozenMetav1Now, 123),
),
}, },
}, },
// {
// name: "the federation domain specifies identity providers that exist",
// wantErr: "", // n/a
// },
} }
for _, tt := range tests { for _, tt := range tests {
@ -950,20 +907,23 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
if tt.wantFederationDomainIssuers != nil { if tt.wantFederationDomainIssuers != nil {
require.True(t, federationDomainsSetter.SetFederationDomainsWasCalled) require.True(t, federationDomainsSetter.SetFederationDomainsWasCalled)
require.ElementsMatch(t, tt.wantFederationDomainIssuers(t), federationDomainsSetter.FederationDomainsReceived) require.ElementsMatch(t, tt.wantFederationDomainIssuers, federationDomainsSetter.FederationDomainsReceived)
} else { } else {
require.False(t, federationDomainsSetter.SetFederationDomainsWasCalled) require.False(t, federationDomainsSetter.SetFederationDomainsWasCalled)
} }
if tt.wantActions != nil { if tt.wantStatusUpdates != nil {
// In this controller we don't actually care about the order of the actions, the FederationDomains // This controller should only perform updates to FederationDomain statuses.
// can be updated in any order. Therefore, we are sorting here to make the test output easier to read. // In this controller we don't actually care about the order of the actions, since the FederationDomains
// Unfortunately the timezone nested in the condition still makes it pretty ugly. // statuses can be updated in any order. Therefore, we are sorting here so we can use require.Equal
actualActions := pinnipedAPIClient.Actions() // to make the test output easier to read. Unfortunately the timezone nested in the condition can still
sortActions(t, actualActions) // make the test failure diffs ugly sometimes, but we do want to assert about timestamps so there's not
wantedActions := tt.wantActions(t) // much we can do about those.
sortActions(t, wantedActions) actualFederationDomainUpdates := getFederationDomainStatusUpdates(t, pinnipedAPIClient.Actions())
require.Equal(t, wantedActions, actualActions) sortFederationDomainsByName(actualFederationDomainUpdates)
sortFederationDomainsByName(tt.wantStatusUpdates)
// Use require.Equal instead of require.ElementsMatch because require.Equal prints a nice diff.
require.Equal(t, tt.wantStatusUpdates, actualFederationDomainUpdates)
} else { } else {
require.Empty(t, pinnipedAPIClient.Actions()) require.Empty(t, pinnipedAPIClient.Actions())
} }
@ -971,18 +931,49 @@ func TestTestFederationDomainWatcherControllerSync(t *testing.T) {
} }
} }
func sortActions(t *testing.T, actions []coretesting.Action) { func expectedFederationDomainStatusUpdate(
sort.SliceStable(actions, func(prev, next int) bool { fd *configv1alpha1.FederationDomain,
updateAction1, ok := actions[prev].(coretesting.UpdateAction) phase configv1alpha1.FederationDomainPhase,
require.True(t, ok, "failed to cast an action as an coretesting.UpdateAction for sort comparison %#v", actions[prev]) conditions []configv1alpha1.Condition,
obj1, ok := updateAction1.GetObject().(metav1.Object) ) *configv1alpha1.FederationDomain {
require.True(t, ok, "failed to cast an action as a metav1.Object for sort comparison %#v", actions[prev]) fdCopy := fd.DeepCopy()
updateAction2, ok := actions[next].(coretesting.UpdateAction) // We don't care about the spec of a FederationDomain in an update status action,
require.True(t, ok, "failed to cast an action as an coretesting.UpdateAction for sort comparison %#v", actions[next]) // so clear it out to make it easier to write expected values.
obj2, ok := updateAction2.GetObject().(metav1.Object) fdCopy.Spec = configv1alpha1.FederationDomainSpec{}
require.True(t, ok, "failed to cast an action as a metav1.Object for sort comparison %#v", actions[next])
return obj1.GetName() < obj2.GetName() fdCopy.Status.Phase = phase
fdCopy.Status.Conditions = conditions
return fdCopy
}
func getFederationDomainStatusUpdates(t *testing.T, actions []coretesting.Action) []*configv1alpha1.FederationDomain {
federationDomains := []*configv1alpha1.FederationDomain{}
for _, action := range actions {
updateAction, ok := action.(coretesting.UpdateAction)
require.True(t, ok, "failed to cast an action as an coretesting.UpdateAction: %#v", action)
require.Equal(t, federationDomainGVR, updateAction.GetResource(), "an update action should have updated a FederationDomain but updated something else")
require.Equal(t, "status", updateAction.GetSubresource(), "an update action should have updated the status subresource but updated something else")
fd, ok := updateAction.GetObject().(*configv1alpha1.FederationDomain)
require.True(t, ok, "failed to cast an action's object as a FederationDomain: %#v", updateAction.GetObject())
require.Equal(t, fd.Namespace, updateAction.GetNamespace(), "an update action might have been called on the wrong namespace for a FederationDomain")
// We don't care about the spec of a FederationDomain in an update status action,
// so clear it out to make it easier to write expected values.
copyOfFD := fd.DeepCopy()
copyOfFD.Spec = configv1alpha1.FederationDomainSpec{}
federationDomains = append(federationDomains, copyOfFD)
}
return federationDomains
}
func sortFederationDomainsByName(federationDomains []*configv1alpha1.FederationDomain) {
sort.SliceStable(federationDomains, func(a, b int) bool {
return federationDomains[a].GetName() < federationDomains[b].GetName()
}) })
} }