mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +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"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@ -38,10 +39,12 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/rand"
|
"k8s.io/apimachinery/pkg/util/rand"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
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/rest"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
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)
|
return reflect.DeepEqual(a, b)
|
||||||
})
|
})
|
||||||
|
|
||||||
func TestExecPluginViaClient(t *testing.T) {
|
type execPluginClientTestData struct {
|
||||||
result, clientAuthorizedToken, clientCertFileName, clientKeyFileName := startTestServer(t)
|
|
||||||
|
|
||||||
unauthorizedCert, unauthorizedKey, err := cert.GenerateSelfSignedCertKey("some-host", nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
name string
|
||||||
clientConfigFunc func(*rest.Config)
|
clientConfigFunc func(*rest.Config)
|
||||||
wantAuthorizationHeaderValues [][]string
|
wantAuthorizationHeaderValues [][]string
|
||||||
@ -118,7 +113,10 @@ func TestExecPluginViaClient(t *testing.T) {
|
|||||||
wantGetCertificateErrorPrefix string
|
wantGetCertificateErrorPrefix string
|
||||||
wantClientErrorPrefix string
|
wantClientErrorPrefix string
|
||||||
wantMetrics *execPluginMetrics
|
wantMetrics *execPluginMetrics
|
||||||
}{
|
}
|
||||||
|
|
||||||
|
func execPluginClientTests(t *testing.T, unauthorizedCert, unauthorizedKey []byte, clientAuthorizedToken, clientCertFileName, clientKeyFileName string) []execPluginClientTestData {
|
||||||
|
return []execPluginClientTestData{
|
||||||
{
|
{
|
||||||
name: "unauthorized token",
|
name: "unauthorized token",
|
||||||
clientConfigFunc: func(c *rest.Config) {
|
clientConfigFunc: func(c *rest.Config) {
|
||||||
@ -414,6 +412,18 @@ func TestExecPluginViaClient(t *testing.T) {
|
|||||||
wantMetrics: &execPluginMetrics{calls: []execPluginCall{{exitCode: 10, callStatus: "plugin_execution_error"}}},
|
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 {
|
for _, test := range tests {
|
||||||
test := test
|
test := test
|
||||||
t.Run(test.name, func(t *testing.T) {
|
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