cluster_upgrade.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. Copyright 2016 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 gcp
  14. import (
  15. "encoding/xml"
  16. "fmt"
  17. "os"
  18. "os/exec"
  19. "path"
  20. "path/filepath"
  21. "regexp"
  22. "strings"
  23. "sync"
  24. "time"
  25. utilversion "k8s.io/apimachinery/pkg/util/version"
  26. "k8s.io/apimachinery/pkg/util/wait"
  27. "k8s.io/apimachinery/pkg/version"
  28. "k8s.io/client-go/discovery"
  29. clientset "k8s.io/client-go/kubernetes"
  30. "k8s.io/kubernetes/test/e2e/chaosmonkey"
  31. "k8s.io/kubernetes/test/e2e/framework"
  32. "k8s.io/kubernetes/test/e2e/framework/config"
  33. "k8s.io/kubernetes/test/e2e/framework/ginkgowrapper"
  34. e2enode "k8s.io/kubernetes/test/e2e/framework/node"
  35. e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
  36. "k8s.io/kubernetes/test/e2e/upgrades"
  37. apps "k8s.io/kubernetes/test/e2e/upgrades/apps"
  38. "k8s.io/kubernetes/test/e2e/upgrades/storage"
  39. "k8s.io/kubernetes/test/utils/junit"
  40. "github.com/onsi/ginkgo"
  41. )
  42. var (
  43. upgradeTarget = config.Flags.String("upgrade-target", "ci/latest", "Version to upgrade to (e.g. 'release/stable', 'release/latest', 'ci/latest', '0.19.1', '0.19.1-669-gabac8c8') if doing an upgrade test.")
  44. upgradeImage = config.Flags.String("upgrade-image", "", "Image to upgrade to (e.g. 'container_vm' or 'gci') if doing an upgrade test.")
  45. )
  46. var upgradeTests = []upgrades.Test{
  47. &upgrades.ServiceUpgradeTest{},
  48. &upgrades.SecretUpgradeTest{},
  49. &apps.ReplicaSetUpgradeTest{},
  50. &apps.StatefulSetUpgradeTest{},
  51. &apps.DeploymentUpgradeTest{},
  52. &apps.JobUpgradeTest{},
  53. &upgrades.ConfigMapUpgradeTest{},
  54. &upgrades.HPAUpgradeTest{},
  55. &storage.PersistentVolumeUpgradeTest{},
  56. &apps.DaemonSetUpgradeTest{},
  57. &upgrades.AppArmorUpgradeTest{},
  58. &storage.VolumeModeDowngradeTest{},
  59. }
  60. var gpuUpgradeTests = []upgrades.Test{
  61. &upgrades.NvidiaGPUUpgradeTest{},
  62. }
  63. var statefulsetUpgradeTests = []upgrades.Test{
  64. &upgrades.MySQLUpgradeTest{},
  65. &upgrades.EtcdUpgradeTest{},
  66. &upgrades.CassandraUpgradeTest{},
  67. }
  68. var kubeProxyUpgradeTests = []upgrades.Test{
  69. &upgrades.KubeProxyUpgradeTest{},
  70. &upgrades.ServiceUpgradeTest{},
  71. }
  72. var kubeProxyDowngradeTests = []upgrades.Test{
  73. &upgrades.KubeProxyDowngradeTest{},
  74. &upgrades.ServiceUpgradeTest{},
  75. }
  76. var _ = SIGDescribe("Upgrade [Feature:Upgrade]", func() {
  77. f := framework.NewDefaultFramework("cluster-upgrade")
  78. // Create the frameworks here because we can only create them
  79. // in a "Describe".
  80. testFrameworks := createUpgradeFrameworks(upgradeTests)
  81. ginkgo.Describe("master upgrade", func() {
  82. ginkgo.It("should maintain a functioning cluster [Feature:MasterUpgrade]", func() {
  83. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  84. framework.ExpectNoError(err)
  85. testSuite := &junit.TestSuite{Name: "Master upgrade"}
  86. masterUpgradeTest := &junit.TestCase{
  87. Name: "[sig-cloud-provider-gcp] master-upgrade",
  88. Classname: "upgrade_tests",
  89. }
  90. testSuite.TestCases = append(testSuite.TestCases, masterUpgradeTest)
  91. upgradeFunc := func() {
  92. start := time.Now()
  93. defer finalizeUpgradeTest(start, masterUpgradeTest)
  94. target := upgCtx.Versions[1].Version.String()
  95. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  96. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  97. }
  98. runUpgradeSuite(f, upgradeTests, testFrameworks, testSuite, upgrades.MasterUpgrade, upgradeFunc)
  99. })
  100. })
  101. ginkgo.Describe("node upgrade", func() {
  102. ginkgo.It("should maintain a functioning cluster [Feature:NodeUpgrade]", func() {
  103. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  104. framework.ExpectNoError(err)
  105. testSuite := &junit.TestSuite{Name: "Node upgrade"}
  106. nodeUpgradeTest := &junit.TestCase{
  107. Name: "node-upgrade",
  108. Classname: "upgrade_tests",
  109. }
  110. upgradeFunc := func() {
  111. start := time.Now()
  112. defer finalizeUpgradeTest(start, nodeUpgradeTest)
  113. target := upgCtx.Versions[1].Version.String()
  114. framework.ExpectNoError(framework.NodeUpgrade(f, target, *upgradeImage))
  115. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  116. }
  117. runUpgradeSuite(f, upgradeTests, testFrameworks, testSuite, upgrades.NodeUpgrade, upgradeFunc)
  118. })
  119. })
  120. ginkgo.Describe("cluster upgrade", func() {
  121. ginkgo.It("should maintain a functioning cluster [Feature:ClusterUpgrade]", func() {
  122. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  123. framework.ExpectNoError(err)
  124. testSuite := &junit.TestSuite{Name: "Cluster upgrade"}
  125. clusterUpgradeTest := &junit.TestCase{Name: "[sig-cloud-provider-gcp] cluster-upgrade", Classname: "upgrade_tests"}
  126. testSuite.TestCases = append(testSuite.TestCases, clusterUpgradeTest)
  127. upgradeFunc := func() {
  128. start := time.Now()
  129. defer finalizeUpgradeTest(start, clusterUpgradeTest)
  130. target := upgCtx.Versions[1].Version.String()
  131. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  132. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  133. framework.ExpectNoError(framework.NodeUpgrade(f, target, *upgradeImage))
  134. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  135. }
  136. runUpgradeSuite(f, upgradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  137. })
  138. })
  139. })
  140. var _ = SIGDescribe("Downgrade [Feature:Downgrade]", func() {
  141. f := framework.NewDefaultFramework("cluster-downgrade")
  142. // Create the frameworks here because we can only create them
  143. // in a "Describe".
  144. testFrameworks := createUpgradeFrameworks(upgradeTests)
  145. ginkgo.Describe("cluster downgrade", func() {
  146. ginkgo.It("should maintain a functioning cluster [Feature:ClusterDowngrade]", func() {
  147. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  148. framework.ExpectNoError(err)
  149. testSuite := &junit.TestSuite{Name: "Cluster downgrade"}
  150. clusterDowngradeTest := &junit.TestCase{Name: "[sig-cloud-provider-gcp] cluster-downgrade", Classname: "upgrade_tests"}
  151. testSuite.TestCases = append(testSuite.TestCases, clusterDowngradeTest)
  152. upgradeFunc := func() {
  153. start := time.Now()
  154. defer finalizeUpgradeTest(start, clusterDowngradeTest)
  155. // Yes this really is a downgrade. And nodes must downgrade first.
  156. target := upgCtx.Versions[1].Version.String()
  157. framework.ExpectNoError(framework.NodeUpgrade(f, target, *upgradeImage))
  158. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  159. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  160. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  161. }
  162. runUpgradeSuite(f, upgradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  163. })
  164. })
  165. })
  166. var _ = SIGDescribe("etcd Upgrade [Feature:EtcdUpgrade]", func() {
  167. f := framework.NewDefaultFramework("etc-upgrade")
  168. // Create the frameworks here because we can only create them
  169. // in a "Describe".
  170. testFrameworks := createUpgradeFrameworks(upgradeTests)
  171. ginkgo.Describe("etcd upgrade", func() {
  172. ginkgo.It("should maintain a functioning cluster", func() {
  173. testSuite := &junit.TestSuite{Name: "Etcd upgrade"}
  174. etcdTest := &junit.TestCase{Name: "[sig-cloud-provider-gcp] etcd-upgrade", Classname: "upgrade_tests"}
  175. testSuite.TestCases = append(testSuite.TestCases, etcdTest)
  176. upgradeFunc := func() {
  177. start := time.Now()
  178. defer finalizeUpgradeTest(start, etcdTest)
  179. framework.ExpectNoError(framework.EtcdUpgrade(framework.TestContext.EtcdUpgradeStorage, framework.TestContext.EtcdUpgradeVersion))
  180. }
  181. runUpgradeSuite(f, upgradeTests, testFrameworks, testSuite, upgrades.EtcdUpgrade, upgradeFunc)
  182. })
  183. })
  184. })
  185. var _ = SIGDescribe("gpu Upgrade [Feature:GPUUpgrade]", func() {
  186. f := framework.NewDefaultFramework("gpu-upgrade")
  187. // Create the frameworks here because we can only create them
  188. // in a "Describe".
  189. testFrameworks := createUpgradeFrameworks(gpuUpgradeTests)
  190. ginkgo.Describe("master upgrade", func() {
  191. ginkgo.It("should NOT disrupt gpu pod [Feature:GPUMasterUpgrade]", func() {
  192. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  193. framework.ExpectNoError(err)
  194. testSuite := &junit.TestSuite{Name: "GPU master upgrade"}
  195. gpuUpgradeTest := &junit.TestCase{Name: "[sig-node] gpu-master-upgrade", Classname: "upgrade_tests"}
  196. testSuite.TestCases = append(testSuite.TestCases, gpuUpgradeTest)
  197. upgradeFunc := func() {
  198. start := time.Now()
  199. defer finalizeUpgradeTest(start, gpuUpgradeTest)
  200. target := upgCtx.Versions[1].Version.String()
  201. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  202. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  203. }
  204. runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgrades.MasterUpgrade, upgradeFunc)
  205. })
  206. })
  207. ginkgo.Describe("cluster upgrade", func() {
  208. ginkgo.It("should be able to run gpu pod after upgrade [Feature:GPUClusterUpgrade]", func() {
  209. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  210. framework.ExpectNoError(err)
  211. testSuite := &junit.TestSuite{Name: "GPU cluster upgrade"}
  212. gpuUpgradeTest := &junit.TestCase{Name: "[sig-node] gpu-cluster-upgrade", Classname: "upgrade_tests"}
  213. testSuite.TestCases = append(testSuite.TestCases, gpuUpgradeTest)
  214. upgradeFunc := func() {
  215. start := time.Now()
  216. defer finalizeUpgradeTest(start, gpuUpgradeTest)
  217. target := upgCtx.Versions[1].Version.String()
  218. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  219. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  220. framework.ExpectNoError(framework.NodeUpgrade(f, target, *upgradeImage))
  221. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  222. }
  223. runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  224. })
  225. })
  226. ginkgo.Describe("cluster downgrade", func() {
  227. ginkgo.It("should be able to run gpu pod after downgrade [Feature:GPUClusterDowngrade]", func() {
  228. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  229. framework.ExpectNoError(err)
  230. testSuite := &junit.TestSuite{Name: "GPU cluster downgrade"}
  231. gpuDowngradeTest := &junit.TestCase{Name: "[sig-node] gpu-cluster-downgrade", Classname: "upgrade_tests"}
  232. testSuite.TestCases = append(testSuite.TestCases, gpuDowngradeTest)
  233. upgradeFunc := func() {
  234. start := time.Now()
  235. defer finalizeUpgradeTest(start, gpuDowngradeTest)
  236. target := upgCtx.Versions[1].Version.String()
  237. framework.ExpectNoError(framework.NodeUpgrade(f, target, *upgradeImage))
  238. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  239. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  240. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  241. }
  242. runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  243. })
  244. })
  245. })
  246. var _ = ginkgo.Describe("[sig-apps] stateful Upgrade [Feature:StatefulUpgrade]", func() {
  247. f := framework.NewDefaultFramework("stateful-upgrade")
  248. // Create the frameworks here because we can only create them
  249. // in a "Describe".
  250. testFrameworks := createUpgradeFrameworks(statefulsetUpgradeTests)
  251. framework.KubeDescribe("stateful upgrade", func() {
  252. ginkgo.It("should maintain a functioning cluster", func() {
  253. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  254. framework.ExpectNoError(err)
  255. testSuite := &junit.TestSuite{Name: "Stateful upgrade"}
  256. statefulUpgradeTest := &junit.TestCase{Name: "[sig-apps] stateful-upgrade", Classname: "upgrade_tests"}
  257. testSuite.TestCases = append(testSuite.TestCases, statefulUpgradeTest)
  258. upgradeFunc := func() {
  259. start := time.Now()
  260. defer finalizeUpgradeTest(start, statefulUpgradeTest)
  261. target := upgCtx.Versions[1].Version.String()
  262. framework.ExpectNoError(framework.MasterUpgrade(f, target))
  263. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  264. framework.ExpectNoError(framework.NodeUpgrade(f, target, *upgradeImage))
  265. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  266. }
  267. runUpgradeSuite(f, statefulsetUpgradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  268. })
  269. })
  270. })
  271. var _ = SIGDescribe("kube-proxy migration [Feature:KubeProxyDaemonSetMigration]", func() {
  272. f := framework.NewDefaultFramework("kube-proxy-ds-migration")
  273. ginkgo.BeforeEach(func() {
  274. e2eskipper.SkipUnlessProviderIs("gce")
  275. })
  276. ginkgo.Describe("Upgrade kube-proxy from static pods to a DaemonSet", func() {
  277. testFrameworks := createUpgradeFrameworks(kubeProxyUpgradeTests)
  278. ginkgo.It("should maintain a functioning cluster [Feature:KubeProxyDaemonSetUpgrade]", func() {
  279. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  280. framework.ExpectNoError(err)
  281. testSuite := &junit.TestSuite{Name: "kube-proxy upgrade"}
  282. kubeProxyUpgradeTest := &junit.TestCase{
  283. Name: "kube-proxy-ds-upgrade",
  284. Classname: "upgrade_tests",
  285. }
  286. testSuite.TestCases = append(testSuite.TestCases, kubeProxyUpgradeTest)
  287. upgradeFunc := func() {
  288. start := time.Now()
  289. defer finalizeUpgradeTest(start, kubeProxyUpgradeTest)
  290. target := upgCtx.Versions[1].Version.String()
  291. framework.ExpectNoError(framework.MasterUpgradeGCEWithKubeProxyDaemonSet(target, true))
  292. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  293. framework.ExpectNoError(framework.NodeUpgradeGCEWithKubeProxyDaemonSet(f, target, *upgradeImage, true))
  294. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  295. }
  296. runUpgradeSuite(f, kubeProxyUpgradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  297. })
  298. })
  299. ginkgo.Describe("Downgrade kube-proxy from a DaemonSet to static pods", func() {
  300. testFrameworks := createUpgradeFrameworks(kubeProxyDowngradeTests)
  301. ginkgo.It("should maintain a functioning cluster [Feature:KubeProxyDaemonSetDowngrade]", func() {
  302. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  303. framework.ExpectNoError(err)
  304. testSuite := &junit.TestSuite{Name: "kube-proxy downgrade"}
  305. kubeProxyDowngradeTest := &junit.TestCase{
  306. Name: "kube-proxy-ds-downgrade",
  307. Classname: "upgrade_tests",
  308. }
  309. testSuite.TestCases = append(testSuite.TestCases, kubeProxyDowngradeTest)
  310. upgradeFunc := func() {
  311. start := time.Now()
  312. defer finalizeUpgradeTest(start, kubeProxyDowngradeTest)
  313. // Yes this really is a downgrade. And nodes must downgrade first.
  314. target := upgCtx.Versions[1].Version.String()
  315. framework.ExpectNoError(framework.NodeUpgradeGCEWithKubeProxyDaemonSet(f, target, *upgradeImage, false))
  316. framework.ExpectNoError(checkNodesVersions(f.ClientSet, target))
  317. framework.ExpectNoError(framework.MasterUpgradeGCEWithKubeProxyDaemonSet(target, false))
  318. framework.ExpectNoError(checkMasterVersion(f.ClientSet, target))
  319. }
  320. runUpgradeSuite(f, kubeProxyDowngradeTests, testFrameworks, testSuite, upgrades.ClusterUpgrade, upgradeFunc)
  321. })
  322. })
  323. })
  324. type chaosMonkeyAdapter struct {
  325. test upgrades.Test
  326. testReport *junit.TestCase
  327. framework *framework.Framework
  328. upgradeType upgrades.UpgradeType
  329. upgCtx upgrades.UpgradeContext
  330. }
  331. func (cma *chaosMonkeyAdapter) Test(sem *chaosmonkey.Semaphore) {
  332. start := time.Now()
  333. var once sync.Once
  334. ready := func() {
  335. once.Do(func() {
  336. sem.Ready()
  337. })
  338. }
  339. defer finalizeUpgradeTest(start, cma.testReport)
  340. defer ready()
  341. if skippable, ok := cma.test.(upgrades.Skippable); ok && skippable.Skip(cma.upgCtx) {
  342. ginkgo.By("skipping test " + cma.test.Name())
  343. cma.testReport.Skipped = "skipping test " + cma.test.Name()
  344. return
  345. }
  346. defer cma.test.Teardown(cma.framework)
  347. cma.test.Setup(cma.framework)
  348. ready()
  349. cma.test.Test(cma.framework, sem.StopCh, cma.upgradeType)
  350. }
  351. func finalizeUpgradeTest(start time.Time, tc *junit.TestCase) {
  352. tc.Time = time.Since(start).Seconds()
  353. r := recover()
  354. if r == nil {
  355. return
  356. }
  357. switch r := r.(type) {
  358. case ginkgowrapper.FailurePanic:
  359. tc.Failures = []*junit.Failure{
  360. {
  361. Message: r.Message,
  362. Type: "Failure",
  363. Value: fmt.Sprintf("%s\n\n%s", r.Message, r.FullStackTrace),
  364. },
  365. }
  366. case e2eskipper.SkipPanic:
  367. tc.Skipped = fmt.Sprintf("%s:%d %q", r.Filename, r.Line, r.Message)
  368. default:
  369. tc.Errors = []*junit.Error{
  370. {
  371. Message: fmt.Sprintf("%v", r),
  372. Type: "Panic",
  373. Value: fmt.Sprintf("%v", r),
  374. },
  375. }
  376. }
  377. }
  378. func createUpgradeFrameworks(tests []upgrades.Test) map[string]*framework.Framework {
  379. nsFilter := regexp.MustCompile("[^[:word:]-]+") // match anything that's not a word character or hyphen
  380. testFrameworks := map[string]*framework.Framework{}
  381. for _, t := range tests {
  382. ns := nsFilter.ReplaceAllString(t.Name(), "-") // and replace with a single hyphen
  383. ns = strings.Trim(ns, "-")
  384. testFrameworks[t.Name()] = framework.NewDefaultFramework(ns)
  385. }
  386. return testFrameworks
  387. }
  388. func runUpgradeSuite(
  389. f *framework.Framework,
  390. tests []upgrades.Test,
  391. testFrameworks map[string]*framework.Framework,
  392. testSuite *junit.TestSuite,
  393. upgradeType upgrades.UpgradeType,
  394. upgradeFunc func(),
  395. ) {
  396. upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), *upgradeTarget)
  397. framework.ExpectNoError(err)
  398. cm := chaosmonkey.New(upgradeFunc)
  399. for _, t := range tests {
  400. testCase := &junit.TestCase{
  401. Name: t.Name(),
  402. Classname: "upgrade_tests",
  403. }
  404. testSuite.TestCases = append(testSuite.TestCases, testCase)
  405. cma := chaosMonkeyAdapter{
  406. test: t,
  407. testReport: testCase,
  408. framework: testFrameworks[t.Name()],
  409. upgradeType: upgradeType,
  410. upgCtx: *upgCtx,
  411. }
  412. cm.Register(cma.Test)
  413. }
  414. start := time.Now()
  415. defer func() {
  416. testSuite.Update()
  417. testSuite.Time = time.Since(start).Seconds()
  418. if framework.TestContext.ReportDir != "" {
  419. fname := filepath.Join(framework.TestContext.ReportDir, fmt.Sprintf("junit_%supgrades.xml", framework.TestContext.ReportPrefix))
  420. f, err := os.Create(fname)
  421. if err != nil {
  422. return
  423. }
  424. defer f.Close()
  425. xml.NewEncoder(f).Encode(testSuite)
  426. }
  427. }()
  428. cm.Do()
  429. }
  430. func getUpgradeContext(c discovery.DiscoveryInterface, upgradeTarget string) (*upgrades.UpgradeContext, error) {
  431. current, err := c.ServerVersion()
  432. if err != nil {
  433. return nil, err
  434. }
  435. curVer, err := utilversion.ParseSemantic(current.String())
  436. if err != nil {
  437. return nil, err
  438. }
  439. upgCtx := &upgrades.UpgradeContext{
  440. Versions: []upgrades.VersionContext{
  441. {
  442. Version: *curVer,
  443. NodeImage: framework.TestContext.NodeOSDistro,
  444. },
  445. },
  446. }
  447. if len(upgradeTarget) == 0 {
  448. return upgCtx, nil
  449. }
  450. next, err := realVersion(upgradeTarget)
  451. if err != nil {
  452. return nil, err
  453. }
  454. nextVer, err := utilversion.ParseSemantic(next)
  455. if err != nil {
  456. return nil, err
  457. }
  458. upgCtx.Versions = append(upgCtx.Versions, upgrades.VersionContext{
  459. Version: *nextVer,
  460. NodeImage: *upgradeImage,
  461. })
  462. return upgCtx, nil
  463. }
  464. // realVersion turns a version constants into a version string deployable on
  465. // GKE. See hack/get-build.sh for more information.
  466. func realVersion(s string) (string, error) {
  467. framework.Logf("Getting real version for %q", s)
  468. v, _, err := framework.RunCmd(path.Join(framework.TestContext.RepoRoot, "hack/get-build.sh"), "-v", s)
  469. if err != nil {
  470. return v, fmt.Errorf("error getting real version for %q: %v", s, err)
  471. }
  472. framework.Logf("Version for %q is %q", s, v)
  473. return strings.TrimPrefix(strings.TrimSpace(v), "v"), nil
  474. }
  475. func traceRouteToMaster() {
  476. traceroute, err := exec.LookPath("traceroute")
  477. if err != nil {
  478. framework.Logf("Could not find traceroute program")
  479. return
  480. }
  481. cmd := exec.Command(traceroute, "-I", framework.GetMasterHost())
  482. out, err := cmd.Output()
  483. if len(out) != 0 {
  484. framework.Logf(string(out))
  485. }
  486. if exiterr, ok := err.(*exec.ExitError); err != nil && ok {
  487. framework.Logf("Error while running traceroute: %s", exiterr.Stderr)
  488. }
  489. }
  490. // checkMasterVersion validates the master version
  491. func checkMasterVersion(c clientset.Interface, want string) error {
  492. framework.Logf("Checking master version")
  493. var err error
  494. var v *version.Info
  495. waitErr := wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) {
  496. v, err = c.Discovery().ServerVersion()
  497. if err != nil {
  498. traceRouteToMaster()
  499. return false, nil
  500. }
  501. return true, nil
  502. })
  503. if waitErr != nil {
  504. return fmt.Errorf("CheckMasterVersion() couldn't get the master version: %v", err)
  505. }
  506. // We do prefix trimming and then matching because:
  507. // want looks like: 0.19.3-815-g50e67d4
  508. // got looks like: v0.19.3-815-g50e67d4034e858-dirty
  509. got := strings.TrimPrefix(v.GitVersion, "v")
  510. if !strings.HasPrefix(got, want) {
  511. return fmt.Errorf("master had kube-apiserver version %s which does not start with %s", got, want)
  512. }
  513. framework.Logf("Master is at version %s", want)
  514. return nil
  515. }
  516. // checkNodesVersions validates the nodes versions
  517. func checkNodesVersions(cs clientset.Interface, want string) error {
  518. l, err := e2enode.GetReadySchedulableNodes(cs)
  519. if err != nil {
  520. return err
  521. }
  522. for _, n := range l.Items {
  523. // We do prefix trimming and then matching because:
  524. // want looks like: 0.19.3-815-g50e67d4
  525. // kv/kvp look like: v0.19.3-815-g50e67d4034e858-dirty
  526. kv, kpv := strings.TrimPrefix(n.Status.NodeInfo.KubeletVersion, "v"),
  527. strings.TrimPrefix(n.Status.NodeInfo.KubeProxyVersion, "v")
  528. if !strings.HasPrefix(kv, want) {
  529. return fmt.Errorf("node %s had kubelet version %s which does not start with %s",
  530. n.ObjectMeta.Name, kv, want)
  531. }
  532. if !strings.HasPrefix(kpv, want) {
  533. return fmt.Errorf("node %s had kube-proxy version %s which does not start with %s",
  534. n.ObjectMeta.Name, kpv, want)
  535. }
  536. }
  537. return nil
  538. }