Merge pull request #134 from mattmoyer/refactor-test-params

Refactor integration test environment helpers to be more structured.
This commit is contained in:
Matt Moyer 2020-09-25 10:04:37 -05:00 committed by GitHub
commit 42e74a02e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 127 additions and 142 deletions

View File

@ -19,7 +19,7 @@ import (
) )
func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t)
const defaultServingCertResourceName = "pinniped-api-tls-serving-certificate" const defaultServingCertResourceName = "pinniped-api-tls-serving-certificate"
@ -74,8 +74,6 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
for _, test := range tests { for _, test := range tests {
test := test test := test
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE")
kubeClient := library.NewClientset(t) kubeClient := library.NewClientset(t)
aggregatedClient := library.NewAggregatedClientset(t) aggregatedClient := library.NewAggregatedClientset(t)
pinnipedClient := library.NewPinnipedClientset(t) pinnipedClient := library.NewPinnipedClientset(t)
@ -85,7 +83,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
const apiServiceName = "v1alpha1.login.pinniped.dev" const apiServiceName = "v1alpha1.login.pinniped.dev"
// Get the initial auto-generated version of the Secret. // Get the initial auto-generated version of the Secret.
secret, err := kubeClient.CoreV1().Secrets(namespaceName).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{}) secret, err := kubeClient.CoreV1().Secrets(env.Namespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
require.NoError(t, err) require.NoError(t, err)
initialCACert := secret.Data["caCertificate"] initialCACert := secret.Data["caCertificate"]
initialPrivateKey := secret.Data["tlsPrivateKey"] initialPrivateKey := secret.Data["tlsPrivateKey"]
@ -100,11 +98,11 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
require.Equal(t, initialCACert, apiService.Spec.CABundle) require.Equal(t, initialCACert, apiService.Spec.CABundle)
// Force rotation to happen. // Force rotation to happen.
require.NoError(t, test.forceRotation(ctx, kubeClient, namespaceName)) require.NoError(t, test.forceRotation(ctx, kubeClient, env.Namespace))
// Expect that the Secret comes back right away with newly minted certs. // Expect that the Secret comes back right away with newly minted certs.
secretIsRegenerated := func() bool { secretIsRegenerated := func() bool {
secret, err = kubeClient.CoreV1().Secrets(namespaceName).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{}) secret, err = kubeClient.CoreV1().Secrets(env.Namespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
return err == nil return err == nil
} }
assert.Eventually(t, secretIsRegenerated, 10*time.Second, 250*time.Millisecond) assert.Eventually(t, secretIsRegenerated, 10*time.Second, 250*time.Millisecond)
@ -135,7 +133,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
// pod has rotated their cert, but not the other ones sitting behind the service. // pod has rotated their cert, but not the other ones sitting behind the service.
aggregatedAPIWorking := func() bool { aggregatedAPIWorking := func() bool {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
_, err = pinnipedClient.LoginV1alpha1().TokenCredentialRequests(namespaceName).Create(ctx, &loginv1alpha1.TokenCredentialRequest{ _, err = pinnipedClient.LoginV1alpha1().TokenCredentialRequests(env.Namespace).Create(ctx, &loginv1alpha1.TokenCredentialRequest{
TypeMeta: metav1.TypeMeta{}, TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{}, ObjectMeta: metav1.ObjectMeta{},
Spec: loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token"}, Spec: loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token"},

View File

@ -17,16 +17,13 @@ import (
) )
func TestGetDeployment(t *testing.T) { func TestGetDeployment(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t)
namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE")
deploymentName := library.GetEnv(t, "PINNIPED_APP_NAME")
client := library.NewClientset(t) client := library.NewClientset(t)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
appDeployment, err := client.AppsV1().Deployments(namespaceName).Get(ctx, deploymentName, metav1.GetOptions{}) appDeployment, err := client.AppsV1().Deployments(env.Namespace).Get(ctx, env.AppName, metav1.GetOptions{})
require.NoError(t, err) require.NoError(t, err)
cond := getDeploymentCondition(appDeployment.Status, appsv1.DeploymentAvailable) cond := getDeploymentCondition(appDeployment.Status, appsv1.DeploymentAvailable)

View File

@ -18,14 +18,7 @@ import (
) )
func TestCLI(t *testing.T) { func TestCLI(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
token := library.GetEnv(t, "PINNIPED_TEST_USER_TOKEN")
namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE")
testUsername := library.GetEnv(t, "PINNIPED_TEST_USER_USERNAME")
expectedTestUserGroups := strings.Split(
strings.ReplaceAll(library.GetEnv(t, "PINNIPED_TEST_USER_GROUPS"), " ", ""), ",",
)
// Create a test webhook configuration to use with the CLI. // Create a test webhook configuration to use with the CLI.
ctx, cancelFunc := context.WithTimeout(context.Background(), 4*time.Minute) ctx, cancelFunc := context.WithTimeout(context.Background(), 4*time.Minute)
@ -62,20 +55,20 @@ func TestCLI(t *testing.T) {
defer cleanupFunc() defer cleanupFunc()
// Run pinniped CLI to get kubeconfig. // Run pinniped CLI to get kubeconfig.
kubeConfigYAML := runPinnipedCLI(t, pinnipedExe, token, namespaceName, "webhook", idp.Name) kubeConfigYAML := runPinnipedCLI(t, pinnipedExe, env.TestUser.Token, env.Namespace, "webhook", idp.Name)
// In addition to the client-go based testing below, also try the kubeconfig // In addition to the client-go based testing below, also try the kubeconfig
// with kubectl to validate that it works. // with kubectl to validate that it works.
adminClient := library.NewClientset(t) adminClient := library.NewClientset(t)
t.Run( t.Run(
"access as user with kubectl", "access as user with kubectl",
accessAsUserWithKubectlTest(ctx, adminClient, kubeConfigYAML, testUsername, namespaceName), accessAsUserWithKubectlTest(ctx, adminClient, kubeConfigYAML, env.TestUser.ExpectedUsername, env.Namespace),
) )
for _, group := range expectedTestUserGroups { for _, group := range env.TestUser.ExpectedGroups {
group := group group := group
t.Run( t.Run(
"access as group "+group+" with kubectl", "access as group "+group+" with kubectl",
accessAsGroupWithKubectlTest(ctx, adminClient, kubeConfigYAML, group, namespaceName), accessAsGroupWithKubectlTest(ctx, adminClient, kubeConfigYAML, group, env.Namespace),
) )
} }
@ -83,8 +76,8 @@ func TestCLI(t *testing.T) {
kubeClient := library.NewClientsetForKubeConfig(t, kubeConfigYAML) kubeClient := library.NewClientsetForKubeConfig(t, kubeConfigYAML)
// Validate that we can auth to the API via our user. // Validate that we can auth to the API via our user.
t.Run("access as user with client-go", accessAsUserTest(ctx, adminClient, testUsername, kubeClient)) t.Run("access as user with client-go", accessAsUserTest(ctx, adminClient, env.TestUser.ExpectedUsername, kubeClient))
for _, group := range expectedTestUserGroups { for _, group := range env.TestUser.ExpectedGroups {
group := group group := group
t.Run("access as group "+group+" with client-go", accessAsGroupTest(ctx, adminClient, group, kubeClient)) t.Run("access as group "+group+" with client-go", accessAsGroupTest(ctx, adminClient, group, kubeClient))
} }

View File

@ -55,10 +55,7 @@ var (
var maskKey = func(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } var maskKey = func(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
func TestClient(t *testing.T) { func TestClient(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
token := library.GetEnv(t, "PINNIPED_TEST_USER_TOKEN")
namespace := library.GetEnv(t, "PINNIPED_NAMESPACE")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel() defer cancel()
@ -75,7 +72,7 @@ func TestClient(t *testing.T) {
var resp *clientauthenticationv1beta1.ExecCredential var resp *clientauthenticationv1beta1.ExecCredential
assert.Eventually(t, func() bool { assert.Eventually(t, func() bool {
resp, err = client.ExchangeToken(ctx, namespace, idp, token, string(clientConfig.CAData), clientConfig.Host) resp, err = client.ExchangeToken(ctx, env.Namespace, idp, env.TestUser.Token, string(clientConfig.CAData), clientConfig.Host)
return err == nil return err == nil
}, 10*time.Second, 500*time.Millisecond) }, 10*time.Second, 500*time.Millisecond)
require.NoError(t, err) require.NoError(t, err)

View File

@ -17,9 +17,7 @@ import (
) )
func TestCredentialIssuerConfig(t *testing.T) { func TestCredentialIssuerConfig(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t)
namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE")
config := library.NewClientConfig(t) config := library.NewClientConfig(t)
client := library.NewPinnipedClientset(t) client := library.NewPinnipedClientset(t)
@ -29,7 +27,7 @@ func TestCredentialIssuerConfig(t *testing.T) {
t.Run("test successful CredentialIssuerConfig", func(t *testing.T) { t.Run("test successful CredentialIssuerConfig", func(t *testing.T) {
actualConfigList, err := client. actualConfigList, err := client.
ConfigV1alpha1(). ConfigV1alpha1().
CredentialIssuerConfigs(namespaceName). CredentialIssuerConfigs(env.Namespace).
List(ctx, metav1.ListOptions{}) List(ctx, metav1.ListOptions{})
require.NoError(t, err) require.NoError(t, err)
@ -43,7 +41,7 @@ func TestCredentialIssuerConfig(t *testing.T) {
actualStatusStrategy := actualStatusStrategies[0] actualStatusStrategy := actualStatusStrategies[0]
require.Equal(t, configv1alpha1.KubeClusterSigningCertificateStrategyType, actualStatusStrategy.Type) require.Equal(t, configv1alpha1.KubeClusterSigningCertificateStrategyType, actualStatusStrategy.Type)
if library.ClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) { if env.HasCapability(library.ClusterSigningKeyIsAvailable) {
require.Equal(t, configv1alpha1.SuccessStrategyStatus, actualStatusStrategy.Status) require.Equal(t, configv1alpha1.SuccessStrategyStatus, actualStatusStrategy.Status)
require.Equal(t, configv1alpha1.FetchedKeyStrategyReason, actualStatusStrategy.Reason) require.Equal(t, configv1alpha1.FetchedKeyStrategyReason, actualStatusStrategy.Reason)
require.Equal(t, "Key was fetched successfully", actualStatusStrategy.Message) require.Equal(t, "Key was fetched successfully", actualStatusStrategy.Message)

View File

@ -7,7 +7,6 @@ import (
"context" "context"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"strings"
"testing" "testing"
"time" "time"
@ -40,12 +39,8 @@ func TestUnsuccessfulCredentialRequest(t *testing.T) {
} }
func TestSuccessfulCredentialRequest(t *testing.T) { func TestSuccessfulCredentialRequest(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
testUsername := library.GetEnv(t, "PINNIPED_TEST_USER_USERNAME")
expectedTestUserGroups := strings.Split(
strings.ReplaceAll(library.GetEnv(t, "PINNIPED_TEST_USER_GROUPS"), " ", ""), ",",
)
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 6*time.Minute)
defer cancel() defer cancel()
@ -64,8 +59,8 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
require.Empty(t, response.Spec) require.Empty(t, response.Spec)
require.Empty(t, response.Status.Credential.Token) require.Empty(t, response.Status.Credential.Token)
require.NotEmpty(t, response.Status.Credential.ClientCertificateData) require.NotEmpty(t, response.Status.Credential.ClientCertificateData)
require.Equal(t, testUsername, getCommonName(t, response.Status.Credential.ClientCertificateData)) require.Equal(t, env.TestUser.ExpectedUsername, getCommonName(t, response.Status.Credential.ClientCertificateData))
require.ElementsMatch(t, expectedTestUserGroups, getOrganizations(t, response.Status.Credential.ClientCertificateData)) require.ElementsMatch(t, env.TestUser.ExpectedGroups, getOrganizations(t, response.Status.Credential.ClientCertificateData))
require.NotEmpty(t, response.Status.Credential.ClientKeyData) require.NotEmpty(t, response.Status.Credential.ClientKeyData)
require.NotNil(t, response.Status.Credential.ExpirationTimestamp) require.NotNil(t, response.Status.Credential.ExpirationTimestamp)
require.InDelta(t, time.Until(response.Status.Credential.ExpirationTimestamp.Time), 1*time.Hour, float64(3*time.Minute)) require.InDelta(t, time.Until(response.Status.Credential.ExpirationTimestamp.Time), 1*time.Hour, float64(3*time.Minute))
@ -82,9 +77,9 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
t.Run( t.Run(
"access as user", "access as user",
accessAsUserTest(ctx, adminClient, testUsername, clientWithCertFromCredentialRequest), accessAsUserTest(ctx, adminClient, env.TestUser.ExpectedUsername, clientWithCertFromCredentialRequest),
) )
for _, group := range expectedTestUserGroups { for _, group := range env.TestUser.ExpectedGroups {
group := group group := group
t.Run( t.Run(
"access as group "+group, "access as group "+group,
@ -94,8 +89,7 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
} }
func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthenticateTheUser(t *testing.T) { func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthenticateTheUser(t *testing.T) {
library.SkipUnlessIntegration(t) library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
response, err := makeRequest(context.Background(), t, loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token"}) response, err := makeRequest(context.Background(), t, loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token"})
@ -107,8 +101,7 @@ func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthentic
} }
func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T) { func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T) {
library.SkipUnlessIntegration(t) library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
response, err := makeRequest(context.Background(), t, loginv1alpha1.TokenCredentialRequestSpec{Token: ""}) response, err := makeRequest(context.Background(), t, loginv1alpha1.TokenCredentialRequestSpec{Token: ""})
@ -127,8 +120,7 @@ func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T
} }
func TestCredentialRequest_OtherwiseValidRequestWithRealTokenShouldFailWhenTheClusterIsNotCapable(t *testing.T) { func TestCredentialRequest_OtherwiseValidRequestWithRealTokenShouldFailWhenTheClusterIsNotCapable(t *testing.T) {
library.SkipUnlessIntegration(t) library.IntegrationEnv(t).WithoutCapability(library.ClusterSigningKeyIsAvailable)
library.SkipWhenClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel() defer cancel()
@ -146,23 +138,23 @@ func TestCredentialRequest_OtherwiseValidRequestWithRealTokenShouldFailWhenTheCl
func makeRequest(ctx context.Context, t *testing.T, spec loginv1alpha1.TokenCredentialRequestSpec) (*loginv1alpha1.TokenCredentialRequest, error) { func makeRequest(ctx context.Context, t *testing.T, spec loginv1alpha1.TokenCredentialRequestSpec) (*loginv1alpha1.TokenCredentialRequest, error) {
t.Helper() t.Helper()
env := library.IntegrationEnv(t)
client := library.NewAnonymousPinnipedClientset(t) client := library.NewAnonymousPinnipedClientset(t)
ctx, cancel := context.WithTimeout(ctx, 10*time.Second) ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel() defer cancel()
ns := library.GetEnv(t, "PINNIPED_NAMESPACE") return client.LoginV1alpha1().TokenCredentialRequests(env.Namespace).Create(ctx, &loginv1alpha1.TokenCredentialRequest{
return client.LoginV1alpha1().TokenCredentialRequests(ns).Create(ctx, &loginv1alpha1.TokenCredentialRequest{
TypeMeta: metav1.TypeMeta{}, TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{Namespace: ns}, ObjectMeta: metav1.ObjectMeta{Namespace: env.Namespace},
Spec: spec, Spec: spec,
}, metav1.CreateOptions{}) }, metav1.CreateOptions{})
} }
func validCredentialRequestSpecWithRealToken(t *testing.T, idp corev1.TypedLocalObjectReference) loginv1alpha1.TokenCredentialRequestSpec { func validCredentialRequestSpecWithRealToken(t *testing.T, idp corev1.TypedLocalObjectReference) loginv1alpha1.TokenCredentialRequestSpec {
return loginv1alpha1.TokenCredentialRequestSpec{ return loginv1alpha1.TokenCredentialRequestSpec{
Token: library.GetEnv(t, "PINNIPED_TEST_USER_TOKEN"), Token: library.IntegrationEnv(t).TestUser.Token,
IdentityProvider: idp, IdentityProvider: idp,
} }
} }

View File

@ -25,9 +25,7 @@ const (
) )
func TestKubeCertAgent(t *testing.T) { func TestKubeCertAgent(t *testing.T) {
library.SkipUnlessIntegration(t) env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable)
namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE")
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel() defer cancel()
@ -39,7 +37,7 @@ func TestKubeCertAgent(t *testing.T) {
// We can pretty safely assert there should be more than 1, since there should be a // We can pretty safely assert there should be more than 1, since there should be a
// kube-cert-agent pod per kube-controller-manager pod, and there should probably be at least // kube-cert-agent pod per kube-controller-manager pod, and there should probably be at least
// 1 kube-controller-manager for this to be a working kube API. // 1 kube-controller-manager for this to be a working kube API.
originalAgentPods, err := kubeClient.CoreV1().Pods(namespaceName).List(ctx, metav1.ListOptions{ originalAgentPods, err := kubeClient.CoreV1().Pods(env.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: kubeCertAgentLabelSelector, LabelSelector: kubeCertAgentLabelSelector,
}) })
require.NoError(t, err) require.NoError(t, err)
@ -48,7 +46,7 @@ func TestKubeCertAgent(t *testing.T) {
agentPodsReconciled := func() bool { agentPodsReconciled := func() bool {
var currentAgentPods *corev1.PodList var currentAgentPods *corev1.PodList
currentAgentPods, err = kubeClient.CoreV1().Pods(namespaceName).List(ctx, metav1.ListOptions{ currentAgentPods, err = kubeClient.CoreV1().Pods(env.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: kubeCertAgentLabelSelector, LabelSelector: kubeCertAgentLabelSelector,
}) })
@ -92,7 +90,7 @@ func TestKubeCertAgent(t *testing.T) {
updatedAgentPod.Spec.Tolerations, updatedAgentPod.Spec.Tolerations,
corev1.Toleration{Key: "fake-toleration"}, corev1.Toleration{Key: "fake-toleration"},
) )
_, err = kubeClient.CoreV1().Pods(namespaceName).Update(ctx, updatedAgentPod, metav1.UpdateOptions{}) _, err = kubeClient.CoreV1().Pods(env.Namespace).Update(ctx, updatedAgentPod, metav1.UpdateOptions{})
require.NoError(t, err) require.NoError(t, err)
// Make sure the original pods come back. // Make sure the original pods come back.
@ -104,7 +102,7 @@ func TestKubeCertAgent(t *testing.T) {
// Delete the first pod. The controller should see it, and flip it back. // Delete the first pod. The controller should see it, and flip it back.
err = kubeClient. err = kubeClient.
CoreV1(). CoreV1().
Pods(namespaceName). Pods(env.Namespace).
Delete(ctx, originalAgentPods.Items[0].Name, metav1.DeleteOptions{}) Delete(ctx, originalAgentPods.Items[0].Name, metav1.DeleteOptions{})
require.NoError(t, err) require.NoError(t, err)

View File

@ -147,12 +147,10 @@ func newAnonymousClientRestConfigWithCertAndKeyAdded(t *testing.T, clientCertifi
// descibes the test IDP within the test namespace. // descibes the test IDP within the test namespace.
func CreateTestWebhookIDP(ctx context.Context, t *testing.T) corev1.TypedLocalObjectReference { func CreateTestWebhookIDP(ctx context.Context, t *testing.T) corev1.TypedLocalObjectReference {
t.Helper() t.Helper()
testEnv := IntegrationEnv(t)
namespace := GetEnv(t, "PINNIPED_NAMESPACE")
endpoint := GetEnv(t, "PINNIPED_TEST_WEBHOOK_ENDPOINT")
caBundle := GetEnv(t, "PINNIPED_TEST_WEBHOOK_CA_BUNDLE")
client := NewPinnipedClientset(t) client := NewPinnipedClientset(t)
webhooks := client.IDPV1alpha1().WebhookIdentityProviders(namespace) webhooks := client.IDPV1alpha1().WebhookIdentityProviders(testEnv.Namespace)
createContext, cancel := context.WithTimeout(ctx, 5*time.Second) createContext, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() defer cancel()
@ -163,10 +161,7 @@ func CreateTestWebhookIDP(ctx context.Context, t *testing.T) corev1.TypedLocalOb
Labels: map[string]string{"pinniped.dev/test": ""}, Labels: map[string]string{"pinniped.dev/test": ""},
Annotations: map[string]string{"pinniped.dev/testName": t.Name()}, Annotations: map[string]string{"pinniped.dev/testName": t.Name()},
}, },
Spec: idpv1alpha1.WebhookIdentityProviderSpec{ Spec: testEnv.TestWebhook,
Endpoint: endpoint,
TLS: &idpv1alpha1.TLSSpec{CertificateAuthorityData: caBundle},
},
}, metav1.CreateOptions{}) }, metav1.CreateOptions{})
require.NoError(t, err, "could not create test WebhookIdentityProvider") require.NoError(t, err, "could not create test WebhookIdentityProvider")
t.Logf("created test WebhookIdentityProvider %s/%s", idp.Namespace, idp.Name) t.Logf("created test WebhookIdentityProvider %s/%s", idp.Namespace, idp.Name)

View File

@ -1,63 +0,0 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package library
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/require"
"sigs.k8s.io/yaml"
)
type TestClusterCapability string
const (
ClusterSigningKeyIsAvailable = TestClusterCapability("clusterSigningKeyIsAvailable")
)
type capabilitiesConfig struct {
Capabilities map[TestClusterCapability]bool `yaml:"capabilities,omitempty"`
}
func ClusterHasCapability(t *testing.T, capability TestClusterCapability) bool {
t.Helper()
capabilitiesDescriptionYAML := os.Getenv("PINNIPED_CLUSTER_CAPABILITY_YAML")
capabilitiesDescriptionFile := os.Getenv("PINNIPED_CLUSTER_CAPABILITY_FILE")
require.NotEmptyf(t,
capabilitiesDescriptionYAML+capabilitiesDescriptionFile,
"must specify either PINNIPED_CLUSTER_CAPABILITY_YAML or PINNIPED_CLUSTER_CAPABILITY_FILE env var for integration tests",
)
if capabilitiesDescriptionYAML == "" {
bytes, err := ioutil.ReadFile(capabilitiesDescriptionFile)
capabilitiesDescriptionYAML = string(bytes)
require.NoError(t, err)
}
var capabilities capabilitiesConfig
err := yaml.Unmarshal([]byte(capabilitiesDescriptionYAML), &capabilities)
require.NoError(t, err)
isCapable, capabilityWasDescribed := capabilities.Capabilities[capability]
require.True(t, capabilityWasDescribed, `the cluster's "%s" capability was not described`, capability)
return isCapable
}
func SkipUnlessClusterHasCapability(t *testing.T, capability TestClusterCapability) {
t.Helper()
if !ClusterHasCapability(t, capability) {
t.Skipf(`skipping integration test because cluster lacks the "%s" capability`, capability)
}
}
func SkipWhenClusterHasCapability(t *testing.T, capability TestClusterCapability) {
t.Helper()
if ClusterHasCapability(t, capability) {
t.Skipf(`skipping integration test because cluster has the "%s" capability`, capability)
}
}

View File

@ -4,17 +4,97 @@
package library package library
import ( import (
"io/ioutil"
"os" "os"
"strings"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sigs.k8s.io/yaml"
idpv1alpha1 "go.pinniped.dev/generated/1.19/apis/idp/v1alpha1"
) )
// GetEnv gets the environment variable with key and asserts that it is not type TestClusterCapability string
// empty. It returns the value of the environment variable.
func GetEnv(t *testing.T, key string) string { const (
ClusterSigningKeyIsAvailable = TestClusterCapability("clusterSigningKeyIsAvailable")
)
// TestEnv captures all the external parameters consumed by our integration tests.
type TestEnv struct {
t *testing.T
Namespace string `json:"namespace"`
AppName string `json:"appName"`
Capabilities map[TestClusterCapability]bool `json:"capabilities"`
TestWebhook idpv1alpha1.WebhookIdentityProviderSpec `json:"testWebhook"`
TestUser struct {
Token string `json:"token"`
ExpectedUsername string `json:"expectedUsername"`
ExpectedGroups []string `json:"expectedGroups"`
} `json:"testUser"`
}
// IntegrationEnv gets the integration test environment from a Kubernetes Secret in the test cluster. This
// method also implies SkipUnlessIntegration().
func IntegrationEnv(t *testing.T) *TestEnv {
t.Helper()
SkipUnlessIntegration(t)
capabilitiesDescriptionYAML := os.Getenv("PINNIPED_CLUSTER_CAPABILITY_YAML")
capabilitiesDescriptionFile := os.Getenv("PINNIPED_CLUSTER_CAPABILITY_FILE")
require.NotEmptyf(t,
capabilitiesDescriptionYAML+capabilitiesDescriptionFile,
"must specify either PINNIPED_CLUSTER_CAPABILITY_YAML or PINNIPED_CLUSTER_CAPABILITY_FILE env var for integration tests",
)
if capabilitiesDescriptionYAML == "" {
bytes, err := ioutil.ReadFile(capabilitiesDescriptionFile)
capabilitiesDescriptionYAML = string(bytes)
require.NoError(t, err)
}
var result TestEnv
err := yaml.Unmarshal([]byte(capabilitiesDescriptionYAML), &result)
require.NoErrorf(t, err, "capabilities specification was invalid YAML")
needEnv := func(key string) string {
t.Helper() t.Helper()
value := os.Getenv(key) value := os.Getenv(key)
require.NotEmptyf(t, value, "must specify %s env var for integration tests", key) require.NotEmptyf(t, value, "must specify %s env var for integration tests", key)
return value return value
} }
result.Namespace = needEnv("PINNIPED_NAMESPACE")
result.AppName = needEnv("PINNIPED_APP_NAME")
result.TestUser.ExpectedUsername = needEnv("PINNIPED_TEST_USER_USERNAME")
result.TestUser.ExpectedGroups = strings.Split(strings.ReplaceAll(needEnv("PINNIPED_TEST_USER_GROUPS"), " ", ""), ",")
result.TestUser.Token = needEnv("PINNIPED_TEST_USER_TOKEN")
result.TestWebhook.Endpoint = needEnv("PINNIPED_TEST_WEBHOOK_ENDPOINT")
result.TestWebhook.TLS = &idpv1alpha1.TLSSpec{CertificateAuthorityData: needEnv("PINNIPED_TEST_WEBHOOK_CA_BUNDLE")}
result.t = t
return &result
}
func (e *TestEnv) HasCapability(cap TestClusterCapability) bool {
e.t.Helper()
isCapable, capabilityWasDescribed := e.Capabilities[cap]
require.True(e.t, capabilityWasDescribed, `the cluster's "%s" capability was not described`, cap)
return isCapable
}
func (e *TestEnv) WithCapability(cap TestClusterCapability) *TestEnv {
e.t.Helper()
if !e.HasCapability(cap) {
e.t.Skipf(`skipping integration test because cluster lacks the "%s" capability`, cap)
}
return e
}
func (e *TestEnv) WithoutCapability(cap TestClusterCapability) *TestEnv {
e.t.Helper()
if e.HasCapability(cap) {
e.t.Skipf(`skipping integration test because cluster has the "%s" capability`, cap)
}
return e
}