2022-09-22 04:30:44 +00:00
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
2021-01-13 01:27:41 +00:00
// SPDX-License-Identifier: Apache-2.0
package groupsuffix
import (
"context"
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
2021-02-16 19:00:08 +00:00
authv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
2021-01-13 01:27:41 +00:00
"go.pinniped.dev/internal/kubeclient"
"go.pinniped.dev/internal/testutil"
)
func ExampleReplace_loginv1alpha1 ( ) {
s , _ := Replace ( loginv1alpha1 . GroupName , "tuna.fish.io" )
fmt . Println ( s )
// Output: login.concierge.tuna.fish.io
}
func ExampleReplace_string ( ) {
s , _ := Replace ( "idp.supervisor.pinniped.dev" , "marlin.io" )
fmt . Println ( s )
// Output: idp.supervisor.marlin.io
}
2021-02-05 01:02:59 +00:00
2021-01-13 01:27:41 +00:00
func TestMiddlware ( t * testing . T ) {
const newSuffix = "some.suffix.com"
podWithoutOwner := & corev1 . Pod {
TypeMeta : metav1 . TypeMeta {
APIVersion : corev1 . SchemeGroupVersion . String ( ) ,
Kind : "Pod" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference { } ,
} ,
}
nonPinnipedOwner := & corev1 . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "some-name" ,
UID : "some-uid" ,
} ,
}
nonPinnipedOwnerGVK := corev1 . SchemeGroupVersion . WithKind ( "Pod" )
podWithNonPinnipedOwner := & corev1 . Pod {
TypeMeta : metav1 . TypeMeta {
APIVersion : corev1 . SchemeGroupVersion . String ( ) ,
Kind : "Pod" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference {
* metav1 . NewControllerRef ( nonPinnipedOwner , nonPinnipedOwnerGVK ) ,
} ,
} ,
}
var ok bool
pinnipedOwner := & configv1alpha1 . FederationDomain {
ObjectMeta : metav1 . ObjectMeta {
Name : "some-name" ,
UID : "some-uid" ,
} ,
}
pinnipedOwnerGVK := configv1alpha1 . SchemeGroupVersion . WithKind ( "FederationDomain" )
pinnipedOwnerWithNewGroupGVK := configv1alpha1 . SchemeGroupVersion . WithKind ( "FederationDomain" )
pinnipedOwnerWithNewGroupGVK . Group , ok = Replace ( pinnipedOwnerWithNewGroupGVK . Group , newSuffix )
require . True ( t , ok )
podWithPinnipedOwner := & corev1 . Pod {
TypeMeta : metav1 . TypeMeta {
APIVersion : corev1 . SchemeGroupVersion . String ( ) ,
Kind : "Pod" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference {
* metav1 . NewControllerRef ( pinnipedOwner , pinnipedOwnerGVK ) ,
// make sure we don't update the non-pinniped owner
* metav1 . NewControllerRef ( nonPinnipedOwner , nonPinnipedOwnerGVK ) ,
} ,
} ,
}
podWithPinnipedOwnerWithNewGroup := & corev1 . Pod {
TypeMeta : metav1 . TypeMeta {
APIVersion : corev1 . SchemeGroupVersion . String ( ) ,
Kind : "Pod" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference {
* metav1 . NewControllerRef ( pinnipedOwner , pinnipedOwnerWithNewGroupGVK ) ,
// make sure we don't update the non-pinniped owner
* metav1 . NewControllerRef ( nonPinnipedOwner , nonPinnipedOwnerGVK ) ,
} ,
} ,
}
federationDomainWithPinnipedOwner := & configv1alpha1 . FederationDomain {
TypeMeta : metav1 . TypeMeta {
APIVersion : configv1alpha1 . SchemeGroupVersion . String ( ) ,
Kind : "FederationDomain" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference {
* metav1 . NewControllerRef ( pinnipedOwner , pinnipedOwnerGVK ) ,
// make sure we don't update the non-pinniped owner
* metav1 . NewControllerRef ( nonPinnipedOwner , nonPinnipedOwnerGVK ) ,
} ,
} ,
}
2021-02-05 01:02:59 +00:00
federationDomainWithNewGroupAndPinnipedOwner : = & configv1alpha1 . FederationDomain {
2021-01-13 01:27:41 +00:00
TypeMeta : metav1 . TypeMeta {
2021-02-05 01:02:59 +00:00
APIVersion : replaceGV ( t , configv1alpha1 . SchemeGroupVersion , newSuffix ) . String ( ) ,
2021-01-13 01:27:41 +00:00
Kind : "FederationDomain" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference {
2021-02-05 01:02:59 +00:00
* metav1 . NewControllerRef ( pinnipedOwner , pinnipedOwnerGVK ) ,
2021-01-13 01:27:41 +00:00
// make sure we don't update the non-pinniped owner
* metav1 . NewControllerRef ( nonPinnipedOwner , nonPinnipedOwnerGVK ) ,
} ,
} ,
}
federationDomainWithNewGroupAndPinnipedOwnerWithNewGroup := & configv1alpha1 . FederationDomain {
TypeMeta : metav1 . TypeMeta {
2021-02-05 01:02:59 +00:00
APIVersion : replaceGV ( t , configv1alpha1 . SchemeGroupVersion , newSuffix ) . String ( ) ,
2021-01-13 01:27:41 +00:00
Kind : "FederationDomain" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
OwnerReferences : [ ] metav1 . OwnerReference {
* metav1 . NewControllerRef ( pinnipedOwner , pinnipedOwnerWithNewGroupGVK ) ,
// make sure we don't update the non-pinniped owner
* metav1 . NewControllerRef ( nonPinnipedOwner , nonPinnipedOwnerGVK ) ,
} ,
} ,
}
2021-02-05 01:02:59 +00:00
tokenCredentialRequest := with (
& loginv1alpha1 . TokenCredentialRequest { } ,
gvk ( replaceGV ( t , loginv1alpha1 . SchemeGroupVersion , newSuffix ) . WithKind ( "TokenCredentialRequest" ) ) ,
)
tokenCredentialRequestWithPinnipedAuthenticator := with (
tokenCredentialRequest ,
authenticatorAPIGroup ( authv1alpha1 . SchemeGroupVersion . Group ) ,
)
tokenCredentialRequestWithCustomAPIGroupAuthenticator := with (
tokenCredentialRequest ,
authenticatorAPIGroup ( replaceGV ( t , authv1alpha1 . SchemeGroupVersion , newSuffix ) . Group ) ,
)
tokenCredentialRequestWithNewGroup := with (
tokenCredentialRequest ,
gvk ( replaceGV ( t , loginv1alpha1 . SchemeGroupVersion , newSuffix ) . WithKind ( "TokenCredentialRequest" ) ) ,
)
tokenCredentialRequestWithNewGroupAndPinnipedAuthenticator := with (
tokenCredentialRequestWithNewGroup ,
authenticatorAPIGroup ( authv1alpha1 . SchemeGroupVersion . Group ) ,
)
tokenCredentialRequestWithNewGroupAndCustomAPIGroupAuthenticator := with (
tokenCredentialRequestWithNewGroup ,
authenticatorAPIGroup ( replaceGV ( t , authv1alpha1 . SchemeGroupVersion , newSuffix ) . Group ) ,
)
2021-01-13 01:27:41 +00:00
tests := [ ] struct {
2021-02-05 01:02:59 +00:00
name string
apiGroupSuffix string
rt * testutil . RoundTrip
requestObj , responseObj kubeclient . Object
wantNilMiddleware bool
wantMutateRequests , wantMutateResponses int
wantMutateRequestErrors , wantMutateResponseErrors [ ] string
wantRequestObj , wantResponseObj kubeclient . Object
2021-01-13 01:27:41 +00:00
} {
{
name : "api group suffix is empty" ,
apiGroupSuffix : "" ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbGet ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
wantNilMiddleware : true ,
} ,
{
name : "api group suffix is default" ,
apiGroupSuffix : "pinniped.dev" ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbGet ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
wantNilMiddleware : true ,
} ,
{
name : "get resource without pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbGet ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
responseObj : podWithoutOwner ,
wantMutateResponses : 1 ,
wantResponseObj : podWithoutOwner ,
} ,
{
name : "get resource without pinniped.dev with non-pinniped.dev owner ref" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbGet ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
responseObj : podWithNonPinnipedOwner ,
wantMutateResponses : 1 ,
wantResponseObj : podWithNonPinnipedOwner ,
} ,
{
name : "get resource without pinniped.dev with pinniped.dev owner ref" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbGet ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
responseObj : podWithPinnipedOwnerWithNewGroup ,
wantMutateResponses : 1 ,
wantResponseObj : podWithPinnipedOwner ,
} ,
{
name : "get resource with pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbGet ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
2021-02-05 01:02:59 +00:00
requestObj : with ( & metav1 . PartialObjectMetadata { } , gvk ( loginv1alpha1 . SchemeGroupVersion . WithKind ( "TokenCredentialRequest" ) ) ) ,
responseObj : tokenCredentialRequestWithNewGroup ,
2021-01-13 01:27:41 +00:00
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
2021-02-05 01:02:59 +00:00
wantRequestObj : with ( & metav1 . PartialObjectMetadata { } , gvk ( replaceGV ( t , loginv1alpha1 . SchemeGroupVersion , newSuffix ) . WithKind ( "TokenCredentialRequest" ) ) ) ,
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
2021-01-13 01:27:41 +00:00
} ,
{
name : "create resource without pinniped.dev and without owner ref" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
requestObj : podWithoutOwner ,
responseObj : podWithoutOwner ,
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : podWithoutOwner ,
wantResponseObj : podWithoutOwner ,
} ,
{
name : "create resource without pinniped.dev and with owner ref that has no pinniped.dev owner" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
requestObj : podWithNonPinnipedOwner ,
responseObj : podWithNonPinnipedOwner ,
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : podWithNonPinnipedOwner ,
wantResponseObj : podWithNonPinnipedOwner ,
} ,
{
name : "create resource without pinniped.dev and with owner ref that has pinniped.dev owner" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
requestObj : podWithPinnipedOwner ,
responseObj : podWithPinnipedOwnerWithNewGroup ,
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : podWithPinnipedOwnerWithNewGroup ,
wantResponseObj : podWithPinnipedOwner ,
} ,
{
name : "create subresource without pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) .
WithSubresource ( "some-subresource" ) ,
responseObj : podWithPinnipedOwner ,
wantMutateResponses : 1 ,
wantResponseObj : podWithPinnipedOwner ,
} ,
{
2022-09-22 04:30:44 +00:00
// test that multiple of our middleware request mutations play nicely with each other on create
2021-01-13 01:27:41 +00:00
name : "create resource with pinniped.dev and with owner ref that has pinniped.dev owner" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( configv1alpha1 . SchemeGroupVersion . WithResource ( "federationdomains" ) ) ,
requestObj : federationDomainWithPinnipedOwner ,
2021-02-05 01:02:59 +00:00
responseObj : federationDomainWithNewGroupAndPinnipedOwnerWithNewGroup ,
2021-01-13 01:27:41 +00:00
wantMutateRequests : 2 ,
wantMutateResponses : 1 ,
wantRequestObj : federationDomainWithNewGroupAndPinnipedOwnerWithNewGroup ,
2021-02-05 01:02:59 +00:00
wantResponseObj : federationDomainWithNewGroupAndPinnipedOwner , // the middleware will reset object GVK for us
2021-01-13 01:27:41 +00:00
} ,
{
2022-09-22 04:30:44 +00:00
// test that multiple of our middleware request mutations play nicely with each other on update
name : "update resource with pinniped.dev and with owner ref that has pinniped.dev owner" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbUpdate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( configv1alpha1 . SchemeGroupVersion . WithResource ( "federationdomains" ) ) ,
requestObj : federationDomainWithPinnipedOwner ,
responseObj : federationDomainWithNewGroupAndPinnipedOwnerWithNewGroup ,
wantMutateRequests : 2 ,
wantMutateResponses : 1 ,
wantRequestObj : federationDomainWithNewGroupAndPinnipedOwnerWithNewGroup ,
wantResponseObj : federationDomainWithNewGroupAndPinnipedOwner , // the middleware will reset object GVK for us
} ,
{
name : "update resource without pinniped.dev and without owner ref" ,
2021-01-13 01:27:41 +00:00
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbUpdate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
2022-09-22 04:30:44 +00:00
requestObj : podWithoutOwner ,
2021-01-13 01:27:41 +00:00
responseObj : podWithoutOwner ,
2022-09-22 04:30:44 +00:00
wantMutateRequests : 1 ,
2021-01-13 01:27:41 +00:00
wantMutateResponses : 1 ,
2022-09-22 04:30:44 +00:00
wantRequestObj : podWithoutOwner ,
2021-01-13 01:27:41 +00:00
wantResponseObj : podWithoutOwner ,
} ,
{
2022-09-22 04:30:44 +00:00
name : "update resource without pinniped.dev and with owner ref that has pinniped.dev owner" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbUpdate ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
requestObj : podWithPinnipedOwner ,
responseObj : podWithPinnipedOwnerWithNewGroup ,
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : podWithPinnipedOwnerWithNewGroup ,
wantResponseObj : podWithPinnipedOwner ,
} ,
{
name : "update resource with pinniped.dev and without owner ref" ,
2021-01-13 01:27:41 +00:00
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbUpdate ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequest ,
2021-02-05 01:02:59 +00:00
responseObj : tokenCredentialRequestWithNewGroup ,
2022-09-22 04:30:44 +00:00
wantMutateRequests : 2 ,
2021-01-13 01:27:41 +00:00
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroup ,
2021-02-05 01:02:59 +00:00
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
2021-01-13 01:27:41 +00:00
} ,
{
name : "list resource without pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbList ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
responseObj : podWithoutOwner ,
wantMutateResponses : 1 ,
wantResponseObj : podWithoutOwner ,
} ,
{
name : "list resource with pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbList ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequest ,
2021-02-05 01:02:59 +00:00
responseObj : tokenCredentialRequestWithNewGroup ,
2021-01-13 01:27:41 +00:00
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroup ,
2021-02-05 01:02:59 +00:00
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
2021-01-13 01:27:41 +00:00
} ,
{
name : "watch resource without pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbWatch ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
responseObj : podWithoutOwner ,
wantMutateResponses : 1 ,
wantResponseObj : podWithoutOwner ,
} ,
{
name : "watch resource with pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbList ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequest ,
2021-02-05 01:02:59 +00:00
responseObj : tokenCredentialRequestWithNewGroup ,
2021-01-13 01:27:41 +00:00
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroup ,
2021-02-05 01:02:59 +00:00
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
2021-01-13 01:27:41 +00:00
} ,
{
name : "patch resource without pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbPatch ) .
WithNamespace ( "some-namespace" ) .
WithResource ( corev1 . SchemeGroupVersion . WithResource ( "pods" ) ) ,
responseObj : podWithoutOwner ,
wantMutateResponses : 1 ,
wantResponseObj : podWithoutOwner ,
} ,
{
name : "patch resource with pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
2021-02-05 01:02:59 +00:00
WithVerb ( kubeclient . VerbPatch ) .
2021-01-13 01:27:41 +00:00
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequest ,
2021-02-05 01:02:59 +00:00
responseObj : tokenCredentialRequestWithNewGroup ,
2021-01-13 01:27:41 +00:00
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroup ,
2021-02-05 01:02:59 +00:00
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
} ,
{
name : "create tokencredentialrequest with pinniped.dev authenticator api group" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequestWithPinnipedAuthenticator ,
responseObj : tokenCredentialRequestWithNewGroup , // a token credential response does not contain a spec
wantMutateRequests : 3 ,
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroupAndCustomAPIGroupAuthenticator ,
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
} ,
{
name : "create tokencredentialrequest with custom authenticator api group fails because api group is expected to be pinniped.dev" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequestWithCustomAPIGroupAuthenticator ,
responseObj : tokenCredentialRequestWithNewGroup , // a token credential response does not contain a spec
wantMutateRequests : 3 ,
wantMutateResponses : 1 ,
2022-04-16 02:43:53 +00:00
wantMutateRequestErrors : [ ] string { ` cannot replace token credential request / authenticator API group "authentication.concierge.some.suffix.com" with group suffix "some.suffix.com" ` } ,
2021-02-05 01:02:59 +00:00
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
} ,
{
name : "create tokencredentialrequest with pinniped.dev authenticator api group and subresource" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) .
WithSubresource ( "some-subresource" ) ,
requestObj : tokenCredentialRequestWithPinnipedAuthenticator ,
responseObj : tokenCredentialRequestWithNewGroup , // a token credential response does not contain a spec
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroupAndPinnipedAuthenticator ,
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
} ,
{
name : "non-create tokencredentialrequest with pinniped.dev authenticator api group" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbList ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequestWithPinnipedAuthenticator ,
responseObj : tokenCredentialRequestWithNewGroup , // a token credential response does not contain a spec
wantMutateRequests : 1 ,
wantMutateResponses : 1 ,
wantRequestObj : tokenCredentialRequestWithNewGroupAndPinnipedAuthenticator ,
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
} ,
{
name : "create tokencredentialrequest with nil authenticator api group" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : tokenCredentialRequest ,
responseObj : tokenCredentialRequestWithNewGroup , // a token credential response does not contain a spec
wantMutateRequests : 3 ,
wantMutateResponses : 1 ,
2022-04-16 02:43:53 +00:00
wantMutateRequestErrors : [ ] string { ` cannot replace token credential request / without authenticator API group ` } ,
2021-02-05 01:02:59 +00:00
wantResponseObj : tokenCredentialRequestWithNewGroup , // the middleware will reset object GVK for us
} ,
{
name : "create tokencredentialrequest with non-*loginv1alpha1.TokenCredentialRequest" ,
apiGroupSuffix : newSuffix ,
rt : ( & testutil . RoundTrip { } ) .
WithVerb ( kubeclient . VerbCreate ) .
WithResource ( loginv1alpha1 . SchemeGroupVersion . WithResource ( "tokencredentialrequests" ) ) ,
requestObj : podWithoutOwner ,
responseObj : podWithoutOwner ,
wantMutateRequests : 3 ,
wantMutateResponses : 1 ,
wantMutateRequestErrors : [ ] string { ` cannot cast obj of type *v1.Pod to *loginv1alpha1.TokenCredentialRequest ` } ,
wantResponseObj : podWithoutOwner ,
2021-01-13 01:27:41 +00:00
} ,
}
for _ , test := range tests {
test := test
t . Run ( test . name , func ( t * testing . T ) {
m := New ( test . apiGroupSuffix )
if test . wantNilMiddleware {
require . Nil ( t , m , "wanted nil middleware" )
return
}
m . Handle ( context . Background ( ) , test . rt )
2021-02-05 01:02:59 +00:00
require . Len ( t , test . rt . MutateRequests , test . wantMutateRequests , "undesired request mutation count" )
require . Len ( t , test . rt . MutateResponses , test . wantMutateResponses , "undesired response mutation count" )
2021-01-13 01:27:41 +00:00
if test . wantMutateRequests != 0 {
require . NotNil ( t , test . requestObj , "expected test.requestObj to be set" )
objMutated := test . requestObj . DeepCopyObject ( ) . ( kubeclient . Object )
2021-02-05 01:02:59 +00:00
var mutateRequestErrors [ ] string
2021-01-13 01:27:41 +00:00
for _ , mutateRequest := range test . rt . MutateRequests {
mutateRequest := mutateRequest
2021-02-05 01:02:59 +00:00
if err := mutateRequest ( objMutated ) ; err != nil {
mutateRequestErrors = append ( mutateRequestErrors , err . Error ( ) )
}
}
if len ( test . wantMutateRequestErrors ) > 0 {
require . Equal ( t , test . wantMutateRequestErrors , mutateRequestErrors , "mutate request errors did not match" )
} else {
require . Equal ( t , test . wantRequestObj , objMutated , "request obj did not match" )
2021-01-13 01:27:41 +00:00
}
}
if test . wantMutateResponses != 0 {
require . NotNil ( t , test . responseObj , "expected test.responseObj to be set" )
objMutated := test . responseObj . DeepCopyObject ( ) . ( kubeclient . Object )
2021-02-05 01:02:59 +00:00
var mutateResponseErrors [ ] string
2021-01-13 01:27:41 +00:00
for _ , mutateResponse := range test . rt . MutateResponses {
mutateResponse := mutateResponse
2021-02-05 01:02:59 +00:00
if err := mutateResponse ( objMutated ) ; err != nil {
mutateResponseErrors = append ( mutateResponseErrors , err . Error ( ) )
}
}
if len ( test . wantMutateRequestErrors ) > 0 {
require . Equal ( t , test . wantMutateResponseErrors , mutateResponseErrors , "mutate response errors did not match" )
} else {
require . Equal ( t , test . wantResponseObj , objMutated , "response obj did not match" )
2021-01-13 01:27:41 +00:00
}
}
} )
}
}
func TestReplaceError ( t * testing . T ) {
2021-02-03 23:49:15 +00:00
s , ok := Replace ( "bad-suffix-that-doesnt-end-in-pinniped-dot-dev" , "shouldnt-matter.com" )
require . Equal ( t , "" , s )
2021-01-13 01:27:41 +00:00
require . False ( t , ok )
2021-02-03 23:49:15 +00:00
s , ok = Replace ( "bad-suffix-that-end-in.prefixed-pinniped.dev" , "shouldnt-matter.com" )
require . Equal ( t , "" , s )
2021-01-13 01:27:41 +00:00
require . False ( t , ok )
}
func TestReplaceSuffix ( t * testing . T ) {
s , ok := Replace ( "something.pinniped.dev.something-else.pinniped.dev" , "tuna.io" )
require . Equal ( t , "something.pinniped.dev.something-else.tuna.io" , s )
require . True ( t , ok )
2021-02-03 23:49:15 +00:00
// When the replace wasn't actually needed, it still returns true.
s , ok = Unreplace ( "something.pinniped.dev" , "pinniped.dev" )
require . Equal ( t , "something.pinniped.dev" , s )
require . True ( t , ok )
}
func TestUnreplaceSuffix ( t * testing . T ) {
s , ok := Unreplace ( "something.pinniped.dev.something-else.tuna.io" , "tuna.io" )
require . Equal ( t , "something.pinniped.dev.something-else.pinniped.dev" , s )
require . True ( t , ok )
// When the unreplace wasn't actually needed, it still returns true.
s , ok = Unreplace ( "something.pinniped.dev" , "pinniped.dev" )
require . Equal ( t , "something.pinniped.dev" , s )
require . True ( t , ok )
// When the unreplace was needed but did not work, return false.
s , ok = Unreplace ( "something.pinniped.dev.something-else.tuna.io" , "salmon.io" )
require . Equal ( t , "" , s )
require . False ( t , ok )
2021-01-13 01:27:41 +00:00
}
func TestValidate ( t * testing . T ) {
tests := [ ] struct {
apiGroupSuffix string
wantErrorPrefix string
} {
{
apiGroupSuffix : "happy.suffix.com" ,
} ,
{
apiGroupSuffix : "no-dots" ,
2021-02-05 17:56:05 +00:00
wantErrorPrefix : "must contain '.'" ,
2021-01-13 01:27:41 +00:00
} ,
{
apiGroupSuffix : ".starts.with.dot" ,
2021-02-05 17:56:05 +00:00
wantErrorPrefix : "a lowercase RFC 1123 subdomain must consist" ,
2021-01-13 01:27:41 +00:00
} ,
{
apiGroupSuffix : "ends.with.dot." ,
2021-02-05 17:56:05 +00:00
wantErrorPrefix : "a lowercase RFC 1123 subdomain must consist" ,
2021-01-13 01:27:41 +00:00
} ,
{
apiGroupSuffix : ".multiple-issues.because-this-string-is-longer-than-the-253-character-limit-of-a-dns-1123-identifier-" + chars ( 253 ) ,
2021-02-05 17:56:05 +00:00
wantErrorPrefix : "[must be no more than 253 characters, a lowercase RFC 1123 subdomain must consist" ,
2021-01-13 01:27:41 +00:00
} ,
}
for _ , test := range tests {
test := test
t . Run ( test . apiGroupSuffix , func ( t * testing . T ) {
err := Validate ( test . apiGroupSuffix )
if test . wantErrorPrefix != "" {
require . Error ( t , err )
require . Truef (
t ,
strings . HasPrefix ( err . Error ( ) , test . wantErrorPrefix ) ,
"%q does not start with %q" , err . Error ( ) , test . wantErrorPrefix )
} else {
require . NoError ( t , err )
}
} )
}
}
2021-02-05 01:02:59 +00:00
type withFunc func ( obj kubeclient . Object )
func with ( obj kubeclient . Object , withFuncs ... withFunc ) kubeclient . Object {
obj = obj . DeepCopyObject ( ) . ( kubeclient . Object )
for _ , withFunc := range withFuncs {
withFunc ( obj )
}
return obj
}
func gvk ( gvk schema . GroupVersionKind ) withFunc {
return func ( obj kubeclient . Object ) {
obj . GetObjectKind ( ) . SetGroupVersionKind ( gvk )
}
}
func authenticatorAPIGroup ( apiGroup string ) withFunc {
return func ( obj kubeclient . Object ) {
tokenCredentialRequest := obj . ( * loginv1alpha1 . TokenCredentialRequest )
tokenCredentialRequest . Spec . Authenticator . APIGroup = & apiGroup
}
}
func replaceGV ( t * testing . T , baseGV schema . GroupVersion , apiGroupSuffix string ) schema . GroupVersion {
2021-01-13 01:27:41 +00:00
t . Helper ( )
groupName , ok := Replace ( baseGV . Group , apiGroupSuffix )
require . True ( t , ok , "expected to be able to replace %q's suffix with %q" , baseGV . Group , apiGroupSuffix )
2021-02-05 01:02:59 +00:00
return schema . GroupVersion { Group : groupName , Version : baseGV . Version }
2021-01-13 01:27:41 +00:00
}
func chars ( count int ) string {
return strings . Repeat ( "a" , count )
}