Merge ~pwlars/testflinger-agent:fix-empty-sections-exception into testflinger-agent:master

Proposed by Paul Larson
Status: Merged
Approved by: Paul Larson
Approved revision: eaf55c25242a8e5c49008576f676adc3b212d609
Merged at revision: 7eb7331bbc6b4b16c38ecb38c1a9cdf406f1c934
Proposed branch: ~pwlars/testflinger-agent:fix-empty-sections-exception
Merge into: testflinger-agent:master
Diff against target: 99 lines (+24/-10)
3 files modified
testflinger_agent/job.py (+3/-3)
testflinger_agent/tests/test_agent.py (+7/-7)
testflinger_agent/tests/test_job.py (+14/-0)
Reviewer Review Type Date Requested Status
Sheila Miguez (community) Approve
Review via email: mp+414824@code.launchpad.net

Description of the change

We already support the idea of skipping a section if it's missing (ex. if you want to skip provision, simply leave out the provisioning section). however I also noticed today that if you leave out the data in the provisioning section, it gives you a pretty confusing error.

Now, if it's present but doesn't have anything in it, it should result in the same sort of non-fatal message that happens when the section is missing completely. However it will still try to do the other parts of the job that it can.

To post a comment you must log in.
Revision history for this message
Sheila Miguez (codersquid) wrote :

lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/testflinger_agent/job.py b/testflinger_agent/job.py
index b76dfdc..b717d32 100644
--- a/testflinger_agent/job.py
+++ b/testflinger_agent/job.py
@@ -55,13 +55,13 @@ class TestflingerJob:
55 if not cmd:55 if not cmd:
56 logger.info('No %s_command configured, skipping...', phase)56 logger.info('No %s_command configured, skipping...', phase)
57 return 057 return 0
58 if phase == 'provision' and 'provision_data' not in self.job_data:58 if phase == 'provision' and not self.job_data.get('provision_data'):
59 logger.info('No provision_data defined in job data, skipping...')59 logger.info('No provision_data defined in job data, skipping...')
60 return 060 return 0
61 if phase == 'test' and 'test_data' not in self.job_data:61 if phase == 'test' and not self.job_data.get('test_data'):
62 logger.info('No test_data defined in job data, skipping...')62 logger.info('No test_data defined in job data, skipping...')
63 return 063 return 0
64 if phase == 'reserve' and 'reserve_data' not in self.job_data:64 if phase == 'reserve' and not self.job_data.get('reserve_data'):
65 return 065 return 0
66 output_log = os.path.join(rundir, phase+'.log')66 output_log = os.path.join(rundir, phase+'.log')
67 serial_log = os.path.join(rundir, phase+'-serial.log')67 serial_log = os.path.join(rundir, phase+'-serial.log')
diff --git a/testflinger_agent/tests/test_agent.py b/testflinger_agent/tests/test_agent.py
index 496dbe3..e9ce10c 100644
--- a/testflinger_agent/tests/test_agent.py
+++ b/testflinger_agent/tests/test_agent.py
@@ -52,7 +52,7 @@ class TestClient:
52 self.config['provision_command'] = 'echo provision1'52 self.config['provision_command'] = 'echo provision1'
53 fake_job_data = {'job_id': str(uuid.uuid1()),53 fake_job_data = {'job_id': str(uuid.uuid1()),
54 'job_queue': 'test',54 'job_queue': 'test',
55 'provision_data': ''}55 'provision_data': {'url': 'foo'}}
56 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},56 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},
57 {'text': '{}'}])57 {'text': '{}'}])
58 requests_mock.post(rmock.ANY, status_code=200)58 requests_mock.post(rmock.ANY, status_code=200)
@@ -67,7 +67,7 @@ class TestClient:
67 self.config['test_command'] = 'echo test1'67 self.config['test_command'] = 'echo test1'
68 fake_job_data = {'job_id': str(uuid.uuid1()),68 fake_job_data = {'job_id': str(uuid.uuid1()),
69 'job_queue': 'test',69 'job_queue': 'test',
70 'test_data': ''}70 'test_data': {'test_cmds': 'foo'}}
71 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},71 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},
72 {'text': '{}'}])72 {'text': '{}'}])
73 requests_mock.post(rmock.ANY, status_code=200)73 requests_mock.post(rmock.ANY, status_code=200)
@@ -82,7 +82,7 @@ class TestClient:
82 self.config['test_command'] = 'echo test_string is $test_string'82 self.config['test_command'] = 'echo test_string is $test_string'
83 fake_job_data = {'job_id': str(uuid.uuid1()),83 fake_job_data = {'job_id': str(uuid.uuid1()),
84 'job_queue': 'test',84 'job_queue': 'test',
85 'test_data': ''}85 'test_data': {'test_cmds': 'foo'}}
86 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},86 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},
87 {'text': '{}'}])87 {'text': '{}'}])
88 requests_mock.post(rmock.ANY, status_code=200)88 requests_mock.post(rmock.ANY, status_code=200)
@@ -99,8 +99,8 @@ class TestClient:
99 self.config['test_command'] = 'echo test1'99 self.config['test_command'] = 'echo test1'
100 fake_job_data = {'job_id': str(uuid.uuid1()),100 fake_job_data = {'job_id': str(uuid.uuid1()),
101 'job_queue': 'test',101 'job_queue': 'test',
102 'provision_data': '',102 'provision_data': {'url': 'foo'},
103 'test_data': ''}103 'test_data': {'test_cmds': 'foo'}}
104 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},104 requests_mock.get(rmock.ANY, [{'text': json.dumps(fake_job_data)},
105 {'text': '{}'}])105 {'text': '{}'}])
106 requests_mock.post(rmock.ANY, status_code=200)106 requests_mock.post(rmock.ANY, status_code=200)
@@ -153,8 +153,8 @@ class TestClient:
153 job_id = str(uuid.uuid1())153 job_id = str(uuid.uuid1())
154 fake_job_data = {'job_id': job_id,154 fake_job_data = {'job_id': job_id,
155 'job_queue': 'test',155 'job_queue': 'test',
156 'provision_data': '',156 'provision_data': {'url': 'foo'},
157 'test_data': ''}157 'test_data': {'test_cmds': 'foo'}}
158 # In this case we are making sure that the repost job request158 # In this case we are making sure that the repost job request
159 # gets good status159 # gets good status
160 with rmock.Mocker() as m:160 with rmock.Mocker() as m:
diff --git a/testflinger_agent/tests/test_job.py b/testflinger_agent/tests/test_job.py
index 481e7b4..bb70c22 100644
--- a/testflinger_agent/tests/test_job.py
+++ b/testflinger_agent/tests/test_job.py
@@ -38,6 +38,20 @@ class TestJob():
38 log_output = log.read()38 log_output = log.read()
39 assert("No provision_data defined in job data" in log_output)39 assert("No provision_data defined in job data" in log_output)
4040
41 def test_skip_empty_provision_data(self, client):
42 """
43 Test that provision phase is skipped when provision_data is
44 present but empty
45 """
46 self.config['provision_command'] = '/bin/true'
47 fake_job_data = {'global_timeout': 1, 'provision_data': ''}
48 job = _TestflingerJob(fake_job_data, client)
49 job.run_test_phase('provision', None)
50 logfile = os.path.join(self.tmpdir, 'testflinger-agent.log')
51 with open(logfile) as log:
52 log_output = log.read()
53 assert("No provision_data defined in job data" in log_output)
54
41 def test_job_global_timeout(self, client, requests_mock):55 def test_job_global_timeout(self, client, requests_mock):
42 """Test that timeout from job_data is respected"""56 """Test that timeout from job_data is respected"""
43 timeout_str = '\nERROR: Global timeout reached! (1s)\n'57 timeout_str = '\nERROR: Global timeout reached! (1s)\n'

Subscribers

People subscribed via source and target branches