Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clean usage of admissionregistration/v1beta1 from integration tests #99736

Merged
merged 4 commits into from Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 33 additions & 4 deletions cmd/kube-apiserver/app/testing/testserver.go
Expand Up @@ -28,6 +28,9 @@ import (
"time"

"github.com/spf13/pflag"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/pkg/transport"
"google.golang.org/grpc"

"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -59,10 +62,12 @@ type TestServerInstanceOptions struct {

// TestServer return values supplied by kube-test-ApiServer
type TestServer struct {
ClientConfig *restclient.Config // Rest client config
ServerOpts *options.ServerRunOptions // ServerOpts
TearDownFn TearDownFunc // TearDown function
TmpDir string // Temp Dir used, by the apiserver
ClientConfig *restclient.Config // Rest client config
ServerOpts *options.ServerRunOptions // ServerOpts
TearDownFn TearDownFunc // TearDown function
TmpDir string // Temp Dir used, by the apiserver
EtcdClient *clientv3.Client // used by tests that need to check data migrated from APIs that are no longer served
EtcdStoragePrefix string // storage prefix in etcd
}

// Logger allows t.Testing and b.Testing to be passed to StartTestServer and StartTestServerOrDie
Expand Down Expand Up @@ -258,12 +263,36 @@ func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, custo
return result, fmt.Errorf("failed to wait for default namespace to be created: %v", err)
}

tlsInfo := transport.TLSInfo{
CertFile: storageConfig.Transport.CertFile,
KeyFile: storageConfig.Transport.KeyFile,
TrustedCAFile: storageConfig.Transport.TrustedCAFile,
}
tlsConfig, err := tlsInfo.ClientConfig()
if err != nil {
return result, err
}
etcdConfig := clientv3.Config{
Endpoints: storageConfig.Transport.ServerList,
DialTimeout: 20 * time.Second,
DialOptions: []grpc.DialOption{
grpc.WithBlock(), // block until the underlying connection is up
},
TLS: tlsConfig,
}
etcdClient, err := clientv3.New(etcdConfig)
if err != nil {
return result, err
}

// from here the caller must call tearDown
result.ClientConfig = restclient.CopyConfig(server.GenericAPIServer.LoopbackClientConfig)
result.ClientConfig.QPS = 1000
result.ClientConfig.Burst = 10000
result.ServerOpts = s
result.TearDownFn = tearDown
result.EtcdClient = etcdClient
result.EtcdStoragePrefix = storageConfig.Prefix

return result, nil
}
Expand Down
67 changes: 55 additions & 12 deletions test/integration/apiserver/admissionwebhook/admission_test.go
Expand Up @@ -25,14 +25,17 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"path"
"sort"
"strings"
"sync"
"testing"
"time"

"go.etcd.io/etcd/clientv3"
admissionreviewv1 "k8s.io/api/admission/v1"
"k8s.io/api/admission/v1beta1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
admissionv1 "k8s.io/api/admissionregistration/v1"
admissionv1beta1 "k8s.io/api/admissionregistration/v1beta1"
appsv1beta1 "k8s.io/api/apps/v1beta1"
Expand All @@ -49,11 +52,13 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
dynamic "k8s.io/client-go/dynamic"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/retry"
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
apisv1beta1 "k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1"
"k8s.io/kubernetes/test/integration/etcd"
"k8s.io/kubernetes/test/integration/framework"
)
Expand All @@ -66,6 +71,10 @@ const (
validation = "validation"
)

var (
noSideEffects = admissionregistrationv1.SideEffectClassNone
)

