k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/utils/apiserver/testapiserver.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package apiserver 18 19 import ( 20 "path" 21 "testing" 22 23 "github.com/google/uuid" 24 "k8s.io/apiserver/pkg/server/dynamiccertificates" 25 etcdserver "k8s.io/apiserver/pkg/storage/etcd3/testserver" 26 "k8s.io/apiserver/pkg/storage/storagebackend" 27 clientset "k8s.io/client-go/kubernetes" 28 "k8s.io/client-go/rest" 29 "k8s.io/client-go/tools/clientcmd" 30 "k8s.io/client-go/util/cert" 31 kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" 32 "k8s.io/kubernetes/test/utils/kubeconfig" 33 ) 34 35 // TestAPIServer provides access to a running apiserver instance. 36 type TestAPIServer struct { 37 // ClientSet is already initialized to access the apiserver as admin. 38 ClientSet clientset.Interface 39 40 // KubeConfigFile is the absolute path for a kube.config file that 41 // grants admin access to the apiserver. 42 KubeConfigFile string 43 } 44 45 // StartAPIServer runs etcd and apiserver in the background in the same 46 // process. All resources get released automatically when the test 47 // completes. If startup fails, the test gets aborted. 48 func StartAPITestServer(t *testing.T) TestAPIServer { 49 cfg := etcdserver.NewTestConfig(t) 50 etcdClient := etcdserver.RunEtcd(t, cfg) 51 storageConfig := storagebackend.NewDefaultConfig(path.Join(uuid.New().String(), "registry"), nil) 52 storageConfig.Transport.ServerList = etcdClient.Endpoints() 53 54 server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{}, storageConfig) 55 t.Cleanup(server.TearDownFn) 56 57 clientSet := clientset.NewForConfigOrDie(server.ClientConfig) 58 59 kubeConfigFile := writeKubeConfigForWardleServerToKASConnection(t, server.ClientConfig) 60 61 return TestAPIServer{ 62 ClientSet: clientSet, 63 KubeConfigFile: kubeConfigFile, 64 } 65 } 66 67 func writeKubeConfigForWardleServerToKASConnection(t *testing.T, kubeClientConfig *rest.Config) string { 68 // write a kubeconfig out for starting other API servers with delegated auth. remember, no in-cluster config 69 // the loopback client config uses a loopback cert with different SNI. We need to use the "real" 70 // cert, so we'll hope we aren't hacked during a unit test and instead load it from the server we started. 71 wardleToKASKubeClientConfig := rest.CopyConfig(kubeClientConfig) 72 73 servingCerts, _, err := cert.GetServingCertificatesForURL(wardleToKASKubeClientConfig.Host, "") 74 if err != nil { 75 t.Fatal(err) 76 } 77 encodedServing, err := cert.EncodeCertificates(servingCerts...) 78 if err != nil { 79 t.Fatal(err) 80 } 81 wardleToKASKubeClientConfig.CAData = encodedServing 82 83 for _, v := range servingCerts { 84 t.Logf("Client: Server public key is %v\n", dynamiccertificates.GetHumanCertDetail(v)) 85 } 86 certs, err := cert.ParseCertsPEM(wardleToKASKubeClientConfig.CAData) 87 if err != nil { 88 t.Fatal(err) 89 } 90 for _, curr := range certs { 91 t.Logf("CA bundle %v\n", dynamiccertificates.GetHumanCertDetail(curr)) 92 } 93 94 adminKubeConfig := kubeconfig.CreateKubeConfig(wardleToKASKubeClientConfig) 95 tmpDir := t.TempDir() 96 kubeConfigFile := path.Join(tmpDir, "kube.config") 97 if err := clientcmd.WriteToFile(*adminKubeConfig, kubeConfigFile); err != nil { 98 t.Fatal(err) 99 } 100 101 return kubeConfigFile 102 }