mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Add integration test for exec plugin global cache
Signed-off-by: Monis Khan <mok@vmware.com>
This commit is contained in:
parent
164ba3ad7d
commit
a45ffd0771
@ -28,6 +28,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@ -38,10 +39,12 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/plugin/pkg/client/auth/exec"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
@ -102,15 +105,7 @@ var execPluginMetricsComparer = cmp.Comparer(func(a, b *execPluginMetrics) bool
|
||||
return reflect.DeepEqual(a, b)
|
||||
})
|
||||
|
||||
func TestExecPluginViaClient(t *testing.T) {
|
||||
result, clientAuthorizedToken, clientCertFileName, clientKeyFileName := startTestServer(t)
|
||||
|
||||
unauthorizedCert, unauthorizedKey, err := cert.GenerateSelfSignedCertKey("some-host", nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
type execPluginClientTestData struct {
|
||||
name string
|
||||
clientConfigFunc func(*rest.Config)
|
||||
wantAuthorizationHeaderValues [][]string
|
||||
@ -118,7 +113,10 @@ func TestExecPluginViaClient(t *testing.T) {
|
||||
wantGetCertificateErrorPrefix string
|
||||
wantClientErrorPrefix string
|
||||
wantMetrics *execPluginMetrics
|
||||
}{
|
||||
}
|
||||
|
||||
func execPluginClientTests(t *testing.T, unauthorizedCert, unauthorizedKey []byte, clientAuthorizedToken, clientCertFileName, clientKeyFileName string) []execPluginClientTestData {
|
||||
return []execPluginClientTestData{
|
||||
{
|
||||
name: "unauthorized token",
|
||||
clientConfigFunc: func(c *rest.Config) {
|
||||
@ -414,6 +412,18 @@ func TestExecPluginViaClient(t *testing.T) {
|
||||
wantMetrics: &execPluginMetrics{calls: []execPluginCall{{exitCode: 10, callStatus: "plugin_execution_error"}}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecPluginViaClient(t *testing.T) {
|
||||
result, clientAuthorizedToken, clientCertFileName, clientKeyFileName := startTestServer(t)
|
||||
|
||||
unauthorizedCert, unauthorizedKey, err := cert.GenerateSelfSignedCertKey("some-host", nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := execPluginClientTests(t, unauthorizedCert, unauthorizedKey, clientAuthorizedToken, clientCertFileName, clientKeyFileName)
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
@ -954,3 +964,91 @@ func assertInformerEvents(t *testing.T, informerSpy *informerSpy, created, updat
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestExecPluginGlobalCache(t *testing.T) {
|
||||
// we do not really need the server for this test but this allows us to easily share the test data
|
||||
result, clientAuthorizedToken, clientCertFileName, clientKeyFileName := startTestServer(t)
|
||||
|
||||
unauthorizedCert, unauthorizedKey, err := cert.GenerateSelfSignedCertKey("some-host", nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testsFirstRun := execPluginClientTests(t, unauthorizedCert, unauthorizedKey, clientAuthorizedToken, clientCertFileName, clientKeyFileName)
|
||||
testsSecondRun := execPluginClientTests(t, unauthorizedCert, unauthorizedKey, clientAuthorizedToken, clientCertFileName, clientKeyFileName)
|
||||
|
||||
randStrings := make([]string, 0, len(testsFirstRun))
|
||||
for range testsFirstRun {
|
||||
randStrings = append(randStrings, rand.String(10))
|
||||
}
|
||||
|
||||
getTestExecClientAddresses := func(t *testing.T, tests []execPluginClientTestData, suffix string) []string {
|
||||
var addresses []string
|
||||
for i, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name+" "+suffix, func(t *testing.T) {
|
||||
clientConfig := rest.AnonymousClientConfig(result.ClientConfig)
|
||||
clientConfig.ExecProvider = &clientcmdapi.ExecConfig{
|
||||
Command: "testdata/exec-plugin.sh",
|
||||
// TODO(ankeesler): move to v1 once exec plugins go GA.
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
Args: []string{
|
||||
// carefully control what the global cache sees as the same exec plugin
|
||||
"--random-arg-to-avoid-authenticator-cache-hits",
|
||||
randStrings[i],
|
||||
},
|
||||
}
|
||||
|
||||
if test.clientConfigFunc != nil {
|
||||
test.clientConfigFunc(clientConfig)
|
||||
}
|
||||
|
||||
addresses = append(addresses, execPluginMemoryAddress(t, clientConfig, i))
|
||||
})
|
||||
}
|
||||
return addresses
|
||||
}
|
||||
|
||||
addressesFirstRun := getTestExecClientAddresses(t, testsFirstRun, "first")
|
||||
addressesSecondRun := getTestExecClientAddresses(t, testsSecondRun, "second")
|
||||
|
||||
if diff := cmp.Diff(addressesFirstRun, addressesSecondRun); diff != "" {
|
||||
t.Error("unexpected addresses; -want, +got:\n" + diff)
|
||||
}
|
||||
|
||||
if want, got := len(testsFirstRun), len(addressesFirstRun); want != got {
|
||||
t.Errorf("expected %d addresses but got %d", want, got)
|
||||
}
|
||||
|
||||
if want, got := len(addressesFirstRun), sets.NewString(addressesFirstRun...).Len(); want != got {
|
||||
t.Errorf("expected %d distinct authenticators but got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func execPluginMemoryAddress(t *testing.T, config *rest.Config, i int) string {
|
||||
t.Helper()
|
||||
|
||||
wantType := reflect.TypeOf(&exec.Authenticator{})
|
||||
|
||||
tc, err := config.TransportConfig()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if tc.WrapTransport == nil {
|
||||
return "<nil> " + strconv.Itoa(i)
|
||||
}
|
||||
|
||||
rt := tc.WrapTransport(nil)
|
||||
|
||||
val := reflect.Indirect(reflect.ValueOf(rt))
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
field := val.Field(i)
|
||||
if field.Type() == wantType {
|
||||
return strconv.FormatUint(uint64(field.Pointer()), 10)
|
||||
}
|
||||
}
|
||||
|
||||
t.Fatal("unable to find authenticator in rest config")
|
||||
return ""
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user