k8s.io/kubernetes@v1.29.3/test/e2e_node/services/apiserver.go (about) 1 /* 2 Copyright 2016 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 services 18 19 import ( 20 "fmt" 21 "os" 22 "testing" 23 24 utiltesting "k8s.io/client-go/util/testing" 25 26 "k8s.io/apiserver/pkg/storage/storagebackend" 27 netutils "k8s.io/utils/net" 28 29 utilerrors "k8s.io/apimachinery/pkg/util/errors" 30 apiserver "k8s.io/kubernetes/cmd/kube-apiserver/app" 31 "k8s.io/kubernetes/cmd/kube-apiserver/app/options" 32 "k8s.io/kubernetes/test/e2e/framework" 33 ) 34 35 const ( 36 clusterIPRange = "10.0.0.1/24" 37 // This key is for testing purposes only and is not considered secure. 38 ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY----- 39 MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49 40 AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0 41 /IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg== 42 -----END EC PRIVATE KEY-----` 43 ) 44 45 // APIServer is a server which manages apiserver. 46 type APIServer struct { 47 storageConfig storagebackend.Config 48 stopCh chan struct{} 49 } 50 51 // NewAPIServer creates an apiserver. 52 func NewAPIServer(storageConfig storagebackend.Config) *APIServer { 53 return &APIServer{ 54 storageConfig: storageConfig, 55 stopCh: make(chan struct{}), 56 } 57 } 58 59 // Start starts the apiserver, returns when apiserver is ready. 60 func (a *APIServer) Start() error { 61 const tokenFilePath = "known_tokens.csv" 62 63 o := options.NewServerRunOptions() 64 o.Etcd.StorageConfig = a.storageConfig 65 _, ipnet, err := netutils.ParseCIDRSloppy(clusterIPRange) 66 if err != nil { 67 return err 68 } 69 if len(framework.TestContext.RuntimeConfig) > 0 { 70 o.APIEnablement.RuntimeConfig = framework.TestContext.RuntimeConfig 71 } 72 o.SecureServing.BindAddress = netutils.ParseIPSloppy("127.0.0.1") 73 o.ServiceClusterIPRanges = ipnet.String() 74 o.AllowPrivileged = true 75 if err := generateTokenFile(tokenFilePath); err != nil { 76 return fmt.Errorf("failed to generate token file %s: %w", tokenFilePath, err) 77 } 78 o.Authentication.TokenFile.TokenFile = tokenFilePath 79 o.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount", "TaintNodesByCondition"} 80 81 saSigningKeyFile, err := os.CreateTemp("/tmp", "insecure_test_key") 82 if err != nil { 83 return fmt.Errorf("create temp file failed: %w", err) 84 } 85 defer utiltesting.CloseAndRemove(&testing.T{}, saSigningKeyFile) 86 if err = os.WriteFile(saSigningKeyFile.Name(), []byte(ecdsaPrivateKey), 0666); err != nil { 87 return fmt.Errorf("write file %s failed: %w", saSigningKeyFile.Name(), err) 88 } 89 o.ServiceAccountSigningKeyFile = saSigningKeyFile.Name() 90 o.Authentication.APIAudiences = []string{"https://foo.bar.example.com"} 91 o.Authentication.ServiceAccounts.Issuers = []string{"https://foo.bar.example.com"} 92 o.Authentication.ServiceAccounts.KeyFiles = []string{saSigningKeyFile.Name()} 93 94 o.KubeletConfig.PreferredAddressTypes = []string{"InternalIP"} 95 96 errCh := make(chan error) 97 go func() { 98 defer close(errCh) 99 completedOptions, err := o.Complete() 100 if err != nil { 101 errCh <- fmt.Errorf("set apiserver default options error: %w", err) 102 return 103 } 104 if errs := completedOptions.Validate(); len(errs) != 0 { 105 errCh <- fmt.Errorf("failed to validate ServerRunOptions: %v", utilerrors.NewAggregate(errs)) 106 return 107 } 108 109 err = apiserver.Run(completedOptions, a.stopCh) 110 if err != nil { 111 errCh <- fmt.Errorf("run apiserver error: %w", err) 112 return 113 } 114 }() 115 116 err = readinessCheck("apiserver", []string{getAPIServerHealthCheckURL()}, errCh) 117 if err != nil { 118 return err 119 } 120 return nil 121 } 122 123 // Stop stops the apiserver. Currently, there is no way to stop the apiserver. 124 // The function is here only for completion. 125 func (a *APIServer) Stop() error { 126 if a.stopCh != nil { 127 close(a.stopCh) 128 a.stopCh = nil 129 } 130 return nil 131 } 132 133 const apiserverName = "apiserver" 134 135 // Name returns the name of APIServer. 136 func (a *APIServer) Name() string { 137 return apiserverName 138 } 139 140 func getAPIServerClientURL() string { 141 return framework.TestContext.Host 142 } 143 144 func getAPIServerHealthCheckURL() string { 145 return framework.TestContext.Host + "/healthz" 146 } 147 148 func generateTokenFile(tokenFilePath string) error { 149 tokenFile := fmt.Sprintf("%s,kubelet,uid,system:masters\n", framework.TestContext.BearerToken) 150 return os.WriteFile(tokenFilePath, []byte(tokenFile), 0644) 151 }