1/* 2Copyright 2016 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package services 18 19import ( 20 "fmt" 21 "io/ioutil" 22 "net" 23 "os" 24 25 "k8s.io/apiserver/pkg/storage/storagebackend" 26 27 utilerrors "k8s.io/apimachinery/pkg/util/errors" 28 apiserver "k8s.io/kubernetes/cmd/kube-apiserver/app" 29 "k8s.io/kubernetes/cmd/kube-apiserver/app/options" 30 "k8s.io/kubernetes/test/e2e/framework" 31) 32 33const ( 34 clusterIPRange = "10.0.0.1/24" 35 // This key is for testing purposes only and is not considered secure. 36 ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY----- 37MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49 38AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0 39/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg== 40-----END EC PRIVATE KEY-----` 41) 42 43// APIServer is a server which manages apiserver. 44type APIServer struct { 45 storageConfig storagebackend.Config 46 stopCh chan struct{} 47} 48 49// NewAPIServer creates an apiserver. 50func NewAPIServer(storageConfig storagebackend.Config) *APIServer { 51 return &APIServer{ 52 storageConfig: storageConfig, 53 stopCh: make(chan struct{}), 54 } 55} 56 57// Start starts the apiserver, returns when apiserver is ready. 58func (a *APIServer) Start() error { 59 const tokenFilePath = "known_tokens.csv" 60 61 o := options.NewServerRunOptions() 62 o.Etcd.StorageConfig = a.storageConfig 63 _, ipnet, err := net.ParseCIDR(clusterIPRange) 64 if err != nil { 65 return err 66 } 67 if len(framework.TestContext.RuntimeConfig) > 0 { 68 o.APIEnablement.RuntimeConfig = framework.TestContext.RuntimeConfig 69 } 70 o.SecureServing.BindAddress = net.ParseIP("127.0.0.1") 71 o.ServiceClusterIPRanges = ipnet.String() 72 o.AllowPrivileged = true 73 if err := generateTokenFile(tokenFilePath); err != nil { 74 return fmt.Errorf("failed to generate token file %s: %v", tokenFilePath, err) 75 } 76 o.Authentication.TokenFile.TokenFile = tokenFilePath 77 o.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount", "TaintNodesByCondition"} 78 79 saSigningKeyFile, err := ioutil.TempFile("/tmp", "insecure_test_key") 80 if err != nil { 81 return fmt.Errorf("create temp file failed: %v", err) 82 } 83 defer os.RemoveAll(saSigningKeyFile.Name()) 84 if err = ioutil.WriteFile(saSigningKeyFile.Name(), []byte(ecdsaPrivateKey), 0666); err != nil { 85 return fmt.Errorf("write file %s failed: %v", saSigningKeyFile.Name(), err) 86 } 87 o.ServiceAccountSigningKeyFile = saSigningKeyFile.Name() 88 o.Authentication.APIAudiences = []string{"https://foo.bar.example.com"} 89 o.Authentication.ServiceAccounts.Issuers = []string{"https://foo.bar.example.com"} 90 o.Authentication.ServiceAccounts.KeyFiles = []string{saSigningKeyFile.Name()} 91 92 errCh := make(chan error) 93 go func() { 94 defer close(errCh) 95 completedOptions, err := apiserver.Complete(o) 96 if err != nil { 97 errCh <- fmt.Errorf("set apiserver default options error: %v", err) 98 return 99 } 100 if errs := completedOptions.Validate(); len(errs) != 0 { 101 errCh <- fmt.Errorf("failed to validate ServerRunOptions: %v", utilerrors.NewAggregate(errs)) 102 return 103 } 104 105 err = apiserver.Run(completedOptions, a.stopCh) 106 if err != nil { 107 errCh <- fmt.Errorf("run apiserver error: %v", err) 108 return 109 } 110 }() 111 112 err = readinessCheck("apiserver", []string{getAPIServerHealthCheckURL()}, errCh) 113 if err != nil { 114 return err 115 } 116 return nil 117} 118 119// Stop stops the apiserver. Currently, there is no way to stop the apiserver. 120// The function is here only for completion. 121func (a *APIServer) Stop() error { 122 if a.stopCh != nil { 123 close(a.stopCh) 124 a.stopCh = nil 125 } 126 return nil 127} 128 129const apiserverName = "apiserver" 130 131// Name returns the name of APIServer. 132func (a *APIServer) Name() string { 133 return apiserverName 134} 135 136func getAPIServerClientURL() string { 137 return framework.TestContext.Host 138} 139 140func getAPIServerHealthCheckURL() string { 141 return framework.TestContext.Host + "/healthz" 142} 143 144func generateTokenFile(tokenFilePath string) error { 145 tokenFile := fmt.Sprintf("%s,kubelet,uid,system:masters\n", framework.TestContext.BearerToken) 146 return ioutil.WriteFile(tokenFilePath, []byte(tokenFile), 0644) 147} 148