Files
pinniped/test/integration/category_test.go
2025-07-30 10:25:23 -05:00

135 lines
3.9 KiB
Go

// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration
import (
"bytes"
"fmt"
"os/exec"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"go.pinniped.dev/test/testlib"
)
func runTestKubectlCommand(t *testing.T, args ...string) (string, string) {
t.Helper()
var stdOut, stdErr bytes.Buffer
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
stdOut.Reset()
stdErr.Reset()
cmd := exec.CommandContext(t.Context(), "kubectl", args...)
cmd.Stdout = &stdOut
cmd.Stderr = &stdErr
requireEventually.NoError(cmd.Run())
}, 120*time.Second, 200*time.Millisecond)
return stdOut.String(), stdErr.String()
}
func requireCleanKubectlStderr(t *testing.T, stderr string) {
// Every line must be empty or contain a known, innocuous warning.
for _, line := range strings.Split(stderr, "\n") {
switch {
case strings.TrimSpace(line) == "",
strings.Contains(line, "Throttling request took"),
strings.Contains(line, "due to client-side throttling, not priority and fairness"),
strings.Contains(line, "the gcp auth plugin is deprecated in v1.22+, unavailable in "),
strings.Contains(line, "To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke"):
// ignore these allowed stderr lines
default:
// anything else is a failure
require.Failf(t, "unexpected kubectl stderr", "kubectl produced unexpected stderr:\n%s\n\n", stderr)
return
}
}
}
func TestGetPinnipedCategory(t *testing.T) {
env := testlib.IntegrationEnv(t)
dotSuffix := "." + env.APIGroupSuffix
aggregatedAPIResources := []struct {
metav1.GroupVersion
ListKind string
Resource string
}{
{
GroupVersion: metav1.GroupVersion{
Group: "login.concierge" + dotSuffix,
Version: "v1alpha1",
},
ListKind: "TokenCredentialRequestList",
Resource: "tokencredentialrequests",
},
{
GroupVersion: metav1.GroupVersion{
Group: "identity.concierge" + dotSuffix,
Version: "v1alpha1",
},
ListKind: "WhoAmIRequestList",
Resource: "whoamirequests",
},
{
GroupVersion: metav1.GroupVersion{
Group: "clientsecret.supervisor" + dotSuffix,
Version: "v1alpha1",
},
ListKind: "OIDCClientSecretRequestList",
Resource: "oidcclientsecretrequests",
},
}
t.Run("can kubectl get whole category as table", func(t *testing.T) {
t.Parallel()
stdout, stderr := runTestKubectlCommand(t, "get", "pinniped", "-A")
requireCleanKubectlStderr(t, stderr)
require.NotContains(t, stdout, "MethodNotAllowed")
// The resulting table should include at least a CredentialIssuer.
require.Contains(t, stdout, dotSuffix)
})
t.Run("can kubectl get each aggregated API as table, and listing these aggregated always results in an empty list", func(t *testing.T) {
t.Parallel()
for _, tt := range aggregatedAPIResources {
t.Run(tt.Resource, func(t *testing.T) {
t.Parallel()
stdout, stderr := runTestKubectlCommand(t, "get", fmt.Sprintf("%s.%s", tt.Resource, tt.Group), "-A")
require.Empty(t, stdout)
require.NotContains(t, stderr, "MethodNotAllowed")
require.Contains(t, stderr, `No resources found`)
})
}
})
t.Run("can kubectl get each aggregated API using raw request, and listing these aggregated always results in an empty list", func(t *testing.T) {
t.Parallel()
for _, tt := range aggregatedAPIResources {
t.Run(tt.Resource, func(t *testing.T) {
t.Parallel()
stdout, stderr := runTestKubectlCommand(t, "get",
"--raw", fmt.Sprintf("/apis/%s/%s/%s", tt.Group, tt.Version, tt.Resource))
requireCleanKubectlStderr(t, stderr)
require.NotContains(t, stdout, "MethodNotAllowed")
require.Contains(t, stdout,
fmt.Sprintf(`{"kind":"%s","apiVersion":"%s/%s","metadata":{"resourceVersion":"0"},"items":[]}`,
tt.ListKind, tt.Group, tt.Version),
)
})
}
})
}