type testContext struct {
t *testing.T

Expand Down Expand Up @@ -592,10 +601,10 @@ func testWebhookAdmission(t *testing.T, watchCache bool) {
holder.gvrToConvertedGVK[metaGVR] = schema.GroupVersionKind{Group: resourcesByGVR[convertedGVR].Group, Version: resourcesByGVR[convertedGVR].Version, Kind: resourcesByGVR[convertedGVR].Kind}
}

if err := createV1beta1MutationWebhook(client, webhookServer.URL+"/v1beta1/"+mutation, webhookServer.URL+"/v1beta1/convert/"+mutation, convertedV1beta1Rules); err != nil {
if err := createV1beta1MutationWebhook(server.EtcdClient, server.EtcdStoragePrefix, client, webhookServer.URL+"/v1beta1/"+mutation, webhookServer.URL+"/v1beta1/convert/"+mutation, convertedV1beta1Rules); err != nil {
t.Fatal(err)
}
if err := createV1beta1ValidationWebhook(client, webhookServer.URL+"/v1beta1/"+validation, webhookServer.URL+"/v1beta1/convert/"+validation, convertedV1beta1Rules); err != nil {
if err := createV1beta1ValidationWebhook(server.EtcdClient, server.EtcdStoragePrefix, client, webhookServer.URL+"/v1beta1/"+validation, webhookServer.URL+"/v1beta1/convert/"+validation, convertedV1beta1Rules); err != nil {
t.Fatal(err)
}
if err := createV1MutationWebhook(client, webhookServer.URL+"/v1/"+mutation, webhookServer.URL+"/v1/convert/"+mutation, convertedV1Rules); err != nil {
Expand Down Expand Up @@ -1500,11 +1509,10 @@ func shouldTestResourceVerb(gvr schema.GroupVersionResource, resource metav1.API
// webhook registration helpers
//

func createV1beta1ValidationWebhook(client clientset.Interface, endpoint, convertedEndpoint string, convertedRules []admissionv1beta1.RuleWithOperations) error {
func createV1beta1ValidationWebhook(etcdClient *clientv3.Client, etcdStoragePrefix string, client clientset.Interface, endpoint, convertedEndpoint string, convertedRules []admissionv1beta1.RuleWithOperations) error {
fail := admissionv1beta1.Fail
equivalent := admissionv1beta1.Equivalent
// Attaching Admission webhook to API server
_, err := client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(context.TODO(), &admissionv1beta1.ValidatingWebhookConfiguration{
webhookConfig := &admissionv1beta1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "admission.integration.test"},
Webhooks: []admissionv1beta1.ValidatingWebhook{
{
Expand Down Expand Up @@ -1532,15 +1540,32 @@ func createV1beta1ValidationWebhook(client clientset.Interface, endpoint, conver
AdmissionReviewVersions: []string{"v1beta1"},
},
},
}, metav1.CreateOptions{})
return err
}
// run through to get defaulting
apisv1beta1.SetObjectDefaults_ValidatingWebhookConfiguration(webhookConfig)
webhookConfig.TypeMeta.Kind = "ValidatingWebhookConfiguration"
webhookConfig.TypeMeta.APIVersion = "admissionregistration.k8s.io/v1beta1"

// Attaching Mutation webhook to API server
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone)
key := path.Join("/", etcdStoragePrefix, "validatingwebhookconfigurations", webhookConfig.Name)
val, _ := json.Marshal(webhookConfig)
if _, err := etcdClient.Put(ctx, key, string(val)); err != nil {
return err
}

// make sure we can get the webhook
if _, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), webhookConfig.Name, metav1.GetOptions{}); err != nil {
return err
}

return nil
}

func createV1beta1MutationWebhook(client clientset.Interface, endpoint, convertedEndpoint string, convertedRules []admissionv1beta1.RuleWithOperations) error {
func createV1beta1MutationWebhook(etcdClient *clientv3.Client, etcdStoragePrefix string, client clientset.Interface, endpoint, convertedEndpoint string, convertedRules []admissionv1beta1.RuleWithOperations) error {
fail := admissionv1beta1.Fail
equivalent := admissionv1beta1.Equivalent
// Attaching Mutation webhook to API server
_, err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(context.TODO(), &admissionv1beta1.MutatingWebhookConfiguration{
webhookConfig := &admissionv1beta1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "mutation.integration.test"},
Webhooks: []admissionv1beta1.MutatingWebhook{
{
Expand Down Expand Up @@ -1568,8 +1593,26 @@ func createV1beta1MutationWebhook(client clientset.Interface, endpoint, converte
AdmissionReviewVersions: []string{"v1beta1"},
},
},
}, metav1.CreateOptions{})
return err
}
// run through to get defaulting
apisv1beta1.SetObjectDefaults_MutatingWebhookConfiguration(webhookConfig)
webhookConfig.TypeMeta.Kind = "MutatingWebhookConfiguration"
webhookConfig.TypeMeta.APIVersion = "admissionregistration.k8s.io/v1beta1"

// Attaching Mutation webhook to API server
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone)
key := path.Join("/", etcdStoragePrefix, "mutatingwebhookconfigurations", webhookConfig.Name)
val, _ := json.Marshal(webhookConfig)
if _, err := etcdClient.Put(ctx, key, string(val)); err != nil {
return err
}

// make sure we can get the webhook
if _, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), webhookConfig.Name, metav1.GetOptions{}); err != nil {
return err
}

