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