def handle_job_submission(self): try: yield except xmlrpc.client.ProtocolError as error: raise TemporarySubmissionIssue(self.url_remove_token(str(error))) except xmlrpc.client.Fault as fault: if fault.faultCode // 100 == 5: # assume HTTP errors 5xx are temporary issues raise TemporarySubmissionIssue(self.url_remove_token(str(fault))) else: raise SubmissionIssue(self.url_remove_token(str(fault))) except ssl.SSLError as fault: raise SubmissionIssue(self.url_remove_token(str(fault)))
def submit(self, test_job): try: job_id = self.__submit__(test_job.definition) test_job.name = self.__lava_job_name(test_job.definition) return job_id except xmlrpc.client.ProtocolError as error: raise TemporarySubmissionIssue(str(error)) except xmlrpc.client.Fault as fault: if fault.faultCode // 100 == 5: # assume HTTP errors 5xx are temporary issues raise TemporarySubmissionIssue(str(fault)) else: raise SubmissionIssue(str(fault)) except ssl.SSLError as fault: raise SubmissionIssue(str(fault))
def test_submit_fatal_error(self, submit_method): submit_method.side_effect = SubmissionIssue("ERROR") submit.apply(args=[self.test_job.id]) self.test_job.refresh_from_db() self.assertEqual(self.test_job.failure, "ERROR")
def handle_job_submission(self): try: yield except xmlrpc.client.ProtocolError as error: raise TemporarySubmissionIssue(self.url_remove_token(str(error))) except xmlrpc.client.Fault as fault: if fault.faultCode // 100 == 5 or fault.faultCode == 408: # assume HTTP errors 5xx are temporary issues # consider 408 as TemporarySubmissionIssue, as it's considered as timeout raise TemporarySubmissionIssue( self.url_remove_token(str(fault))) else: raise SubmissionIssue(self.url_remove_token(str(fault))) except ssl.SSLError as fault: raise SubmissionIssue(self.url_remove_token(str(fault))) except ConnectionRefusedError as fault: raise TemporarySubmissionIssue(str(fault))
class CiApiTest(TestCase): def setUp(self): self.group = core_models.Group.objects.create(slug='mygroup') self.usergroup = core_models.UserNamespace.objects.create( slug='~project-member-user') self.project = self.group.projects.create(slug='myproject') self.userproject = self.usergroup.projects.create(slug='userproject') self.project_admin_user = User.objects.create(username='******') self.group.add_admin(self.project_admin_user) self.project_submission_user = User.objects.create( username='******') self.group.add_user(self.project_submission_user, 'submitter') self.project_member_user = User.objects.create( username='******') self.group.add_user(self.project_member_user, 'member') self.usergroup.add_user(self.project_member_user, 'submitter') self.build = self.project.builds.create(version='1') self.userbuild = self.userproject.builds.create(version='1') Token.objects.create(user=self.project_submission_user, key='thekey') Token.objects.create(user=self.project_member_user, key='memberkey') Token.objects.create(user=self.project_admin_user, key='adminkey') self.backend = models.Backend.objects.create( name='lava', implementation_type='fake') self.client = APIClient('thekey') self.restclient = RestAPIClient('thekey') self.memberclient = APIClient('memberkey') self.adminclient = APIClient('adminkey') def test_auth(self): args = { 'backend': 'lava', 'definition': 'foo: 1', } self.client.token = 'invalid-token' r = self.client.post('/api/submitjob/mygroup/myproject/1/myenv', args) self.assertEqual(403, r.status_code) def test_creates_test_run(self): args = { 'backend': 'lava', 'definition': 'foo: 1', } r = self.client.post('/api/submitjob/mygroup/myproject/1/myenv', args) self.assertEqual(201, r.status_code) self.assertEqual( 1, models.TestJob.objects.filter( target=self.project, environment='myenv', target_build=self.build, backend=self.backend, definition='foo: 1', ).count()) def test_submitjob_private_group(self): args = { 'backend': 'lava', 'definition': 'foo: 1', } r = self.memberclient.post( '/api/submitjob/~project-member-user/userproject/1/myenv', args) self.assertEqual(201, r.status_code) self.assertEqual( 1, models.TestJob.objects.filter( target=self.userproject, environment='myenv', target_build=self.userbuild, backend=self.backend, definition='foo: 1', ).count()) def test_invalid_backend_test_run(self): args = { 'backend': 'lava.foo', 'definition': 'foo: 1', } r = self.client.post('/api/submitjob/mygroup/myproject/1/myenv', args) self.assertEqual(400, r.status_code) def test_missing_definition_test_run(self): args = {'backend': 'lava'} r = self.client.post('/api/submitjob/mygroup/myproject/1/myenv', args) self.assertEqual(400, r.status_code) def test_accepts_definition_as_file_upload(self): args = { 'backend': 'lava', 'definition': open(twoline_job_definition_file) } r = self.client.post('/api/submitjob/mygroup/myproject/1/myenv', args) self.assertEqual(201, r.status_code) testjob = models.TestJob.objects.filter( target=self.project, environment='myenv', target_build=self.build, backend=self.backend, definition='bar: something\nfoo: 1', ).get() # when parsing back to yaml, it weirdly adds an extra linebreak at the end self.assertEqual('bar: something\nfoo: 1\n', testjob.show_definition) @patch("squad.ci.tasks.submit.delay") def test_schedules_submission(self, submit): args = { 'backend': 'lava', 'definition': 'foo: 1', } self.client.post('/api/submitjob/mygroup/myproject/1/myenv', args) job_id = models.TestJob.objects.last().id submit.assert_called_with(job_id) @patch("squad.ci.tasks.fetch.delay") def test_auth_on_watch_testjob(self, fetch): testjob_id = 1234 args = { 'backend': 'lava', 'testjob_id': testjob_id, } self.client.token = 'invalid-token' r = self.client.post('/api/watchjob/mygroup/myproject/1/myenv', args) self.assertEqual(403, r.status_code) @patch("squad.ci.tasks.fetch.delay") def test_watch_testjob(self, fetch): testjob_id = 1234 args = { 'backend': 'lava', 'testjob_id': testjob_id, } r = self.client.post('/api/watchjob/mygroup/myproject/1/myenv', args) self.assertEqual(201, r.status_code) self.assertEqual( 1, models.TestJob.objects.filter(target=self.project, environment='myenv', target_build=self.build, backend=self.backend, submitted=True, job_id=testjob_id).count()) @patch("squad.ci.tasks.fetch.delay") def test_watch_testjob_private_group(self, fetch): testjob_id = 1234 args = { 'backend': 'lava', 'testjob_id': testjob_id, } r = self.memberclient.post( '/api/watchjob/~project-member-user/userproject/1/myenv', args) self.assertEqual(201, r.status_code) self.assertEqual( 1, models.TestJob.objects.filter(target=self.userproject, environment='myenv', target_build=self.userbuild, backend=self.backend, submitted=True, job_id=testjob_id).count()) @patch("squad.ci.tasks.fetch.delay") def test_watch_testjob_mising_id(self, fetch): args = {'backend': 'lava'} r = self.client.post('/api/watchjob/mygroup/myproject/1/myenv', args) self.assertEqual(400, r.status_code) @patch('squad.ci.models.Backend.get_implementation') def test_resubmit_submitter(self, get_implementation): impl = MagicMock() impl.resubmit = MagicMock() get_implementation.return_value = impl t = self.backend.test_jobs.create(target=self.project, can_resubmit=True) r = self.client.post('/api/resubmit/%s' % t.pk) self.assertEqual(201, r.status_code) impl.resubmit.assert_called() t.refresh_from_db() self.assertEqual(False, t.can_resubmit) @patch('squad.ci.models.Backend.get_implementation') def test_resubmit_submitter_cant_resubmit(self, get_implementation): impl = MagicMock() impl.resubmit = MagicMock() get_implementation.return_value = impl t = self.backend.test_jobs.create(target=self.project, can_resubmit=False) r = self.client.post('/api/resubmit/%s' % t.pk) self.assertEqual(403, r.status_code) impl.resubmit.assert_not_called() t.refresh_from_db() self.assertEqual(False, t.can_resubmit) @patch('squad.ci.models.Backend.get_implementation') def test_resubmit_submitter_token_auth(self, get_implementation): impl = MagicMock() impl.resubmit = MagicMock() get_implementation.return_value = impl t = self.backend.test_jobs.create(target=self.project, can_resubmit=True) r = self.restclient.post('/api/resubmit/%s' % t.pk) self.assertEqual(201, r.status_code) impl.resubmit.assert_called() t.refresh_from_db() self.assertEqual(False, t.can_resubmit) @patch('squad.ci.models.Backend.get_implementation') def test_resubmit_submitter_auth_token_cant_resubmit( self, get_implementation): impl = MagicMock() impl.resubmit = MagicMock() get_implementation.return_value = impl t = self.backend.test_jobs.create(target=self.project, can_resubmit=False) r = self.restclient.post('/api/resubmit/%s' % t.pk) self.assertEqual(403, r.status_code) impl.resubmit.assert_not_called() t.refresh_from_db() self.assertEqual(False, t.can_resubmit) @patch('squad.ci.models.Backend.get_implementation') def test_force_resubmit_submitter_token_auth(self, get_implementation): impl = MagicMock() impl.resubmit = MagicMock() get_implementation.return_value = impl t = self.backend.test_jobs.create(target=self.project, can_resubmit=True) r = self.restclient.post('/api/resubmit/%s' % t.pk) self.assertEqual(201, r.status_code) impl.resubmit.assert_called() t.refresh_from_db() self.assertEqual(False, t.can_resubmit) @patch('squad.ci.models.Backend.get_implementation') def test_resubmit_admin(self, get_implementation): impl = MagicMock() impl.resubmit = MagicMock() get_implementation.return_value = impl t = self.backend.test_jobs.create(target=self.project, can_resubmit=True) r = self.adminclient.post('/api/resubmit/%s' % t.pk) self.assertEqual(201, r.status_code) impl.resubmit.assert_called() t.refresh_from_db() self.assertEqual(False, t.can_resubmit) def test_disallowed_resubmit(self): t = self.backend.test_jobs.create(target=self.project, can_resubmit=True) r = self.memberclient.post('/api/resubmit/%s' % t.pk) self.assertEqual(401, r.status_code) def test_resubmit_invalid_id(self): staff_user_password = "******" staff_user = User.objects.create_superuser( username="******", email="*****@*****.**", password=staff_user_password, is_staff=True) staff_user.save() client = Client() client.login(username=staff_user.username, password=staff_user_password) r = client.post('/api/resubmit/999') self.assertEqual(404, r.status_code) @patch('squad.ci.models.TestJob.resubmit', side_effect=SubmissionIssue('BOOM')) def test_resubmit_error(self, resubmit): t = self.backend.test_jobs.create(target=self.project, can_resubmit=True) r = self.adminclient.post('/api/resubmit/%s' % t.pk) self.assertEqual(500, r.status_code) self.assertEqual('BOOM', r.content.decode())