return nil
}

func createV1ValidationWebhook(client clientset.Interface, endpoint, convertedEndpoint string, convertedRules []admissionv1.RuleWithOperations) error {
Expand Down
28 changes: 15 additions & 13 deletions test/integration/apiserver/admissionwebhook/broken_webhook_test.go
Expand Up @@ -22,7 +22,7 @@ import (
"testing"
"time"

admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestBrokenWebhook(t *testing.T) {
}

t.Logf("Creating Broken Webhook that will block all operations on all objects")
_, err = client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(context.TODO(), brokenWebhookConfig(brokenWebhookName), metav1.CreateOptions{})
_, err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(context.TODO(), brokenWebhookConfig(brokenWebhookName), metav1.CreateOptions{})
if err != nil {
t.Fatalf("Failed to register broken webhook: %v", err)
}
Expand Down Expand Up @@ -96,7 +96,7 @@ func TestBrokenWebhook(t *testing.T) {
}

t.Logf("Deleting the broken webhook to fix the cluster")
err = client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Delete(context.TODO(), brokenWebhookName, metav1.DeleteOptions{})
err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(context.TODO(), brokenWebhookName, metav1.DeleteOptions{})
if err != nil {
t.Fatalf("Failed to delete broken webhook: %v", err)
}
Expand Down Expand Up @@ -149,35 +149,37 @@ func exampleDeployment(name string) *appsv1.Deployment {
}
}

func brokenWebhookConfig(name string) *admissionregistrationv1beta1.ValidatingWebhookConfiguration {
func brokenWebhookConfig(name string) *admissionregistrationv1.ValidatingWebhookConfiguration {
var path string
failurePolicy := admissionregistrationv1beta1.Fail
return &admissionregistrationv1beta1.ValidatingWebhookConfiguration{
failurePolicy := admissionregistrationv1.Fail
return &admissionregistrationv1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Webhooks: []admissionregistrationv1beta1.ValidatingWebhook{
Webhooks: []admissionregistrationv1.ValidatingWebhook{
{
Name: "broken-webhook.k8s.io",
Rules: []admissionregistrationv1beta1.RuleWithOperations{{
Operations: []admissionregistrationv1beta1.OperationType{admissionregistrationv1beta1.OperationAll},
Rule: admissionregistrationv1beta1.Rule{
Rules: []admissionregistrationv1.RuleWithOperations{{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.OperationAll},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"*"},
APIVersions: []string{"*"},
Resources: []string{"*/*"},
},
}},
// This client config references a non existent service
// so it should always fail.
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{
Service: &admissionregistrationv1beta1.ServiceReference{
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Namespace: "default",
Name: "invalid-webhook-service",
Path: &path,
},
CABundle: nil,
},
FailurePolicy: &failurePolicy,
FailurePolicy: &failurePolicy,
SideEffects: &noSideEffects,
AdmissionReviewVersions: []string{"v1"},
},
},
}
Expand Down
19 changes: 10 additions & 9 deletions test/integration/apiserver/admissionwebhook/client_auth_test.go
Expand Up @@ -32,7 +32,7 @@ import (
"time"

"k8s.io/api/admission/v1beta1"
admissionv1beta1 "k8s.io/api/admissionregistration/v1beta1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -165,28 +165,29 @@ plugins:
t.Fatal(err)
}

fail := admissionv1beta1.Fail
mutatingCfg, err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(context.TODO(), &admissionv1beta1.MutatingWebhookConfiguration{
fail := admissionregistrationv1.Fail
mutatingCfg, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.TODO(), &admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "admission.integration.test"},
Webhooks: []admissionv1beta1.MutatingWebhook{{
Webhooks: []admissionregistrationv1.MutatingWebhook{{
Name: "admission.integration.test",
ClientConfig: admissionv1beta1.WebhookClientConfig{
ClientConfig: admissionregistrationv1.WebhookClientConfig{
URL: &webhookServer.URL,
CABundle: localhostCert,
},
Rules: []admissionv1beta1.RuleWithOperations{{
Operations: []admissionv1beta1.OperationType{admissionv1beta1.OperationAll},
Rule: admissionv1beta1.Rule{APIGroups: []string{""}, APIVersions: []string{"v1"}, Resources: []string{"pods"}},
Rules: []admissionregistrationv1.RuleWithOperations{{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.OperationAll},
Rule: admissionregistrationv1.Rule{APIGroups: []string{""}, APIVersions: []string{"v1"}, Resources: []string{"pods"}},
}},
FailurePolicy: &fail,
AdmissionReviewVersions: []string{"v1beta1"},
SideEffects: &noSideEffects,
}},
}, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
defer func() {
err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Delete(context.TODO(), mutatingCfg.GetName(), metav1.DeleteOptions{})
err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(context.TODO(), mutatingCfg.GetName(), metav1.DeleteOptions{})
if err != nil {
t.Fatal(err)
}
Expand Down
19 changes: 10 additions & 9 deletions test/integration/apiserver/admissionwebhook/load_balance_test.go
Expand Up @@ -31,7 +31,7 @@ import (
"time"

"k8s.io/api/admission/v1beta1"
admissionv1beta1 "k8s.io/api/admissionregistration/v1beta1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -114,28 +114,29 @@ func TestWebhookLoadBalance(t *testing.T) {
t.Fatal(err)
}

fail := admissionv1beta1.Fail
mutatingCfg, err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(context.TODO(), &admissionv1beta1.MutatingWebhookConfiguration{
fail := admissionregistrationv1.Fail
mutatingCfg, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.TODO(), &admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "admission.integration.test"},
Webhooks: []admissionv1beta1.MutatingWebhook{{
Webhooks: []admissionregistrationv1.MutatingWebhook{{
Name: "admission.integration.test",
ClientConfig: admissionv1beta1.WebhookClientConfig{
ClientConfig: admissionregistrationv1.WebhookClientConfig{
URL: &webhookURL,
CABundle: localhostCert,
},
Rules: []admissionv1beta1.RuleWithOperations{{
Operations: []admissionv1beta1.OperationType{admissionv1beta1.OperationAll},
Rule: admissionv1beta1.Rule{APIGroups: []string{""}, APIVersions: []string{"v1"}, Resources: []string{"pods"}},
Rules: []admissionregistrationv1.RuleWithOperations{{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.OperationAll},
Rule: admissionregistrationv1.Rule{APIGroups: []string{""}, APIVersions: []string{"v1"}, Resources: []string{"pods"}},
}},
FailurePolicy: &fail,
AdmissionReviewVersions: []string{"v1beta1"},
SideEffects: &noSideEffects,
}},
}, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
defer func() {
err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Delete(context.TODO(), mutatingCfg.GetName(), metav1.DeleteOptions{})
err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(context.TODO(), mutatingCfg.GetName(), metav1.DeleteOptions{})
if err != nil {
t.Fatal(err)
}
Expand Down