1# This file is part of Buildbot. Buildbot is free software: you can 2# redistribute it and/or modify it under the terms of the GNU General Public 3# License as published by the Free Software Foundation, version 2. 4# 5# This program is distributed in the hope that it will be useful, but WITHOUT 6# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 7# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 8# details. 9# 10# You should have received a copy of the GNU General Public License along with 11# this program; if not, write to the Free Software Foundation, Inc., 51 12# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 13# 14# Copyright Buildbot Team Members 15 16import os 17from unittest.case import SkipTest 18 19from twisted.internet import defer 20 21from buildbot.config import BuilderConfig 22from buildbot.plugins import schedulers 23from buildbot.plugins import steps 24from buildbot.process.factory import BuildFactory 25from buildbot.process.results import SUCCESS 26from buildbot.test.util.integration import RunMasterBase 27from buildbot.util import kubeclientservice 28from buildbot.worker import kubernetes 29 30# This integration test creates a master and kubernetes worker environment, 31# It requires a kubernetes cluster up and running. It tries to get the config 32# like loading "~/.kube/config" files or environment variable. 33# You can use minikube to create a kubernetes environment for development: 34 35# # See https://github.com/kubernetes/minikube for full documentation 36# minikube start # [--vm-driver=kvm] 37# 38# export masterFQDN=$(ip route get $(minikube ip)| awk '{ print $5 }') 39# export KUBE_NAMESPACE=`kubectl config get-contexts \`kubectl config current-context\` 40# |tail -n1 |awk '{print $5}'` 41 42# useful commands: 43# - 'minikube dashboard' to display WebUI of the kubernetes cluster 44# - 'minikube ip' to display the IP of the kube-apimaster 45# - 'minikube ssh' to get a shell into the minikube VM 46 47# following environment variable can be used to stress concurrent worker startup 48NUM_CONCURRENT = int(os.environ.get("KUBE_TEST_NUM_CONCURRENT_BUILD", 1)) 49 50 51class KubernetesMaster(RunMasterBase): 52 timeout = 200 53 54 def setUp(self): 55 if "TEST_KUBERNETES" not in os.environ: 56 raise SkipTest( 57 "kubernetes integration tests only run when environment " 58 "variable TEST_KUBERNETES is set") 59 if 'masterFQDN' not in os.environ: 60 raise SkipTest( 61 "you need to export masterFQDN. You have example in the test file. " 62 "Make sure that you're spawned worker can callback this IP") 63 64 @defer.inlineCallbacks 65 def test_trigger(self): 66 yield self.setupConfig( 67 masterConfig(num_concurrent=NUM_CONCURRENT), startWorker=False) 68 yield self.doForceBuild() 69 70 builds = yield self.master.data.get(("builds", )) 71 # if there are some retry, there will be more builds 72 self.assertEqual(len(builds), 1 + NUM_CONCURRENT) 73 for b in builds: 74 self.assertEqual(b['results'], SUCCESS) 75 76 77class KubernetesMasterTReq(KubernetesMaster): 78 def setup(self): 79 super().setUp() 80 self.patch(kubernetes.KubeClientService, 'PREFER_TREQ', True) 81 82 83# master configuration 84def masterConfig(num_concurrent, extra_steps=None): 85 if extra_steps is None: 86 extra_steps = [] 87 c = {} 88 89 c['schedulers'] = [ 90 schedulers.ForceScheduler(name="force", builderNames=["testy"]) 91 ] 92 triggereables = [] 93 for i in range(num_concurrent): 94 c['schedulers'].append( 95 schedulers.Triggerable( 96 name="trigsched" + str(i), builderNames=["build"])) 97 triggereables.append("trigsched" + str(i)) 98 99 f = BuildFactory() 100 f.addStep(steps.ShellCommand(command='echo hello')) 101 f.addStep( 102 steps.Trigger( 103 schedulerNames=triggereables, 104 waitForFinish=True, 105 updateSourceStamp=True)) 106 f.addStep(steps.ShellCommand(command='echo world')) 107 f2 = BuildFactory() 108 f2.addStep(steps.ShellCommand(command='echo ola')) 109 for step in extra_steps: 110 f2.addStep(step) 111 c['builders'] = [ 112 BuilderConfig(name="testy", workernames=["kubernetes0"], factory=f), 113 BuilderConfig( 114 name="build", 115 workernames=["kubernetes" + str(i) for i in range(num_concurrent)], 116 factory=f2) 117 ] 118 masterFQDN = os.environ.get('masterFQDN') 119 c['workers'] = [ 120 kubernetes.KubeLatentWorker( 121 'kubernetes' + str(i), 122 'buildbot/buildbot-worker', 123 kube_config=kubeclientservice.KubeCtlProxyConfigLoader( 124 namespace=os.getenv("KUBE_NAMESPACE", "default")), 125 masterFQDN=masterFQDN) for i in range(num_concurrent) 126 ] 127 # un comment for debugging what happens if things looks locked. 128 # c['www'] = {'port': 8080} 129 c['protocols'] = {"pb": {"port": "tcp:9989"}} 130 131 return c 132