def test_worker_sync_builds(self, storage): """Ensure Projects with "synchronous_builds" are assigned properly. 1. Create a "synchronous" Project 2. Add a RUNNING build and and QUEUED build 3. Create a regular Project with a QUEUED build Make sure the QUEUED build from the second Project is assigned rather than the *older* but blocked build from the first Project. """ if db.engine.dialect.name == 'sqlite': self.skipTest('Test requires MySQL') rundef = {'run_url': 'foo', 'runner_url': 'foo', 'env': {}} storage().get_run_definition.return_value = json.dumps(rundef) w = Worker('w1', 'ubuntu', 12, 2, 'aarch64', 'key', 2, ['aarch96']) w.enlisted = True w.online = True db.session.add(w) # create a "synchronous" builds project self.create_projects('job-1') p = Project.query.all()[0] p.synchronous_builds = True db.session.commit() # add an active build b = Build.create(p) r = Run(b, 'p1b1r1') r.host_tag = 'aarch96' r.status = BuildStatus.RUNNING db.session.add(r) # Queue up another run on this build. The project is sync, but the # runs in a single build can go in parallel r = Run(b, 'p1b1r2') r.host_tag = 'aarch96' db.session.add(r) # now queue a build up b = Build.create(p) r = Run(b, 'p1b2r1') r.host_tag = 'aarch97' # different host-tag, but should be blocked db.session.add(r) # create a normal project self.create_projects('job-2') p = Project.query.all()[1] db.session.commit() # queue up a build. This is "older" than the queued build for # the synchronous project, but should get selected below b = Build.create(p) r = Run(b, 'p2b1r1') r.host_tag = 'aarch97' db.session.add(r) db.session.commit() headers = [ ('Content-type', 'application/json'), ('Authorization', 'Token key'), ] qs = 'available_runners=1&foo=2' # This should make the p1b1r2 run running resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code, resp.data) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data['data']['worker']['run-defs'])) self.assertEqual( [ BuildStatus.RUNNING, BuildStatus.RUNNING, BuildStatus.QUEUED, BuildStatus.QUEUED ], # NOQA [x.status for x in Run.query]) # now job-1 should get blocked and job-2's run will get popped # lets change the host-tag to ensure this does *all* runs w.host_tags = ['aarch97'] db.session.commit() resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code, resp.data) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data['data']['worker']['run-defs'])) self.assertEqual( [ BuildStatus.RUNNING, BuildStatus.RUNNING, BuildStatus.QUEUED, BuildStatus.RUNNING ], # NOQA [x.status for x in Run.query])
def test_worker_sync_builds(self, storage): """Ensure Projects with "synchronous_builds" are assigned properly. 1. Create a "synchronous" Project 2. Add a RUNNING build and and QUEUED build 3. Create a regular Project with a QUEUED build Make sure the QUEUED build from the second Project is assigned rather than the *older* but blocked build from the first Project. """ if db.engine.dialect.name == "sqlite": self.skipTest("Test requires MySQL") rundef = {"run_url": "foo", "runner_url": "foo", "env": {}} storage().get_run_definition.return_value = json.dumps(rundef) w = Worker("w1", "ubuntu", 12, 2, "aarch64", "key", 2, ["aarch96"]) w.enlisted = True w.online = True db.session.add(w) # create a "synchronous" builds project self.create_projects("job-1") p = Project.query.all()[0] p.synchronous_builds = True db.session.commit() # add an active build b = Build.create(p) r = Run(b, "p1b1r1") r.host_tag = "aarch96" r.status = BuildStatus.RUNNING db.session.add(r) # Queue up another run on this build. The project is sync, but the # runs in a single build can go in parallel r = Run(b, "p1b1r2") r.host_tag = "aarch96" db.session.add(r) # now queue a build up b = Build.create(p) r = Run(b, "p1b2r1") r.host_tag = "aarch97" # different host-tag, but should be blocked db.session.add(r) # create a normal project self.create_projects("job-2") p = Project.query.all()[1] db.session.commit() # queue up a build. This is "older" than the queued build for # the synchronous project, but should get selected below b = Build.create(p) r = Run(b, "p2b1r1") r.host_tag = "aarch97" db.session.add(r) db.session.commit() headers = [ ("Content-type", "application/json"), ("Authorization", "Token key"), ] qs = "available_runners=1&foo=2" # This should make the p1b1r2 run running resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code, resp.data) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data["data"]["worker"]["run-defs"])) self.assertEqual( [ BuildStatus.RUNNING, BuildStatus.RUNNING, BuildStatus.QUEUED, BuildStatus.QUEUED, ], # NOQA [x.status for x in Run.query], ) # now job-1 should get blocked and job-2's run will get popped # lets change the host-tag to ensure this does *all* runs w.host_tags = ["aarch97"] db.session.commit() resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code, resp.data) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data["data"]["worker"]["run-defs"])) self.assertEqual( [ BuildStatus.RUNNING, BuildStatus.RUNNING, BuildStatus.QUEUED, BuildStatus.RUNNING, ], # NOQA [x.status for x in Run.query], )
def test_worker_get_run(self, storage): if db.engine.dialect.name == 'sqlite': self.skipTest('Test requires MySQL') rundef = {'run_url': 'foo', 'runner_url': 'foo', 'env': {}} storage().get_run_definition.return_value = json.dumps(rundef) w = Worker('w1', 'ubuntu', 12, 2, 'aarch64', 'key', 2, ['aarch96']) w.enlisted = True w.online = True db.session.add(w) self.create_projects('job-1') p = Project.query.all()[0] b = Build.create(p) r = Run(b, 'run0') r.host_tag = 'aarch96' db.session.add(r) db.session.commit() headers = [ ('Content-type', 'application/json'), ('Authorization', 'Token key'), ] qs = 'available_runners=1&foo=2' resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code, resp.data) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data['data']['worker']['run-defs'])) # now put a tag on the worker that doesn't match r.status = BuildStatus.QUEUED w.host_tags = 'amd64, foo' db.session.commit() resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertNotIn('run-defs', data['data']['worker']) # now tag the run with the worker's host name r.host_tag = 'w1' w.host_tags = '' db.session.commit() resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data['data']['worker']['run-defs'])) # now do a pattern match w.host_tags = 'aarch96' r.host_tag = 'aa?c*' r.status = BuildStatus.QUEUED db.session.commit() resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data['data']['worker']['run-defs'])) # now mark it only for surges w.surges_only = True r.status = BuildStatus.QUEUED r.host_tag = 'aarch96' db.session.commit() resp = self.client.get('/workers/w1/', headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertNotIn('run-defs', data['data']['worker'])
def test_worker_get_run(self, storage): if db.engine.dialect.name == "sqlite": self.skipTest("Test requires MySQL") rundef = {"run_url": "foo", "runner_url": "foo", "env": {}} storage().get_run_definition.return_value = json.dumps(rundef) w = Worker("w1", "ubuntu", 12, 2, "aarch64", "key", 2, ["aarch96"]) w.enlisted = True w.online = True db.session.add(w) self.create_projects("job-1") p = Project.query.all()[0] b = Build.create(p) r = Run(b, "run0") r.host_tag = "aarch96" db.session.add(r) db.session.commit() headers = [ ("Content-type", "application/json"), ("Authorization", "Token key"), ] qs = "available_runners=1&foo=2" resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code, resp.data) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data["data"]["worker"]["run-defs"])) # now put a tag on the worker that doesn't match r.status = BuildStatus.QUEUED w.host_tags = "amd64, foo" db.session.commit() resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertNotIn("run-defs", data["data"]["worker"]) # now tag the run with the worker's host name r.host_tag = "w1" w.host_tags = "" db.session.commit() resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data["data"]["worker"]["run-defs"])) # now do a pattern match w.host_tags = "aarch96" r.host_tag = "aa?c*" r.status = BuildStatus.QUEUED db.session.commit() resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertEqual(1, len(data["data"]["worker"]["run-defs"])) # now mark it only for surges w.surges_only = True r.status = BuildStatus.QUEUED r.host_tag = "aarch96" db.session.commit() resp = self.client.get("/workers/w1/", headers=headers, query_string=qs) self.assertEqual(200, resp.status_code) data = json.loads(resp.data.decode()) self.assertNotIn("run-defs", data["data"]["worker"])