util.go 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package framework
  14. import (
  15. "bytes"
  16. "context"
  17. "encoding/json"
  18. "fmt"
  19. "io"
  20. "io/ioutil"
  21. "math/rand"
  22. "net"
  23. "net/http"
  24. "net/url"
  25. "os"
  26. "os/exec"
  27. "path"
  28. "sort"
  29. "strconv"
  30. "strings"
  31. "sync"
  32. "syscall"
  33. "time"
  34. "golang.org/x/net/websocket"
  35. "k8s.io/klog"
  36. "github.com/onsi/ginkgo"
  37. "github.com/onsi/gomega"
  38. gomegatypes "github.com/onsi/gomega/types"
  39. appsv1 "k8s.io/api/apps/v1"
  40. v1 "k8s.io/api/core/v1"
  41. apierrors "k8s.io/apimachinery/pkg/api/errors"
  42. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  43. "k8s.io/apimachinery/pkg/fields"
  44. "k8s.io/apimachinery/pkg/labels"
  45. "k8s.io/apimachinery/pkg/runtime"
  46. "k8s.io/apimachinery/pkg/runtime/schema"
  47. "k8s.io/apimachinery/pkg/util/sets"
  48. "k8s.io/apimachinery/pkg/util/uuid"
  49. "k8s.io/apimachinery/pkg/util/wait"
  50. utilyaml "k8s.io/apimachinery/pkg/util/yaml"
  51. clientset "k8s.io/client-go/kubernetes"
  52. "k8s.io/client-go/kubernetes/scheme"
  53. "k8s.io/client-go/rest"
  54. restclient "k8s.io/client-go/rest"
  55. scaleclient "k8s.io/client-go/scale"
  56. "k8s.io/client-go/tools/clientcmd"
  57. clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
  58. watchtools "k8s.io/client-go/tools/watch"
  59. podutil "k8s.io/kubernetes/pkg/api/v1/pod"
  60. "k8s.io/kubernetes/pkg/client/conditions"
  61. "k8s.io/kubernetes/pkg/controller"
  62. "k8s.io/kubernetes/pkg/master/ports"
  63. taintutils "k8s.io/kubernetes/pkg/util/taints"
  64. testutils "k8s.io/kubernetes/test/utils"
  65. imageutils "k8s.io/kubernetes/test/utils/image"
  66. uexec "k8s.io/utils/exec"
  67. // TODO: Remove the following imports (ref: https://github.com/kubernetes/kubernetes/issues/81245)
  68. e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
  69. e2emetrics "k8s.io/kubernetes/test/e2e/framework/metrics"
  70. e2enode "k8s.io/kubernetes/test/e2e/framework/node"
  71. e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
  72. e2eresource "k8s.io/kubernetes/test/e2e/framework/resource"
  73. e2essh "k8s.io/kubernetes/test/e2e/framework/ssh"
  74. )
  75. const (
  76. // PodListTimeout is how long to wait for the pod to be listable.
  77. PodListTimeout = time.Minute
  78. // PodStartTimeout is how long to wait for the pod to be started.
  79. PodStartTimeout = 5 * time.Minute
  80. // PodStartShortTimeout is same as `PodStartTimeout` to wait for the pod to be started, but shorter.
  81. // Use it case by case when we are sure pod start will not be delayed.
  82. // minutes by slow docker pulls or something else.
  83. PodStartShortTimeout = 2 * time.Minute
  84. // PodDeleteTimeout is how long to wait for a pod to be deleted.
  85. PodDeleteTimeout = 5 * time.Minute
  86. // PodGetTimeout is how long to wait for a pod to be got.
  87. PodGetTimeout = 2 * time.Minute
  88. // PodEventTimeout is how much we wait for a pod event to occur.
  89. PodEventTimeout = 2 * time.Minute
  90. // NamespaceCleanupTimeout is how long to wait for the namespace to be deleted.
  91. // If there are any orphaned namespaces to clean up, this test is running
  92. // on a long lived cluster. A long wait here is preferably to spurious test
  93. // failures caused by leaked resources from a previous test run.
  94. NamespaceCleanupTimeout = 15 * time.Minute
  95. // ServiceStartTimeout is how long to wait for a service endpoint to be resolvable.
  96. ServiceStartTimeout = 3 * time.Minute
  97. // Poll is how often to Poll pods, nodes and claims.
  98. Poll = 2 * time.Second
  99. // PollShortTimeout is the short timeout value in polling.
  100. PollShortTimeout = 1 * time.Minute
  101. // ServiceAccountProvisionTimeout is how long to wait for a service account to be provisioned.
  102. // service accounts are provisioned after namespace creation
  103. // a service account is required to support pod creation in a namespace as part of admission control
  104. ServiceAccountProvisionTimeout = 2 * time.Minute
  105. // SingleCallTimeout is how long to try single API calls (like 'get' or 'list'). Used to prevent
  106. // transient failures from failing tests.
  107. // TODO: client should not apply this timeout to Watch calls. Increased from 30s until that is fixed.
  108. SingleCallTimeout = 5 * time.Minute
  109. // NodeReadyInitialTimeout is how long nodes have to be "ready" when a test begins. They should already
  110. // be "ready" before the test starts, so this is small.
  111. NodeReadyInitialTimeout = 20 * time.Second
  112. // PodReadyBeforeTimeout is how long pods have to be "ready" when a test begins.
  113. PodReadyBeforeTimeout = 5 * time.Minute
  114. // ClaimProvisionShortTimeout is same as `ClaimProvisionTimeout` to wait for claim to be dynamically provisioned, but shorter.
  115. // Use it case by case when we are sure this timeout is enough.
  116. ClaimProvisionShortTimeout = 1 * time.Minute
  117. // ClaimDeletingTimeout is How long claims have to become deleted.
  118. ClaimDeletingTimeout = 3 * time.Minute
  119. // RecreateNodeReadyAgainTimeout is how long a node is allowed to become "Ready" after it is recreated before
  120. // the test is considered failed.
  121. RecreateNodeReadyAgainTimeout = 10 * time.Minute
  122. // RestartNodeReadyAgainTimeout is how long a node is allowed to become "Ready" after it is restarted before
  123. // the test is considered failed.
  124. RestartNodeReadyAgainTimeout = 5 * time.Minute
  125. // RestartPodReadyAgainTimeout is how long a pod is allowed to become "running" and "ready" after a node
  126. // restart before test is considered failed.
  127. RestartPodReadyAgainTimeout = 5 * time.Minute
  128. // SnapshotCreateTimeout is how long for snapshot to create snapshotContent.
  129. SnapshotCreateTimeout = 5 * time.Minute
  130. // Number of objects that gc can delete in a second.
  131. // GC issues 2 requestes for single delete.
  132. gcThroughput = 10
  133. // Minimal number of nodes for the cluster to be considered large.
  134. largeClusterThreshold = 100
  135. // TODO(justinsb): Avoid hardcoding this.
  136. awsMasterIP = "172.20.0.9"
  137. // ssh port
  138. sshPort = "22"
  139. )
  140. var (
  141. // ClaimProvisionTimeout is how long claims have to become dynamically provisioned.
  142. ClaimProvisionTimeout = 5 * time.Minute
  143. // BusyBoxImage is the image URI of BusyBox.
  144. BusyBoxImage = imageutils.GetE2EImage(imageutils.BusyBox)
  145. // AgnHostImage is the image URI of AgnHost
  146. AgnHostImage = imageutils.GetE2EImage(imageutils.Agnhost)
  147. // ProvidersWithSSH are those providers where each node is accessible with SSH
  148. ProvidersWithSSH = []string{"gce", "gke", "aws", "local"}
  149. // ServeHostnameImage is a serve hostname image name.
  150. ServeHostnameImage = imageutils.GetE2EImage(imageutils.Agnhost)
  151. )
  152. // RunID is a unique identifier of the e2e run.
  153. // Beware that this ID is not the same for all tests in the e2e run, because each Ginkgo node creates it separately.
  154. var RunID = uuid.NewUUID()
  155. // CreateTestingNSFn is a func that is responsible for creating namespace used for executing e2e tests.
  156. type CreateTestingNSFn func(baseName string, c clientset.Interface, labels map[string]string) (*v1.Namespace, error)
  157. // GetMasterHost returns a hostname of a master.
  158. func GetMasterHost() string {
  159. masterURL, err := url.Parse(TestContext.Host)
  160. ExpectNoError(err)
  161. return masterURL.Hostname()
  162. }
  163. // ProviderIs returns true if the provider is included is the providers. Otherwise false.
  164. func ProviderIs(providers ...string) bool {
  165. for _, provider := range providers {
  166. if strings.EqualFold(provider, TestContext.Provider) {
  167. return true
  168. }
  169. }
  170. return false
  171. }
  172. // MasterOSDistroIs returns true if the master OS distro is included in the supportedMasterOsDistros. Otherwise false.
  173. func MasterOSDistroIs(supportedMasterOsDistros ...string) bool {
  174. for _, distro := range supportedMasterOsDistros {
  175. if strings.EqualFold(distro, TestContext.MasterOSDistro) {
  176. return true
  177. }
  178. }
  179. return false
  180. }
  181. // NodeOSDistroIs returns true if the node OS distro is included in the supportedNodeOsDistros. Otherwise false.
  182. func NodeOSDistroIs(supportedNodeOsDistros ...string) bool {
  183. for _, distro := range supportedNodeOsDistros {
  184. if strings.EqualFold(distro, TestContext.NodeOSDistro) {
  185. return true
  186. }
  187. }
  188. return false
  189. }
  190. // DeleteNamespaces deletes all namespaces that match the given delete and skip filters.
  191. // Filter is by simple strings.Contains; first skip filter, then delete filter.
  192. // Returns the list of deleted namespaces or an error.
  193. func DeleteNamespaces(c clientset.Interface, deleteFilter, skipFilter []string) ([]string, error) {
  194. ginkgo.By("Deleting namespaces")
  195. nsList, err := c.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
  196. ExpectNoError(err, "Failed to get namespace list")
  197. var deleted []string
  198. var wg sync.WaitGroup
  199. OUTER:
  200. for _, item := range nsList.Items {
  201. if skipFilter != nil {
  202. for _, pattern := range skipFilter {
  203. if strings.Contains(item.Name, pattern) {
  204. continue OUTER
  205. }
  206. }
  207. }
  208. if deleteFilter != nil {
  209. var shouldDelete bool
  210. for _, pattern := range deleteFilter {
  211. if strings.Contains(item.Name, pattern) {
  212. shouldDelete = true
  213. break
  214. }
  215. }
  216. if !shouldDelete {
  217. continue OUTER
  218. }
  219. }
  220. wg.Add(1)
  221. deleted = append(deleted, item.Name)
  222. go func(nsName string) {
  223. defer wg.Done()
  224. defer ginkgo.GinkgoRecover()
  225. gomega.Expect(c.CoreV1().Namespaces().Delete(context.TODO(), nsName, nil)).To(gomega.Succeed())
  226. Logf("namespace : %v api call to delete is complete ", nsName)
  227. }(item.Name)
  228. }
  229. wg.Wait()
  230. return deleted, nil
  231. }
  232. // WaitForNamespacesDeleted waits for the namespaces to be deleted.
  233. func WaitForNamespacesDeleted(c clientset.Interface, namespaces []string, timeout time.Duration) error {
  234. ginkgo.By("Waiting for namespaces to vanish")
  235. nsMap := map[string]bool{}
  236. for _, ns := range namespaces {
  237. nsMap[ns] = true
  238. }
  239. //Now POLL until all namespaces have been eradicated.
  240. return wait.Poll(2*time.Second, timeout,
  241. func() (bool, error) {
  242. nsList, err := c.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
  243. if err != nil {
  244. return false, err
  245. }
  246. for _, item := range nsList.Items {
  247. if _, ok := nsMap[item.Name]; ok {
  248. return false, nil
  249. }
  250. }
  251. return true, nil
  252. })
  253. }
  254. func waitForServiceAccountInNamespace(c clientset.Interface, ns, serviceAccountName string, timeout time.Duration) error {
  255. w, err := c.CoreV1().ServiceAccounts(ns).Watch(context.TODO(), metav1.SingleObject(metav1.ObjectMeta{Name: serviceAccountName}))
  256. if err != nil {
  257. return err
  258. }
  259. ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout)
  260. defer cancel()
  261. _, err = watchtools.UntilWithoutRetry(ctx, w, conditions.ServiceAccountHasSecrets)
  262. return err
  263. }
  264. // WaitForDefaultServiceAccountInNamespace waits for the default service account to be provisioned
  265. // the default service account is what is associated with pods when they do not specify a service account
  266. // as a result, pods are not able to be provisioned in a namespace until the service account is provisioned
  267. func WaitForDefaultServiceAccountInNamespace(c clientset.Interface, namespace string) error {
  268. return waitForServiceAccountInNamespace(c, namespace, "default", ServiceAccountProvisionTimeout)
  269. }
  270. // WaitForPersistentVolumeDeleted waits for a PersistentVolume to get deleted or until timeout occurs, whichever comes first.
  271. func WaitForPersistentVolumeDeleted(c clientset.Interface, pvName string, Poll, timeout time.Duration) error {
  272. Logf("Waiting up to %v for PersistentVolume %s to get deleted", timeout, pvName)
  273. for start := time.Now(); time.Since(start) < timeout; time.Sleep(Poll) {
  274. pv, err := c.CoreV1().PersistentVolumes().Get(context.TODO(), pvName, metav1.GetOptions{})
  275. if err == nil {
  276. Logf("PersistentVolume %s found and phase=%s (%v)", pvName, pv.Status.Phase, time.Since(start))
  277. continue
  278. }
  279. if apierrors.IsNotFound(err) {
  280. Logf("PersistentVolume %s was removed", pvName)
  281. return nil
  282. }
  283. Logf("Get persistent volume %s in failed, ignoring for %v: %v", pvName, Poll, err)
  284. }
  285. return fmt.Errorf("PersistentVolume %s still exists within %v", pvName, timeout)
  286. }
  287. // findAvailableNamespaceName random namespace name starting with baseName.
  288. func findAvailableNamespaceName(baseName string, c clientset.Interface) (string, error) {
  289. var name string
  290. err := wait.PollImmediate(Poll, 30*time.Second, func() (bool, error) {
  291. name = fmt.Sprintf("%v-%v", baseName, RandomSuffix())
  292. _, err := c.CoreV1().Namespaces().Get(context.TODO(), name, metav1.GetOptions{})
  293. if err == nil {
  294. // Already taken
  295. return false, nil
  296. }
  297. if apierrors.IsNotFound(err) {
  298. return true, nil
  299. }
  300. Logf("Unexpected error while getting namespace: %v", err)
  301. return false, nil
  302. })
  303. return name, err
  304. }
  305. // CreateTestingNS should be used by every test, note that we append a common prefix to the provided test name.
  306. // Please see NewFramework instead of using this directly.
  307. func CreateTestingNS(baseName string, c clientset.Interface, labels map[string]string) (*v1.Namespace, error) {
  308. if labels == nil {
  309. labels = map[string]string{}
  310. }
  311. labels["e2e-run"] = string(RunID)
  312. // We don't use ObjectMeta.GenerateName feature, as in case of API call
  313. // failure we don't know whether the namespace was created and what is its
  314. // name.
  315. name, err := findAvailableNamespaceName(baseName, c)
  316. if err != nil {
  317. return nil, err
  318. }
  319. namespaceObj := &v1.Namespace{
  320. ObjectMeta: metav1.ObjectMeta{
  321. Name: name,
  322. Namespace: "",
  323. Labels: labels,
  324. },
  325. Status: v1.NamespaceStatus{},
  326. }
  327. // Be robust about making the namespace creation call.
  328. var got *v1.Namespace
  329. if err := wait.PollImmediate(Poll, 30*time.Second, func() (bool, error) {
  330. var err error
  331. got, err = c.CoreV1().Namespaces().Create(context.TODO(), namespaceObj, metav1.CreateOptions{})
  332. if err != nil {
  333. Logf("Unexpected error while creating namespace: %v", err)
  334. return false, nil
  335. }
  336. return true, nil
  337. }); err != nil {
  338. return nil, err
  339. }
  340. if TestContext.VerifyServiceAccount {
  341. if err := WaitForDefaultServiceAccountInNamespace(c, got.Name); err != nil {
  342. // Even if we fail to create serviceAccount in the namespace,
  343. // we have successfully create a namespace.
  344. // So, return the created namespace.
  345. return got, err
  346. }
  347. }
  348. return got, nil
  349. }
  350. // CheckTestingNSDeletedExcept checks whether all e2e based existing namespaces are in the Terminating state
  351. // and waits until they are finally deleted. It ignores namespace skip.
  352. func CheckTestingNSDeletedExcept(c clientset.Interface, skip string) error {
  353. // TODO: Since we don't have support for bulk resource deletion in the API,
  354. // while deleting a namespace we are deleting all objects from that namespace
  355. // one by one (one deletion == one API call). This basically exposes us to
  356. // throttling - currently controller-manager has a limit of max 20 QPS.
  357. // Once #10217 is implemented and used in namespace-controller, deleting all
  358. // object from a given namespace should be much faster and we will be able
  359. // to lower this timeout.
  360. // However, now Density test is producing ~26000 events and Load capacity test
  361. // is producing ~35000 events, thus assuming there are no other requests it will
  362. // take ~30 minutes to fully delete the namespace. Thus I'm setting it to 60
  363. // minutes to avoid any timeouts here.
  364. timeout := 60 * time.Minute
  365. Logf("Waiting for terminating namespaces to be deleted...")
  366. for start := time.Now(); time.Since(start) < timeout; time.Sleep(15 * time.Second) {
  367. namespaces, err := c.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
  368. if err != nil {
  369. Logf("Listing namespaces failed: %v", err)
  370. continue
  371. }
  372. terminating := 0
  373. for _, ns := range namespaces.Items {
  374. if strings.HasPrefix(ns.ObjectMeta.Name, "e2e-tests-") && ns.ObjectMeta.Name != skip {
  375. if ns.Status.Phase == v1.NamespaceActive {
  376. return fmt.Errorf("Namespace %s is active", ns.ObjectMeta.Name)
  377. }
  378. terminating++
  379. }
  380. }
  381. if terminating == 0 {
  382. return nil
  383. }
  384. }
  385. return fmt.Errorf("Waiting for terminating namespaces to be deleted timed out")
  386. }
  387. // WaitForService waits until the service appears (exist == true), or disappears (exist == false)
  388. func WaitForService(c clientset.Interface, namespace, name string, exist bool, interval, timeout time.Duration) error {
  389. err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  390. _, err := c.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})
  391. switch {
  392. case err == nil:
  393. Logf("Service %s in namespace %s found.", name, namespace)
  394. return exist, nil
  395. case apierrors.IsNotFound(err):
  396. Logf("Service %s in namespace %s disappeared.", name, namespace)
  397. return !exist, nil
  398. case !testutils.IsRetryableAPIError(err):
  399. Logf("Non-retryable failure while getting service.")
  400. return false, err
  401. default:
  402. Logf("Get service %s in namespace %s failed: %v", name, namespace, err)
  403. return false, nil
  404. }
  405. })
  406. if err != nil {
  407. stateMsg := map[bool]string{true: "to appear", false: "to disappear"}
  408. return fmt.Errorf("error waiting for service %s/%s %s: %v", namespace, name, stateMsg[exist], err)
  409. }
  410. return nil
  411. }
  412. //WaitForServiceEndpointsNum waits until the amount of endpoints that implement service to expectNum.
  413. func WaitForServiceEndpointsNum(c clientset.Interface, namespace, serviceName string, expectNum int, interval, timeout time.Duration) error {
  414. return wait.Poll(interval, timeout, func() (bool, error) {
  415. Logf("Waiting for amount of service:%s endpoints to be %d", serviceName, expectNum)
  416. list, err := c.CoreV1().Endpoints(namespace).List(context.TODO(), metav1.ListOptions{})
  417. if err != nil {
  418. return false, err
  419. }
  420. for _, e := range list.Items {
  421. if e.Name == serviceName && countEndpointsNum(&e) == expectNum {
  422. return true, nil
  423. }
  424. }
  425. return false, nil
  426. })
  427. }
  428. func countEndpointsNum(e *v1.Endpoints) int {
  429. num := 0
  430. for _, sub := range e.Subsets {
  431. num += len(sub.Addresses)
  432. }
  433. return num
  434. }
  435. // restclientConfig returns a config holds the information needed to build connection to kubernetes clusters.
  436. func restclientConfig(kubeContext string) (*clientcmdapi.Config, error) {
  437. Logf(">>> kubeConfig: %s", TestContext.KubeConfig)
  438. if TestContext.KubeConfig == "" {
  439. return nil, fmt.Errorf("KubeConfig must be specified to load client config")
  440. }
  441. c, err := clientcmd.LoadFromFile(TestContext.KubeConfig)
  442. if err != nil {
  443. return nil, fmt.Errorf("error loading KubeConfig: %v", err.Error())
  444. }
  445. if kubeContext != "" {
  446. Logf(">>> kubeContext: %s", kubeContext)
  447. c.CurrentContext = kubeContext
  448. }
  449. return c, nil
  450. }
  451. // ClientConfigGetter is a func that returns getter to return a config.
  452. type ClientConfigGetter func() (*restclient.Config, error)
  453. // LoadConfig returns a config for a rest client with the UserAgent set to include the current test name.
  454. func LoadConfig() (config *restclient.Config, err error) {
  455. defer func() {
  456. if err == nil && config != nil {
  457. testDesc := ginkgo.CurrentGinkgoTestDescription()
  458. if len(testDesc.ComponentTexts) > 0 {
  459. componentTexts := strings.Join(testDesc.ComponentTexts, " ")
  460. config.UserAgent = fmt.Sprintf("%s -- %s", rest.DefaultKubernetesUserAgent(), componentTexts)
  461. }
  462. }
  463. }()
  464. if TestContext.NodeE2E {
  465. // This is a node e2e test, apply the node e2e configuration
  466. return &restclient.Config{Host: TestContext.Host}, nil
  467. }
  468. c, err := restclientConfig(TestContext.KubeContext)
  469. if err != nil {
  470. if TestContext.KubeConfig == "" {
  471. return restclient.InClusterConfig()
  472. }
  473. return nil, err
  474. }
  475. // In case Host is not set in TestContext, sets it as
  476. // CurrentContext Server for k8s API client to connect to.
  477. if TestContext.Host == "" && c.Clusters != nil {
  478. currentContext, ok := c.Clusters[c.CurrentContext]
  479. if ok {
  480. TestContext.Host = currentContext.Server
  481. }
  482. }
  483. return clientcmd.NewDefaultClientConfig(*c, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: TestContext.Host}}).ClientConfig()
  484. }
  485. // LoadClientset returns clientset for connecting to kubernetes clusters.
  486. func LoadClientset() (*clientset.Clientset, error) {
  487. config, err := LoadConfig()
  488. if err != nil {
  489. return nil, fmt.Errorf("error creating client: %v", err.Error())
  490. }
  491. return clientset.NewForConfig(config)
  492. }
  493. // RandomSuffix provides a random sequence to append to pods,services,rcs.
  494. func RandomSuffix() string {
  495. return strconv.Itoa(rand.Intn(10000))
  496. }
  497. // Cleanup stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped.
  498. func Cleanup(filePath, ns string, selectors ...string) {
  499. ginkgo.By("using delete to clean up resources")
  500. var nsArg string
  501. if ns != "" {
  502. nsArg = fmt.Sprintf("--namespace=%s", ns)
  503. }
  504. RunKubectlOrDie(ns, "delete", "--grace-period=0", "-f", filePath, nsArg)
  505. AssertCleanup(ns, selectors...)
  506. }
  507. // AssertCleanup asserts that cleanup of a namespace wrt selectors occurred.
  508. func AssertCleanup(ns string, selectors ...string) {
  509. var nsArg string
  510. if ns != "" {
  511. nsArg = fmt.Sprintf("--namespace=%s", ns)
  512. }
  513. var e error
  514. verifyCleanupFunc := func() (bool, error) {
  515. e = nil
  516. for _, selector := range selectors {
  517. resources := RunKubectlOrDie(ns, "get", "rc,svc", "-l", selector, "--no-headers", nsArg)
  518. if resources != "" {
  519. e = fmt.Errorf("Resources left running after stop:\n%s", resources)
  520. return false, nil
  521. }
  522. pods := RunKubectlOrDie(ns, "get", "pods", "-l", selector, nsArg, "-o", "go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}{{ \"\\n\" }}{{ end }}{{ end }}")
  523. if pods != "" {
  524. e = fmt.Errorf("Pods left unterminated after stop:\n%s", pods)
  525. return false, nil
  526. }
  527. }
  528. return true, nil
  529. }
  530. err := wait.PollImmediate(500*time.Millisecond, 1*time.Minute, verifyCleanupFunc)
  531. if err != nil {
  532. Failf(e.Error())
  533. }
  534. }
  535. // LookForStringInPodExec looks for the given string in the output of a command
  536. // executed in a specific pod container.
  537. // TODO(alejandrox1): move to pod/ subpkg once kubectl methods are refactored.
  538. func LookForStringInPodExec(ns, podName string, command []string, expectedString string, timeout time.Duration) (result string, err error) {
  539. return LookForString(expectedString, timeout, func() string {
  540. // use the first container
  541. args := []string{"exec", podName, fmt.Sprintf("--namespace=%v", ns), "--"}
  542. args = append(args, command...)
  543. return RunKubectlOrDie(ns, args...)
  544. })
  545. }
  546. // LookForString looks for the given string in the output of fn, repeatedly calling fn until
  547. // the timeout is reached or the string is found. Returns last log and possibly
  548. // error if the string was not found.
  549. // TODO(alejandrox1): move to pod/ subpkg once kubectl methods are refactored.
  550. func LookForString(expectedString string, timeout time.Duration, fn func() string) (result string, err error) {
  551. for t := time.Now(); time.Since(t) < timeout; time.Sleep(Poll) {
  552. result = fn()
  553. if strings.Contains(result, expectedString) {
  554. return
  555. }
  556. }
  557. err = fmt.Errorf("Failed to find \"%s\", last result: \"%s\"", expectedString, result)
  558. return
  559. }
  560. // KubectlBuilder is used to build, customize and execute a kubectl Command.
  561. // Add more functions to customize the builder as needed.
  562. type KubectlBuilder struct {
  563. cmd *exec.Cmd
  564. timeout <-chan time.Time
  565. }
  566. // NewKubectlCommand returns a KubectlBuilder for running kubectl.
  567. func NewKubectlCommand(namespace string, args ...string) *KubectlBuilder {
  568. b := new(KubectlBuilder)
  569. tk := e2ekubectl.NewTestKubeconfig(TestContext.CertDir, TestContext.Host, TestContext.KubeConfig, TestContext.KubeContext, TestContext.KubectlPath, namespace)
  570. b.cmd = tk.KubectlCmd(args...)
  571. return b
  572. }
  573. // WithEnv sets the given environment and returns itself.
  574. func (b *KubectlBuilder) WithEnv(env []string) *KubectlBuilder {
  575. b.cmd.Env = env
  576. return b
  577. }
  578. // WithTimeout sets the given timeout and returns itself.
  579. func (b *KubectlBuilder) WithTimeout(t <-chan time.Time) *KubectlBuilder {
  580. b.timeout = t
  581. return b
  582. }
  583. // WithStdinData sets the given data to stdin and returns itself.
  584. func (b KubectlBuilder) WithStdinData(data string) *KubectlBuilder {
  585. b.cmd.Stdin = strings.NewReader(data)
  586. return &b
  587. }
  588. // WithStdinReader sets the given reader and returns itself.
  589. func (b KubectlBuilder) WithStdinReader(reader io.Reader) *KubectlBuilder {
  590. b.cmd.Stdin = reader
  591. return &b
  592. }
  593. // ExecOrDie runs the kubectl executable or dies if error occurs.
  594. func (b KubectlBuilder) ExecOrDie(namespace string) string {
  595. str, err := b.Exec()
  596. // In case of i/o timeout error, try talking to the apiserver again after 2s before dying.
  597. // Note that we're still dying after retrying so that we can get visibility to triage it further.
  598. if isTimeout(err) {
  599. Logf("Hit i/o timeout error, talking to the server 2s later to see if it's temporary.")
  600. time.Sleep(2 * time.Second)
  601. retryStr, retryErr := RunKubectl(namespace, "version")
  602. Logf("stdout: %q", retryStr)
  603. Logf("err: %v", retryErr)
  604. }
  605. ExpectNoError(err)
  606. return str
  607. }
  608. func isTimeout(err error) bool {
  609. switch err := err.(type) {
  610. case *url.Error:
  611. if err, ok := err.Err.(net.Error); ok && err.Timeout() {
  612. return true
  613. }
  614. case net.Error:
  615. if err.Timeout() {
  616. return true
  617. }
  618. }
  619. return false
  620. }
  621. // Exec runs the kubectl executable.
  622. func (b KubectlBuilder) Exec() (string, error) {
  623. var stdout, stderr bytes.Buffer
  624. cmd := b.cmd
  625. cmd.Stdout, cmd.Stderr = &stdout, &stderr
  626. Logf("Running '%s %s'", cmd.Path, strings.Join(cmd.Args[1:], " ")) // skip arg[0] as it is printed separately
  627. if err := cmd.Start(); err != nil {
  628. return "", fmt.Errorf("error starting %v:\nCommand stdout:\n%v\nstderr:\n%v\nerror:\n%v", cmd, cmd.Stdout, cmd.Stderr, err)
  629. }
  630. errCh := make(chan error, 1)
  631. go func() {
  632. errCh <- cmd.Wait()
  633. }()
  634. select {
  635. case err := <-errCh:
  636. if err != nil {
  637. var rc = 127
  638. if ee, ok := err.(*exec.ExitError); ok {
  639. rc = int(ee.Sys().(syscall.WaitStatus).ExitStatus())
  640. Logf("rc: %d", rc)
  641. }
  642. return "", uexec.CodeExitError{
  643. Err: fmt.Errorf("error running %v:\nCommand stdout:\n%v\nstderr:\n%v\nerror:\n%v", cmd, cmd.Stdout, cmd.Stderr, err),
  644. Code: rc,
  645. }
  646. }
  647. case <-b.timeout:
  648. b.cmd.Process.Kill()
  649. return "", fmt.Errorf("timed out waiting for command %v:\nCommand stdout:\n%v\nstderr:\n%v", cmd, cmd.Stdout, cmd.Stderr)
  650. }
  651. Logf("stderr: %q", stderr.String())
  652. Logf("stdout: %q", stdout.String())
  653. return stdout.String(), nil
  654. }
  655. // RunKubectlOrDie is a convenience wrapper over kubectlBuilder
  656. func RunKubectlOrDie(namespace string, args ...string) string {
  657. return NewKubectlCommand(namespace, args...).ExecOrDie(namespace)
  658. }
  659. // RunKubectl is a convenience wrapper over kubectlBuilder
  660. func RunKubectl(namespace string, args ...string) (string, error) {
  661. return NewKubectlCommand(namespace, args...).Exec()
  662. }
  663. // RunKubectlOrDieInput is a convenience wrapper over kubectlBuilder that takes input to stdin
  664. func RunKubectlOrDieInput(namespace string, data string, args ...string) string {
  665. return NewKubectlCommand(namespace, args...).WithStdinData(data).ExecOrDie(namespace)
  666. }
  667. // RunKubectlInput is a convenience wrapper over kubectlBuilder that takes input to stdin
  668. func RunKubectlInput(namespace string, data string, args ...string) (string, error) {
  669. return NewKubectlCommand(namespace, args...).WithStdinData(data).Exec()
  670. }
  671. // RunKubemciWithKubeconfig is a convenience wrapper over RunKubemciCmd
  672. func RunKubemciWithKubeconfig(args ...string) (string, error) {
  673. if TestContext.KubeConfig != "" {
  674. args = append(args, "--"+clientcmd.RecommendedConfigPathFlag+"="+TestContext.KubeConfig)
  675. }
  676. return RunKubemciCmd(args...)
  677. }
  678. // RunKubemciCmd is a convenience wrapper over kubectlBuilder to run kubemci.
  679. // It assumes that kubemci exists in PATH.
  680. func RunKubemciCmd(args ...string) (string, error) {
  681. // kubemci is assumed to be in PATH.
  682. kubemci := "kubemci"
  683. b := new(KubectlBuilder)
  684. args = append(args, "--gcp-project="+TestContext.CloudConfig.ProjectID)
  685. b.cmd = exec.Command(kubemci, args...)
  686. return b.Exec()
  687. }
  688. // StartCmdAndStreamOutput returns stdout and stderr after starting the given cmd.
  689. func StartCmdAndStreamOutput(cmd *exec.Cmd) (stdout, stderr io.ReadCloser, err error) {
  690. stdout, err = cmd.StdoutPipe()
  691. if err != nil {
  692. return
  693. }
  694. stderr, err = cmd.StderrPipe()
  695. if err != nil {
  696. return
  697. }
  698. Logf("Asynchronously running '%s %s'", cmd.Path, strings.Join(cmd.Args, " "))
  699. err = cmd.Start()
  700. return
  701. }
  702. // TryKill is rough equivalent of ctrl+c for cleaning up processes. Intended to be run in defer.
  703. func TryKill(cmd *exec.Cmd) {
  704. if err := cmd.Process.Kill(); err != nil {
  705. Logf("ERROR failed to kill command %v! The process may leak", cmd)
  706. }
  707. }
  708. // testContainerOutputMatcher runs the given pod in the given namespace and waits
  709. // for all of the containers in the podSpec to move into the 'Success' status, and tests
  710. // the specified container log against the given expected output using the given matcher.
  711. func (f *Framework) testContainerOutputMatcher(scenarioName string,
  712. pod *v1.Pod,
  713. containerIndex int,
  714. expectedOutput []string,
  715. matcher func(string, ...interface{}) gomegatypes.GomegaMatcher) {
  716. ginkgo.By(fmt.Sprintf("Creating a pod to test %v", scenarioName))
  717. if containerIndex < 0 || containerIndex >= len(pod.Spec.Containers) {
  718. Failf("Invalid container index: %d", containerIndex)
  719. }
  720. ExpectNoError(f.MatchContainerOutput(pod, pod.Spec.Containers[containerIndex].Name, expectedOutput, matcher))
  721. }
  722. // MatchContainerOutput creates a pod and waits for all it's containers to exit with success.
  723. // It then tests that the matcher with each expectedOutput matches the output of the specified container.
  724. func (f *Framework) MatchContainerOutput(
  725. pod *v1.Pod,
  726. containerName string,
  727. expectedOutput []string,
  728. matcher func(string, ...interface{}) gomegatypes.GomegaMatcher) error {
  729. ns := pod.ObjectMeta.Namespace
  730. if ns == "" {
  731. ns = f.Namespace.Name
  732. }
  733. podClient := f.PodClientNS(ns)
  734. createdPod := podClient.Create(pod)
  735. defer func() {
  736. ginkgo.By("delete the pod")
  737. podClient.DeleteSync(createdPod.Name, &metav1.DeleteOptions{}, DefaultPodDeletionTimeout)
  738. }()
  739. // Wait for client pod to complete.
  740. podErr := e2epod.WaitForPodSuccessInNamespace(f.ClientSet, createdPod.Name, ns)
  741. // Grab its logs. Get host first.
  742. podStatus, err := podClient.Get(context.TODO(), createdPod.Name, metav1.GetOptions{})
  743. if err != nil {
  744. return fmt.Errorf("failed to get pod status: %v", err)
  745. }
  746. if podErr != nil {
  747. // Pod failed. Dump all logs from all containers to see what's wrong
  748. _ = podutil.VisitContainers(&podStatus.Spec, func(c *v1.Container) bool {
  749. logs, err := e2epod.GetPodLogs(f.ClientSet, ns, podStatus.Name, c.Name)
  750. if err != nil {
  751. Logf("Failed to get logs from node %q pod %q container %q: %v",
  752. podStatus.Spec.NodeName, podStatus.Name, c.Name, err)
  753. } else {
  754. Logf("Output of node %q pod %q container %q: %s", podStatus.Spec.NodeName, podStatus.Name, c.Name, logs)
  755. }
  756. return true
  757. })
  758. return fmt.Errorf("expected pod %q success: %v", createdPod.Name, podErr)
  759. }
  760. Logf("Trying to get logs from node %s pod %s container %s: %v",
  761. podStatus.Spec.NodeName, podStatus.Name, containerName, err)
  762. // Sometimes the actual containers take a second to get started, try to get logs for 60s
  763. logs, err := e2epod.GetPodLogs(f.ClientSet, ns, podStatus.Name, containerName)
  764. if err != nil {
  765. Logf("Failed to get logs from node %q pod %q container %q. %v",
  766. podStatus.Spec.NodeName, podStatus.Name, containerName, err)
  767. return fmt.Errorf("failed to get logs from %s for %s: %v", podStatus.Name, containerName, err)
  768. }
  769. for _, expected := range expectedOutput {
  770. m := matcher(expected)
  771. matches, err := m.Match(logs)
  772. if err != nil {
  773. return fmt.Errorf("expected %q in container output: %v", expected, err)
  774. } else if !matches {
  775. return fmt.Errorf("expected %q in container output: %s", expected, m.FailureMessage(logs))
  776. }
  777. }
  778. return nil
  779. }
  780. // EventsLister is a func that lists events.
  781. type EventsLister func(opts metav1.ListOptions, ns string) (*v1.EventList, error)
  782. // dumpEventsInNamespace dumps events in the given namespace.
  783. func dumpEventsInNamespace(eventsLister EventsLister, namespace string) {
  784. ginkgo.By(fmt.Sprintf("Collecting events from namespace %q.", namespace))
  785. events, err := eventsLister(metav1.ListOptions{}, namespace)
  786. ExpectNoError(err, "failed to list events in namespace %q", namespace)
  787. ginkgo.By(fmt.Sprintf("Found %d events.", len(events.Items)))
  788. // Sort events by their first timestamp
  789. sortedEvents := events.Items
  790. if len(sortedEvents) > 1 {
  791. sort.Sort(byFirstTimestamp(sortedEvents))
  792. }
  793. for _, e := range sortedEvents {
  794. Logf("At %v - event for %v: %v %v: %v", e.FirstTimestamp, e.InvolvedObject.Name, e.Source, e.Reason, e.Message)
  795. }
  796. // Note that we don't wait for any Cleanup to propagate, which means
  797. // that if you delete a bunch of pods right before ending your test,
  798. // you may or may not see the killing/deletion/Cleanup events.
  799. }
  800. // DumpAllNamespaceInfo dumps events, pods and nodes information in the given namespace.
  801. func DumpAllNamespaceInfo(c clientset.Interface, namespace string) {
  802. dumpEventsInNamespace(func(opts metav1.ListOptions, ns string) (*v1.EventList, error) {
  803. return c.CoreV1().Events(ns).List(context.TODO(), opts)
  804. }, namespace)
  805. e2epod.DumpAllPodInfoForNamespace(c, namespace)
  806. // If cluster is large, then the following logs are basically useless, because:
  807. // 1. it takes tens of minutes or hours to grab all of them
  808. // 2. there are so many of them that working with them are mostly impossible
  809. // So we dump them only if the cluster is relatively small.
  810. maxNodesForDump := TestContext.MaxNodesToGather
  811. nodes, err := c.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
  812. if err != nil {
  813. Logf("unable to fetch node list: %v", err)
  814. return
  815. }
  816. if len(nodes.Items) <= maxNodesForDump {
  817. dumpAllNodeInfo(c, nodes)
  818. } else {
  819. Logf("skipping dumping cluster info - cluster too large")
  820. }
  821. }
  822. // byFirstTimestamp sorts a slice of events by first timestamp, using their involvedObject's name as a tie breaker.
  823. type byFirstTimestamp []v1.Event
  824. func (o byFirstTimestamp) Len() int { return len(o) }
  825. func (o byFirstTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
  826. func (o byFirstTimestamp) Less(i, j int) bool {
  827. if o[i].FirstTimestamp.Equal(&o[j].FirstTimestamp) {
  828. return o[i].InvolvedObject.Name < o[j].InvolvedObject.Name
  829. }
  830. return o[i].FirstTimestamp.Before(&o[j].FirstTimestamp)
  831. }
  832. func dumpAllNodeInfo(c clientset.Interface, nodes *v1.NodeList) {
  833. names := make([]string, len(nodes.Items))
  834. for ix := range nodes.Items {
  835. names[ix] = nodes.Items[ix].Name
  836. }
  837. DumpNodeDebugInfo(c, names, Logf)
  838. }
  839. // DumpNodeDebugInfo dumps debug information of the given nodes.
  840. func DumpNodeDebugInfo(c clientset.Interface, nodeNames []string, logFunc func(fmt string, args ...interface{})) {
  841. for _, n := range nodeNames {
  842. logFunc("\nLogging node info for node %v", n)
  843. node, err := c.CoreV1().Nodes().Get(context.TODO(), n, metav1.GetOptions{})
  844. if err != nil {
  845. logFunc("Error getting node info %v", err)
  846. }
  847. logFunc("Node Info: %v", node)
  848. logFunc("\nLogging kubelet events for node %v", n)
  849. for _, e := range getNodeEvents(c, n) {
  850. logFunc("source %v type %v message %v reason %v first ts %v last ts %v, involved obj %+v",
  851. e.Source, e.Type, e.Message, e.Reason, e.FirstTimestamp, e.LastTimestamp, e.InvolvedObject)
  852. }
  853. logFunc("\nLogging pods the kubelet thinks is on node %v", n)
  854. podList, err := getKubeletPods(c, n)
  855. if err != nil {
  856. logFunc("Unable to retrieve kubelet pods for node %v: %v", n, err)
  857. continue
  858. }
  859. for _, p := range podList.Items {
  860. logFunc("%v started at %v (%d+%d container statuses recorded)", p.Name, p.Status.StartTime, len(p.Status.InitContainerStatuses), len(p.Status.ContainerStatuses))
  861. for _, c := range p.Status.InitContainerStatuses {
  862. logFunc("\tInit container %v ready: %v, restart count %v",
  863. c.Name, c.Ready, c.RestartCount)
  864. }
  865. for _, c := range p.Status.ContainerStatuses {
  866. logFunc("\tContainer %v ready: %v, restart count %v",
  867. c.Name, c.Ready, c.RestartCount)
  868. }
  869. }
  870. e2emetrics.HighLatencyKubeletOperations(c, 10*time.Second, n, logFunc)
  871. // TODO: Log node resource info
  872. }
  873. }
  874. // getKubeletPods retrieves the list of pods on the kubelet.
  875. func getKubeletPods(c clientset.Interface, node string) (*v1.PodList, error) {
  876. var client restclient.Result
  877. finished := make(chan struct{}, 1)
  878. go func() {
  879. // call chain tends to hang in some cases when Node is not ready. Add an artificial timeout for this call. #22165
  880. client = c.CoreV1().RESTClient().Get().
  881. Resource("nodes").
  882. SubResource("proxy").
  883. Name(fmt.Sprintf("%v:%v", node, ports.KubeletPort)).
  884. Suffix("pods").
  885. Do(context.TODO())
  886. finished <- struct{}{}
  887. }()
  888. select {
  889. case <-finished:
  890. result := &v1.PodList{}
  891. if err := client.Into(result); err != nil {
  892. return &v1.PodList{}, err
  893. }
  894. return result, nil
  895. case <-time.After(PodGetTimeout):
  896. return &v1.PodList{}, fmt.Errorf("Waiting up to %v for getting the list of pods", PodGetTimeout)
  897. }
  898. }
  899. // logNodeEvents logs kubelet events from the given node. This includes kubelet
  900. // restart and node unhealthy events. Note that listing events like this will mess
  901. // with latency metrics, beware of calling it during a test.
  902. func getNodeEvents(c clientset.Interface, nodeName string) []v1.Event {
  903. selector := fields.Set{
  904. "involvedObject.kind": "Node",
  905. "involvedObject.name": nodeName,
  906. "involvedObject.namespace": metav1.NamespaceAll,
  907. "source": "kubelet",
  908. }.AsSelector().String()
  909. options := metav1.ListOptions{FieldSelector: selector}
  910. events, err := c.CoreV1().Events(metav1.NamespaceSystem).List(context.TODO(), options)
  911. if err != nil {
  912. Logf("Unexpected error retrieving node events %v", err)
  913. return []v1.Event{}
  914. }
  915. return events.Items
  916. }
  917. // WaitForAllNodesSchedulable waits up to timeout for all
  918. // (but TestContext.AllowedNotReadyNodes) to become scheduable.
  919. func WaitForAllNodesSchedulable(c clientset.Interface, timeout time.Duration) error {
  920. Logf("Waiting up to %v for all (but %d) nodes to be schedulable", timeout, TestContext.AllowedNotReadyNodes)
  921. return wait.PollImmediate(
  922. 30*time.Second,
  923. timeout,
  924. e2enode.CheckReadyForTests(c, TestContext.NonblockingTaints, TestContext.AllowedNotReadyNodes, largeClusterThreshold),
  925. )
  926. }
  927. // GetPodSecretUpdateTimeout reuturns the timeout duration for updating pod secret.
  928. func GetPodSecretUpdateTimeout(c clientset.Interface) time.Duration {
  929. // With SecretManager(ConfigMapManager), we may have to wait up to full sync period +
  930. // TTL of secret(configmap) to elapse before the Kubelet projects the update into the
  931. // volume and the container picks it up.
  932. // So this timeout is based on default Kubelet sync period (1 minute) + maximum TTL for
  933. // secret(configmap) that's based on cluster size + additional time as a fudge factor.
  934. secretTTL, err := getNodeTTLAnnotationValue(c)
  935. if err != nil {
  936. Logf("Couldn't get node TTL annotation (using default value of 0): %v", err)
  937. }
  938. podLogTimeout := 240*time.Second + secretTTL
  939. return podLogTimeout
  940. }
  941. func getNodeTTLAnnotationValue(c clientset.Interface) (time.Duration, error) {
  942. nodes, err := c.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
  943. if err != nil || len(nodes.Items) == 0 {
  944. return time.Duration(0), fmt.Errorf("Couldn't list any nodes to get TTL annotation: %v", err)
  945. }
  946. // Since TTL the kubelet is using is stored in node object, for the timeout
  947. // purpose we take it from the first node (all of them should be the same).
  948. node := &nodes.Items[0]
  949. if node.Annotations == nil {
  950. return time.Duration(0), fmt.Errorf("No annotations found on the node")
  951. }
  952. value, ok := node.Annotations[v1.ObjectTTLAnnotationKey]
  953. if !ok {
  954. return time.Duration(0), fmt.Errorf("No TTL annotation found on the node")
  955. }
  956. intValue, err := strconv.Atoi(value)
  957. if err != nil {
  958. return time.Duration(0), fmt.Errorf("Cannot convert TTL annotation from %#v to int", *node)
  959. }
  960. return time.Duration(intValue) * time.Second, nil
  961. }
  962. // AddOrUpdateLabelOnNode adds the given label key and value to the given node or updates value.
  963. func AddOrUpdateLabelOnNode(c clientset.Interface, nodeName string, labelKey, labelValue string) {
  964. ExpectNoError(testutils.AddLabelsToNode(c, nodeName, map[string]string{labelKey: labelValue}))
  965. }
  966. // ExpectNodeHasLabel expects that the given node has the given label pair.
  967. func ExpectNodeHasLabel(c clientset.Interface, nodeName string, labelKey string, labelValue string) {
  968. ginkgo.By("verifying the node has the label " + labelKey + " " + labelValue)
  969. node, err := c.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
  970. ExpectNoError(err)
  971. ExpectEqual(node.Labels[labelKey], labelValue)
  972. }
  973. // RemoveTaintOffNode removes the given taint from the given node.
  974. func RemoveTaintOffNode(c clientset.Interface, nodeName string, taint v1.Taint) {
  975. ExpectNoError(controller.RemoveTaintOffNode(c, nodeName, nil, &taint))
  976. verifyThatTaintIsGone(c, nodeName, &taint)
  977. }
  978. // AddOrUpdateTaintOnNode adds the given taint to the given node or updates taint.
  979. func AddOrUpdateTaintOnNode(c clientset.Interface, nodeName string, taint v1.Taint) {
  980. ExpectNoError(controller.AddOrUpdateTaintOnNode(c, nodeName, &taint))
  981. }
  982. // RemoveLabelOffNode is for cleaning up labels temporarily added to node,
  983. // won't fail if target label doesn't exist or has been removed.
  984. func RemoveLabelOffNode(c clientset.Interface, nodeName string, labelKey string) {
  985. ginkgo.By("removing the label " + labelKey + " off the node " + nodeName)
  986. ExpectNoError(testutils.RemoveLabelOffNode(c, nodeName, []string{labelKey}))
  987. ginkgo.By("verifying the node doesn't have the label " + labelKey)
  988. ExpectNoError(testutils.VerifyLabelsRemoved(c, nodeName, []string{labelKey}))
  989. }
  990. func verifyThatTaintIsGone(c clientset.Interface, nodeName string, taint *v1.Taint) {
  991. ginkgo.By("verifying the node doesn't have the taint " + taint.ToString())
  992. nodeUpdated, err := c.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
  993. ExpectNoError(err)
  994. if taintutils.TaintExists(nodeUpdated.Spec.Taints, taint) {
  995. Failf("Failed removing taint " + taint.ToString() + " of the node " + nodeName)
  996. }
  997. }
  998. // ExpectNodeHasTaint expects that the node has the given taint.
  999. func ExpectNodeHasTaint(c clientset.Interface, nodeName string, taint *v1.Taint) {
  1000. ginkgo.By("verifying the node has the taint " + taint.ToString())
  1001. if has, err := NodeHasTaint(c, nodeName, taint); !has {
  1002. ExpectNoError(err)
  1003. Failf("Failed to find taint %s on node %s", taint.ToString(), nodeName)
  1004. }
  1005. }
  1006. // NodeHasTaint returns true if the node has the given taint, else returns false.
  1007. func NodeHasTaint(c clientset.Interface, nodeName string, taint *v1.Taint) (bool, error) {
  1008. node, err := c.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
  1009. if err != nil {
  1010. return false, err
  1011. }
  1012. nodeTaints := node.Spec.Taints
  1013. if len(nodeTaints) == 0 || !taintutils.TaintExists(nodeTaints, taint) {
  1014. return false, nil
  1015. }
  1016. return true, nil
  1017. }
  1018. // ScaleResource scales resource to the given size.
  1019. func ScaleResource(
  1020. clientset clientset.Interface,
  1021. scalesGetter scaleclient.ScalesGetter,
  1022. ns, name string,
  1023. size uint,
  1024. wait bool,
  1025. kind schema.GroupKind,
  1026. gvr schema.GroupVersionResource,
  1027. ) error {
  1028. ginkgo.By(fmt.Sprintf("Scaling %v %s in namespace %s to %d", kind, name, ns, size))
  1029. if err := testutils.ScaleResourceWithRetries(scalesGetter, ns, name, size, gvr); err != nil {
  1030. return fmt.Errorf("error while scaling RC %s to %d replicas: %v", name, size, err)
  1031. }
  1032. if !wait {
  1033. return nil
  1034. }
  1035. return e2epod.WaitForControlledPodsRunning(clientset, ns, name, kind)
  1036. }
  1037. // DeleteResourceAndWaitForGC deletes only given resource and waits for GC to delete the pods.
  1038. func DeleteResourceAndWaitForGC(c clientset.Interface, kind schema.GroupKind, ns, name string) error {
  1039. ginkgo.By(fmt.Sprintf("deleting %v %s in namespace %s, will wait for the garbage collector to delete the pods", kind, name, ns))
  1040. rtObject, err := e2eresource.GetRuntimeObjectForKind(c, kind, ns, name)
  1041. if err != nil {
  1042. if apierrors.IsNotFound(err) {
  1043. Logf("%v %s not found: %v", kind, name, err)
  1044. return nil
  1045. }
  1046. return err
  1047. }
  1048. selector, err := e2eresource.GetSelectorFromRuntimeObject(rtObject)
  1049. if err != nil {
  1050. return err
  1051. }
  1052. replicas, err := e2eresource.GetReplicasFromRuntimeObject(rtObject)
  1053. if err != nil {
  1054. return err
  1055. }
  1056. ps, err := testutils.NewPodStore(c, ns, selector, fields.Everything())
  1057. if err != nil {
  1058. return err
  1059. }
  1060. defer ps.Stop()
  1061. falseVar := false
  1062. deleteOption := &metav1.DeleteOptions{OrphanDependents: &falseVar}
  1063. startTime := time.Now()
  1064. if err := testutils.DeleteResourceWithRetries(c, kind, ns, name, deleteOption); err != nil {
  1065. return err
  1066. }
  1067. deleteTime := time.Since(startTime)
  1068. Logf("Deleting %v %s took: %v", kind, name, deleteTime)
  1069. var interval, timeout time.Duration
  1070. switch {
  1071. case replicas < 100:
  1072. interval = 100 * time.Millisecond
  1073. case replicas < 1000:
  1074. interval = 1 * time.Second
  1075. default:
  1076. interval = 10 * time.Second
  1077. }
  1078. if replicas < 5000 {
  1079. timeout = 10 * time.Minute
  1080. } else {
  1081. timeout = time.Duration(replicas/gcThroughput) * time.Second
  1082. // gcThroughput is pretty strict now, add a bit more to it
  1083. timeout = timeout + 3*time.Minute
  1084. }
  1085. err = waitForPodsInactive(ps, interval, timeout)
  1086. if err != nil {
  1087. return fmt.Errorf("error while waiting for pods to become inactive %s: %v", name, err)
  1088. }
  1089. terminatePodTime := time.Since(startTime) - deleteTime
  1090. Logf("Terminating %v %s pods took: %v", kind, name, terminatePodTime)
  1091. // In gce, at any point, small percentage of nodes can disappear for
  1092. // ~10 minutes due to hostError. 20 minutes should be long enough to
  1093. // restart VM in that case and delete the pod.
  1094. err = waitForPodsGone(ps, interval, 20*time.Minute)
  1095. if err != nil {
  1096. return fmt.Errorf("error while waiting for pods gone %s: %v", name, err)
  1097. }
  1098. return nil
  1099. }
  1100. // waitForPodsGone waits until there are no pods left in the PodStore.
  1101. func waitForPodsGone(ps *testutils.PodStore, interval, timeout time.Duration) error {
  1102. var pods []*v1.Pod
  1103. err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  1104. if pods = ps.List(); len(pods) == 0 {
  1105. return true, nil
  1106. }
  1107. return false, nil
  1108. })
  1109. if err == wait.ErrWaitTimeout {
  1110. for _, pod := range pods {
  1111. Logf("ERROR: Pod %q still exists. Node: %q", pod.Name, pod.Spec.NodeName)
  1112. }
  1113. return fmt.Errorf("there are %d pods left. E.g. %q on node %q", len(pods), pods[0].Name, pods[0].Spec.NodeName)
  1114. }
  1115. return err
  1116. }
  1117. // waitForPodsInactive waits until there are no active pods left in the PodStore.
  1118. // This is to make a fair comparison of deletion time between DeleteRCAndPods
  1119. // and DeleteRCAndWaitForGC, because the RC controller decreases status.replicas
  1120. // when the pod is inactvie.
  1121. func waitForPodsInactive(ps *testutils.PodStore, interval, timeout time.Duration) error {
  1122. var activePods []*v1.Pod
  1123. err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  1124. pods := ps.List()
  1125. activePods = controller.FilterActivePods(pods)
  1126. if len(activePods) != 0 {
  1127. return false, nil
  1128. }
  1129. return true, nil
  1130. })
  1131. if err == wait.ErrWaitTimeout {
  1132. for _, pod := range activePods {
  1133. Logf("ERROR: Pod %q running on %q is still active", pod.Name, pod.Spec.NodeName)
  1134. }
  1135. return fmt.Errorf("there are %d active pods. E.g. %q on node %q", len(activePods), activePods[0].Name, activePods[0].Spec.NodeName)
  1136. }
  1137. return err
  1138. }
  1139. // RunHostCmd runs the given cmd in the context of the given pod using `kubectl exec`
  1140. // inside of a shell.
  1141. func RunHostCmd(ns, name, cmd string) (string, error) {
  1142. return RunKubectl(ns, "exec", fmt.Sprintf("--namespace=%v", ns), name, "--", "/bin/sh", "-x", "-c", cmd)
  1143. }
  1144. // RunHostCmdOrDie calls RunHostCmd and dies on error.
  1145. func RunHostCmdOrDie(ns, name, cmd string) string {
  1146. stdout, err := RunHostCmd(ns, name, cmd)
  1147. Logf("stdout: %v", stdout)
  1148. ExpectNoError(err)
  1149. return stdout
  1150. }
  1151. // RunHostCmdWithRetries calls RunHostCmd and retries all errors
  1152. // until it succeeds or the specified timeout expires.
  1153. // This can be used with idempotent commands to deflake transient Node issues.
  1154. func RunHostCmdWithRetries(ns, name, cmd string, interval, timeout time.Duration) (string, error) {
  1155. start := time.Now()
  1156. for {
  1157. out, err := RunHostCmd(ns, name, cmd)
  1158. if err == nil {
  1159. return out, nil
  1160. }
  1161. if elapsed := time.Since(start); elapsed > timeout {
  1162. return out, fmt.Errorf("RunHostCmd still failed after %v: %v", elapsed, err)
  1163. }
  1164. Logf("Waiting %v to retry failed RunHostCmd: %v", interval, err)
  1165. time.Sleep(interval)
  1166. }
  1167. }
  1168. // AllNodesReady checks whether all registered nodes are ready.
  1169. // TODO: we should change the AllNodesReady call in AfterEach to WaitForAllNodesHealthy,
  1170. // and figure out how to do it in a configurable way, as we can't expect all setups to run
  1171. // default test add-ons.
  1172. func AllNodesReady(c clientset.Interface, timeout time.Duration) error {
  1173. Logf("Waiting up to %v for all (but %d) nodes to be ready", timeout, TestContext.AllowedNotReadyNodes)
  1174. var notReady []*v1.Node
  1175. err := wait.PollImmediate(Poll, timeout, func() (bool, error) {
  1176. notReady = nil
  1177. // It should be OK to list unschedulable Nodes here.
  1178. nodes, err := c.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
  1179. if err != nil {
  1180. if testutils.IsRetryableAPIError(err) {
  1181. return false, nil
  1182. }
  1183. return false, err
  1184. }
  1185. for i := range nodes.Items {
  1186. node := &nodes.Items[i]
  1187. if !e2enode.IsConditionSetAsExpected(node, v1.NodeReady, true) {
  1188. notReady = append(notReady, node)
  1189. }
  1190. }
  1191. // Framework allows for <TestContext.AllowedNotReadyNodes> nodes to be non-ready,
  1192. // to make it possible e.g. for incorrect deployment of some small percentage
  1193. // of nodes (which we allow in cluster validation). Some nodes that are not
  1194. // provisioned correctly at startup will never become ready (e.g. when something
  1195. // won't install correctly), so we can't expect them to be ready at any point.
  1196. return len(notReady) <= TestContext.AllowedNotReadyNodes, nil
  1197. })
  1198. if err != nil && err != wait.ErrWaitTimeout {
  1199. return err
  1200. }
  1201. if len(notReady) > TestContext.AllowedNotReadyNodes {
  1202. msg := ""
  1203. for _, node := range notReady {
  1204. msg = fmt.Sprintf("%s, %s", msg, node.Name)
  1205. }
  1206. return fmt.Errorf("Not ready nodes: %#v", msg)
  1207. }
  1208. return nil
  1209. }
  1210. // RestartKubelet restarts kubelet on the given host.
  1211. func RestartKubelet(host string) error {
  1212. // TODO: Make it work for all providers and distros.
  1213. supportedProviders := []string{"gce", "aws", "vsphere"}
  1214. if !ProviderIs(supportedProviders...) {
  1215. return fmt.Errorf("unsupported provider for RestartKubelet: %s, supported providers are: %v", TestContext.Provider, supportedProviders)
  1216. }
  1217. if ProviderIs("gce") && !NodeOSDistroIs("debian", "gci") {
  1218. return fmt.Errorf("unsupported node OS distro: %s", TestContext.NodeOSDistro)
  1219. }
  1220. var cmd string
  1221. if ProviderIs("gce") && NodeOSDistroIs("debian") {
  1222. cmd = "sudo /etc/init.d/kubelet restart"
  1223. } else if ProviderIs("vsphere") {
  1224. var sudoPresent bool
  1225. sshResult, err := e2essh.SSH("sudo --version", host, TestContext.Provider)
  1226. if err != nil {
  1227. return fmt.Errorf("Unable to ssh to host %s with error %v", host, err)
  1228. }
  1229. if !strings.Contains(sshResult.Stderr, "command not found") {
  1230. sudoPresent = true
  1231. }
  1232. sshResult, err = e2essh.SSH("systemctl --version", host, TestContext.Provider)
  1233. if err != nil {
  1234. return fmt.Errorf("Failed to execute command 'systemctl' on host %s with error %v", host, err)
  1235. }
  1236. if !strings.Contains(sshResult.Stderr, "command not found") {
  1237. cmd = "systemctl restart kubelet"
  1238. } else {
  1239. cmd = "service kubelet restart"
  1240. }
  1241. if sudoPresent {
  1242. cmd = fmt.Sprintf("sudo %s", cmd)
  1243. }
  1244. } else {
  1245. cmd = "sudo systemctl restart kubelet"
  1246. }
  1247. Logf("Restarting kubelet via ssh on host %s with command %s", host, cmd)
  1248. result, err := e2essh.SSH(cmd, host, TestContext.Provider)
  1249. if err != nil || result.Code != 0 {
  1250. e2essh.LogResult(result)
  1251. return fmt.Errorf("couldn't restart kubelet: %v", err)
  1252. }
  1253. return nil
  1254. }
  1255. // RestartApiserver restarts the kube-apiserver.
  1256. func RestartApiserver(namespace string, cs clientset.Interface) error {
  1257. // TODO: Make it work for all providers.
  1258. if !ProviderIs("gce", "gke", "aws") {
  1259. return fmt.Errorf("unsupported provider for RestartApiserver: %s", TestContext.Provider)
  1260. }
  1261. if ProviderIs("gce", "aws") {
  1262. initialRestartCount, err := getApiserverRestartCount(cs)
  1263. if err != nil {
  1264. return fmt.Errorf("failed to get apiserver's restart count: %v", err)
  1265. }
  1266. if err := sshRestartMaster(); err != nil {
  1267. return fmt.Errorf("failed to restart apiserver: %v", err)
  1268. }
  1269. return waitForApiserverRestarted(cs, initialRestartCount)
  1270. }
  1271. // GKE doesn't allow ssh access, so use a same-version master
  1272. // upgrade to teardown/recreate master.
  1273. v, err := cs.Discovery().ServerVersion()
  1274. if err != nil {
  1275. return err
  1276. }
  1277. return masterUpgradeGKE(namespace, v.GitVersion[1:]) // strip leading 'v'
  1278. }
  1279. func sshRestartMaster() error {
  1280. if !ProviderIs("gce", "aws") {
  1281. return fmt.Errorf("unsupported provider for sshRestartMaster: %s", TestContext.Provider)
  1282. }
  1283. var command string
  1284. if ProviderIs("gce") {
  1285. command = "pidof kube-apiserver | xargs sudo kill"
  1286. } else {
  1287. command = "sudo /etc/init.d/kube-apiserver restart"
  1288. }
  1289. Logf("Restarting master via ssh, running: %v", command)
  1290. result, err := e2essh.SSH(command, net.JoinHostPort(GetMasterHost(), sshPort), TestContext.Provider)
  1291. if err != nil || result.Code != 0 {
  1292. e2essh.LogResult(result)
  1293. return fmt.Errorf("couldn't restart apiserver: %v", err)
  1294. }
  1295. return nil
  1296. }
  1297. // waitForApiserverRestarted waits until apiserver's restart count increased.
  1298. func waitForApiserverRestarted(c clientset.Interface, initialRestartCount int32) error {
  1299. for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
  1300. restartCount, err := getApiserverRestartCount(c)
  1301. if err != nil {
  1302. Logf("Failed to get apiserver's restart count: %v", err)
  1303. continue
  1304. }
  1305. if restartCount > initialRestartCount {
  1306. Logf("Apiserver has restarted.")
  1307. return nil
  1308. }
  1309. Logf("Waiting for apiserver restart count to increase")
  1310. }
  1311. return fmt.Errorf("timed out waiting for apiserver to be restarted")
  1312. }
  1313. func getApiserverRestartCount(c clientset.Interface) (int32, error) {
  1314. label := labels.SelectorFromSet(labels.Set(map[string]string{"component": "kube-apiserver"}))
  1315. listOpts := metav1.ListOptions{LabelSelector: label.String()}
  1316. pods, err := c.CoreV1().Pods(metav1.NamespaceSystem).List(context.TODO(), listOpts)
  1317. if err != nil {
  1318. return -1, err
  1319. }
  1320. if len(pods.Items) != 1 {
  1321. return -1, fmt.Errorf("unexpected number of apiserver pod: %d", len(pods.Items))
  1322. }
  1323. for _, s := range pods.Items[0].Status.ContainerStatuses {
  1324. if s.Name != "kube-apiserver" {
  1325. continue
  1326. }
  1327. return s.RestartCount, nil
  1328. }
  1329. return -1, fmt.Errorf("Failed to find kube-apiserver container in pod")
  1330. }
  1331. // RestartControllerManager restarts the kube-controller-manager.
  1332. func RestartControllerManager() error {
  1333. // TODO: Make it work for all providers and distros.
  1334. if !ProviderIs("gce", "aws") {
  1335. return fmt.Errorf("unsupported provider for RestartControllerManager: %s", TestContext.Provider)
  1336. }
  1337. if ProviderIs("gce") && !MasterOSDistroIs("gci") {
  1338. return fmt.Errorf("unsupported master OS distro: %s", TestContext.MasterOSDistro)
  1339. }
  1340. cmd := "pidof kube-controller-manager | xargs sudo kill"
  1341. Logf("Restarting controller-manager via ssh, running: %v", cmd)
  1342. result, err := e2essh.SSH(cmd, net.JoinHostPort(GetMasterHost(), sshPort), TestContext.Provider)
  1343. if err != nil || result.Code != 0 {
  1344. e2essh.LogResult(result)
  1345. return fmt.Errorf("couldn't restart controller-manager: %v", err)
  1346. }
  1347. return nil
  1348. }
  1349. // WaitForControllerManagerUp waits for the kube-controller-manager to be up.
  1350. func WaitForControllerManagerUp() error {
  1351. cmd := "curl http://localhost:" + strconv.Itoa(ports.InsecureKubeControllerManagerPort) + "/healthz"
  1352. for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
  1353. result, err := e2essh.SSH(cmd, net.JoinHostPort(GetMasterHost(), sshPort), TestContext.Provider)
  1354. if err != nil || result.Code != 0 {
  1355. e2essh.LogResult(result)
  1356. }
  1357. if result.Stdout == "ok" {
  1358. return nil
  1359. }
  1360. }
  1361. return fmt.Errorf("waiting for controller-manager timed out")
  1362. }
  1363. type extractRT struct {
  1364. http.Header
  1365. }
  1366. func (rt *extractRT) RoundTrip(req *http.Request) (*http.Response, error) {
  1367. rt.Header = req.Header
  1368. return &http.Response{}, nil
  1369. }
  1370. // headersForConfig extracts any http client logic necessary for the provided
  1371. // config.
  1372. func headersForConfig(c *restclient.Config, url *url.URL) (http.Header, error) {
  1373. extract := &extractRT{}
  1374. rt, err := restclient.HTTPWrappersForConfig(c, extract)
  1375. if err != nil {
  1376. return nil, err
  1377. }
  1378. if _, err := rt.RoundTrip(&http.Request{URL: url}); err != nil {
  1379. return nil, err
  1380. }
  1381. return extract.Header, nil
  1382. }
  1383. // OpenWebSocketForURL constructs a websocket connection to the provided URL, using the client
  1384. // config, with the specified protocols.
  1385. func OpenWebSocketForURL(url *url.URL, config *restclient.Config, protocols []string) (*websocket.Conn, error) {
  1386. tlsConfig, err := restclient.TLSConfigFor(config)
  1387. if err != nil {
  1388. return nil, fmt.Errorf("Failed to create tls config: %v", err)
  1389. }
  1390. if url.Scheme == "https" {
  1391. url.Scheme = "wss"
  1392. } else {
  1393. url.Scheme = "ws"
  1394. }
  1395. headers, err := headersForConfig(config, url)
  1396. if err != nil {
  1397. return nil, fmt.Errorf("Failed to load http headers: %v", err)
  1398. }
  1399. cfg, err := websocket.NewConfig(url.String(), "http://localhost")
  1400. if err != nil {
  1401. return nil, fmt.Errorf("Failed to create websocket config: %v", err)
  1402. }
  1403. cfg.Header = headers
  1404. cfg.TlsConfig = tlsConfig
  1405. cfg.Protocol = protocols
  1406. return websocket.DialConfig(cfg)
  1407. }
  1408. // LookForStringInLog looks for the given string in the log of a specific pod container
  1409. func LookForStringInLog(ns, podName, container, expectedString string, timeout time.Duration) (result string, err error) {
  1410. return LookForString(expectedString, timeout, func() string {
  1411. return RunKubectlOrDie(ns, "logs", podName, container, fmt.Sprintf("--namespace=%v", ns))
  1412. })
  1413. }
  1414. // EnsureLoadBalancerResourcesDeleted ensures that cloud load balancer resources that were created
  1415. // are actually cleaned up. Currently only implemented for GCE/GKE.
  1416. func EnsureLoadBalancerResourcesDeleted(ip, portRange string) error {
  1417. return TestContext.CloudConfig.Provider.EnsureLoadBalancerResourcesDeleted(ip, portRange)
  1418. }
  1419. // BlockNetwork blocks network between the given from value and the given to value.
  1420. // The following helper functions can block/unblock network from source
  1421. // host to destination host by manipulating iptable rules.
  1422. // This function assumes it can ssh to the source host.
  1423. //
  1424. // Caution:
  1425. // Recommend to input IP instead of hostnames. Using hostnames will cause iptables to
  1426. // do a DNS lookup to resolve the name to an IP address, which will
  1427. // slow down the test and cause it to fail if DNS is absent or broken.
  1428. //
  1429. // Suggested usage pattern:
  1430. // func foo() {
  1431. // ...
  1432. // defer UnblockNetwork(from, to)
  1433. // BlockNetwork(from, to)
  1434. // ...
  1435. // }
  1436. //
  1437. func BlockNetwork(from string, to string) {
  1438. Logf("block network traffic from %s to %s", from, to)
  1439. iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to)
  1440. dropCmd := fmt.Sprintf("sudo iptables --insert %s", iptablesRule)
  1441. if result, err := e2essh.SSH(dropCmd, from, TestContext.Provider); result.Code != 0 || err != nil {
  1442. e2essh.LogResult(result)
  1443. Failf("Unexpected error: %v", err)
  1444. }
  1445. }
  1446. // UnblockNetwork unblocks network between the given from value and the given to value.
  1447. func UnblockNetwork(from string, to string) {
  1448. Logf("Unblock network traffic from %s to %s", from, to)
  1449. iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to)
  1450. undropCmd := fmt.Sprintf("sudo iptables --delete %s", iptablesRule)
  1451. // Undrop command may fail if the rule has never been created.
  1452. // In such case we just lose 30 seconds, but the cluster is healthy.
  1453. // But if the rule had been created and removing it failed, the node is broken and
  1454. // not coming back. Subsequent tests will run or fewer nodes (some of the tests
  1455. // may fail). Manual intervention is required in such case (recreating the
  1456. // cluster solves the problem too).
  1457. err := wait.Poll(time.Millisecond*100, time.Second*30, func() (bool, error) {
  1458. result, err := e2essh.SSH(undropCmd, from, TestContext.Provider)
  1459. if result.Code == 0 && err == nil {
  1460. return true, nil
  1461. }
  1462. e2essh.LogResult(result)
  1463. if err != nil {
  1464. Logf("Unexpected error: %v", err)
  1465. }
  1466. return false, nil
  1467. })
  1468. if err != nil {
  1469. Failf("Failed to remove the iptable REJECT rule. Manual intervention is "+
  1470. "required on host %s: remove rule %s, if exists", from, iptablesRule)
  1471. }
  1472. }
  1473. // CoreDump SSHs to the master and all nodes and dumps their logs into dir.
  1474. // It shells out to cluster/log-dump/log-dump.sh to accomplish this.
  1475. func CoreDump(dir string) {
  1476. if TestContext.DisableLogDump {
  1477. Logf("Skipping dumping logs from cluster")
  1478. return
  1479. }
  1480. var cmd *exec.Cmd
  1481. if TestContext.LogexporterGCSPath != "" {
  1482. Logf("Dumping logs from nodes to GCS directly at path: %s", TestContext.LogexporterGCSPath)
  1483. cmd = exec.Command(path.Join(TestContext.RepoRoot, "cluster", "log-dump", "log-dump.sh"), dir, TestContext.LogexporterGCSPath)
  1484. } else {
  1485. Logf("Dumping logs locally to: %s", dir)
  1486. cmd = exec.Command(path.Join(TestContext.RepoRoot, "cluster", "log-dump", "log-dump.sh"), dir)
  1487. }
  1488. cmd.Env = append(os.Environ(), fmt.Sprintf("LOG_DUMP_SYSTEMD_SERVICES=%s", parseSystemdServices(TestContext.SystemdServices)))
  1489. cmd.Env = append(os.Environ(), fmt.Sprintf("LOG_DUMP_SYSTEMD_JOURNAL=%v", TestContext.DumpSystemdJournal))
  1490. cmd.Stdout = os.Stdout
  1491. cmd.Stderr = os.Stderr
  1492. if err := cmd.Run(); err != nil {
  1493. Logf("Error running cluster/log-dump/log-dump.sh: %v", err)
  1494. }
  1495. }
  1496. // parseSystemdServices converts services separator from comma to space.
  1497. func parseSystemdServices(services string) string {
  1498. return strings.TrimSpace(strings.Replace(services, ",", " ", -1))
  1499. }
  1500. // RunCmd runs cmd using args and returns its stdout and stderr. It also outputs
  1501. // cmd's stdout and stderr to their respective OS streams.
  1502. func RunCmd(command string, args ...string) (string, string, error) {
  1503. return RunCmdEnv(nil, command, args...)
  1504. }
  1505. // RunCmdEnv runs cmd with the provided environment and args and
  1506. // returns its stdout and stderr. It also outputs cmd's stdout and
  1507. // stderr to their respective OS streams.
  1508. func RunCmdEnv(env []string, command string, args ...string) (string, string, error) {
  1509. Logf("Running %s %v", command, args)
  1510. var bout, berr bytes.Buffer
  1511. cmd := exec.Command(command, args...)
  1512. // We also output to the OS stdout/stderr to aid in debugging in case cmd
  1513. // hangs and never returns before the test gets killed.
  1514. //
  1515. // This creates some ugly output because gcloud doesn't always provide
  1516. // newlines.
  1517. cmd.Stdout = io.MultiWriter(os.Stdout, &bout)
  1518. cmd.Stderr = io.MultiWriter(os.Stderr, &berr)
  1519. cmd.Env = env
  1520. err := cmd.Run()
  1521. stdout, stderr := bout.String(), berr.String()
  1522. if err != nil {
  1523. return "", "", fmt.Errorf("error running %s %v; got error %v, stdout %q, stderr %q",
  1524. command, args, err, stdout, stderr)
  1525. }
  1526. return stdout, stderr, nil
  1527. }
  1528. // E2ETestNodePreparer implements testutils.TestNodePreparer interface, which is used
  1529. // to create/modify Nodes before running a test.
  1530. type E2ETestNodePreparer struct {
  1531. client clientset.Interface
  1532. // Specifies how many nodes should be modified using the given strategy.
  1533. // Only one strategy can be applied to a single Node, so there needs to
  1534. // be at least <sum_of_keys> Nodes in the cluster.
  1535. countToStrategy []testutils.CountToStrategy
  1536. nodeToAppliedStrategy map[string]testutils.PrepareNodeStrategy
  1537. }
  1538. // PrepareNodes prepares nodes in the cluster.
  1539. func (p *E2ETestNodePreparer) PrepareNodes() error {
  1540. nodes, err := e2enode.GetReadySchedulableNodes(p.client)
  1541. if err != nil {
  1542. return err
  1543. }
  1544. numTemplates := 0
  1545. for _, v := range p.countToStrategy {
  1546. numTemplates += v.Count
  1547. }
  1548. if numTemplates > len(nodes.Items) {
  1549. return fmt.Errorf("Can't prepare Nodes. Got more templates than existing Nodes")
  1550. }
  1551. index := 0
  1552. sum := 0
  1553. for _, v := range p.countToStrategy {
  1554. sum += v.Count
  1555. for ; index < sum; index++ {
  1556. if err := testutils.DoPrepareNode(p.client, &nodes.Items[index], v.Strategy); err != nil {
  1557. klog.Errorf("Aborting node preparation: %v", err)
  1558. return err
  1559. }
  1560. p.nodeToAppliedStrategy[nodes.Items[index].Name] = v.Strategy
  1561. }
  1562. }
  1563. return nil
  1564. }
  1565. // CleanupNodes cleanups nodes in the cluster.
  1566. func (p *E2ETestNodePreparer) CleanupNodes() error {
  1567. var encounteredError error
  1568. nodes, err := e2enode.GetReadySchedulableNodes(p.client)
  1569. if err != nil {
  1570. return err
  1571. }
  1572. for i := range nodes.Items {
  1573. name := nodes.Items[i].Name
  1574. strategy, found := p.nodeToAppliedStrategy[name]
  1575. if found {
  1576. if err = testutils.DoCleanupNode(p.client, name, strategy); err != nil {
  1577. klog.Errorf("Skipping cleanup of Node: failed update of %v: %v", name, err)
  1578. encounteredError = err
  1579. }
  1580. }
  1581. }
  1582. return encounteredError
  1583. }
  1584. // getMasterAddresses returns the externalIP, internalIP and hostname fields of the master.
  1585. // If any of these is unavailable, it is set to "".
  1586. func getMasterAddresses(c clientset.Interface) (string, string, string) {
  1587. var externalIP, internalIP, hostname string
  1588. // Populate the internal IP.
  1589. eps, err := c.CoreV1().Endpoints(metav1.NamespaceDefault).Get(context.TODO(), "kubernetes", metav1.GetOptions{})
  1590. if err != nil {
  1591. Failf("Failed to get kubernetes endpoints: %v", err)
  1592. }
  1593. if len(eps.Subsets) != 1 || len(eps.Subsets[0].Addresses) != 1 {
  1594. Failf("There are more than 1 endpoints for kubernetes service: %+v", eps)
  1595. }
  1596. internalIP = eps.Subsets[0].Addresses[0].IP
  1597. // Populate the external IP/hostname.
  1598. hostURL, err := url.Parse(TestContext.Host)
  1599. if err != nil {
  1600. Failf("Failed to parse hostname: %v", err)
  1601. }
  1602. if net.ParseIP(hostURL.Host) != nil {
  1603. externalIP = hostURL.Host
  1604. } else {
  1605. hostname = hostURL.Host
  1606. }
  1607. return externalIP, internalIP, hostname
  1608. }
  1609. // GetAllMasterAddresses returns all IP addresses on which the kubelet can reach the master.
  1610. // It may return internal and external IPs, even if we expect for
  1611. // e.g. internal IPs to be used (issue #56787), so that we can be
  1612. // sure to block the master fully during tests.
  1613. func GetAllMasterAddresses(c clientset.Interface) []string {
  1614. externalIP, internalIP, _ := getMasterAddresses(c)
  1615. ips := sets.NewString()
  1616. switch TestContext.Provider {
  1617. case "gce", "gke":
  1618. if externalIP != "" {
  1619. ips.Insert(externalIP)
  1620. }
  1621. if internalIP != "" {
  1622. ips.Insert(internalIP)
  1623. }
  1624. case "aws":
  1625. ips.Insert(awsMasterIP)
  1626. default:
  1627. Failf("This test is not supported for provider %s and should be disabled", TestContext.Provider)
  1628. }
  1629. return ips.List()
  1630. }
  1631. // DescribeIng describes information of ingress by running kubectl describe ing.
  1632. func DescribeIng(ns string) {
  1633. Logf("\nOutput of kubectl describe ing:\n")
  1634. desc, _ := RunKubectl(
  1635. ns, "describe", "ing", fmt.Sprintf("--namespace=%v", ns))
  1636. Logf(desc)
  1637. }
  1638. // NewTestPod returns a pod that has the specified requests and limits
  1639. func (f *Framework) NewTestPod(name string, requests v1.ResourceList, limits v1.ResourceList) *v1.Pod {
  1640. return &v1.Pod{
  1641. ObjectMeta: metav1.ObjectMeta{
  1642. Name: name,
  1643. },
  1644. Spec: v1.PodSpec{
  1645. Containers: []v1.Container{
  1646. {
  1647. Name: "pause",
  1648. Image: imageutils.GetPauseImageName(),
  1649. Resources: v1.ResourceRequirements{
  1650. Requests: requests,
  1651. Limits: limits,
  1652. },
  1653. },
  1654. },
  1655. },
  1656. }
  1657. }
  1658. // NewAgnhostPod returns a pod that uses the agnhost image. The image's binary supports various subcommands
  1659. // that behave the same, no matter the underlying OS.
  1660. func (f *Framework) NewAgnhostPod(name string, args ...string) *v1.Pod {
  1661. return &v1.Pod{
  1662. ObjectMeta: metav1.ObjectMeta{
  1663. Name: name,
  1664. },
  1665. Spec: v1.PodSpec{
  1666. Containers: []v1.Container{
  1667. {
  1668. Name: "agnhost",
  1669. Image: AgnHostImage,
  1670. Args: args,
  1671. },
  1672. },
  1673. },
  1674. }
  1675. }
  1676. // CreateEmptyFileOnPod creates empty file at given path on the pod.
  1677. // TODO(alejandrox1): move to subpkg pod once kubectl methods have been refactored.
  1678. func CreateEmptyFileOnPod(namespace string, podName string, filePath string) error {
  1679. _, err := RunKubectl(namespace, "exec", fmt.Sprintf("--namespace=%s", namespace), podName, "--", "/bin/sh", "-c", fmt.Sprintf("touch %s", filePath))
  1680. return err
  1681. }
  1682. // DumpDebugInfo dumps debug info of tests.
  1683. func DumpDebugInfo(c clientset.Interface, ns string) {
  1684. sl, _ := c.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: labels.Everything().String()})
  1685. for _, s := range sl.Items {
  1686. desc, _ := RunKubectl(ns, "describe", "po", s.Name, fmt.Sprintf("--namespace=%v", ns))
  1687. Logf("\nOutput of kubectl describe %v:\n%v", s.Name, desc)
  1688. l, _ := RunKubectl(ns, "logs", s.Name, fmt.Sprintf("--namespace=%v", ns), "--tail=100")
  1689. Logf("\nLast 100 log lines of %v:\n%v", s.Name, l)
  1690. }
  1691. }
  1692. // DsFromManifest reads a .json/yaml file and returns the daemonset in it.
  1693. func DsFromManifest(url string) (*appsv1.DaemonSet, error) {
  1694. var ds appsv1.DaemonSet
  1695. Logf("Parsing ds from %v", url)
  1696. var response *http.Response
  1697. var err error
  1698. for i := 1; i <= 5; i++ {
  1699. response, err = http.Get(url)
  1700. if err == nil && response.StatusCode == 200 {
  1701. break
  1702. }
  1703. time.Sleep(time.Duration(i) * time.Second)
  1704. }
  1705. if err != nil {
  1706. return nil, fmt.Errorf("Failed to get url: %v", err)
  1707. }
  1708. if response.StatusCode != 200 {
  1709. return nil, fmt.Errorf("invalid http response status: %v", response.StatusCode)
  1710. }
  1711. defer response.Body.Close()
  1712. data, err := ioutil.ReadAll(response.Body)
  1713. if err != nil {
  1714. return nil, fmt.Errorf("Failed to read html response body: %v", err)
  1715. }
  1716. dataJSON, err := utilyaml.ToJSON(data)
  1717. if err != nil {
  1718. return nil, fmt.Errorf("Failed to parse data to json: %v", err)
  1719. }
  1720. err = runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), dataJSON, &ds)
  1721. if err != nil {
  1722. return nil, fmt.Errorf("Failed to decode DaemonSet spec: %v", err)
  1723. }
  1724. return &ds, nil
  1725. }
  1726. // GetClusterZones returns the values of zone label collected from all nodes.
  1727. func GetClusterZones(c clientset.Interface) (sets.String, error) {
  1728. nodes, err := c.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
  1729. if err != nil {
  1730. return nil, fmt.Errorf("Error getting nodes while attempting to list cluster zones: %v", err)
  1731. }
  1732. // collect values of zone label from all nodes
  1733. zones := sets.NewString()
  1734. for _, node := range nodes.Items {
  1735. if zone, found := node.Labels[v1.LabelZoneFailureDomain]; found {
  1736. zones.Insert(zone)
  1737. }
  1738. if zone, found := node.Labels[v1.LabelZoneFailureDomainStable]; found {
  1739. zones.Insert(zone)
  1740. }
  1741. }
  1742. return zones, nil
  1743. }
  1744. // GetFileModeRegex returns a file mode related regex which should be matched by the mounttest pods' output.
  1745. // If the given mask is nil, then the regex will contain the default OS file modes, which are 0644 for Linux and 0775 for Windows.
  1746. func GetFileModeRegex(filePath string, mask *int32) string {
  1747. var (
  1748. linuxMask int32
  1749. windowsMask int32
  1750. )
  1751. if mask == nil {
  1752. linuxMask = int32(0644)
  1753. windowsMask = int32(0775)
  1754. } else {
  1755. linuxMask = *mask
  1756. windowsMask = *mask
  1757. }
  1758. linuxOutput := fmt.Sprintf("mode of file \"%s\": %v", filePath, os.FileMode(linuxMask))
  1759. windowsOutput := fmt.Sprintf("mode of Windows file \"%v\": %s", filePath, os.FileMode(windowsMask))
  1760. return fmt.Sprintf("(%s|%s)", linuxOutput, windowsOutput)
  1761. }
  1762. // PrettyPrintJSON converts metrics to JSON format.
  1763. func PrettyPrintJSON(metrics interface{}) string {
  1764. output := &bytes.Buffer{}
  1765. if err := json.NewEncoder(output).Encode(metrics); err != nil {
  1766. Logf("Error building encoder: %v", err)
  1767. return ""
  1768. }
  1769. formatted := &bytes.Buffer{}
  1770. if err := json.Indent(formatted, output.Bytes(), "", " "); err != nil {
  1771. Logf("Error indenting: %v", err)
  1772. return ""
  1773. }
  1774. return string(formatted.Bytes())
  1775. }