Fix issue: T928
Fixed more lint issues.
Fix issue: T928
Fixed more lint issues.
Run Py.Test
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
at first glance, it looks good to me but I'll leave the review decision up to @mkrizek
Path | Packages | |||
---|---|---|---|---|
M | jobtriggers/cloud_compose_complete_msg.py (45 lines) | |||
M | testing/test_cloud_compose_trigger.py (37 lines) |
Commit | Tree | Parents | Author | Summary | Date |
---|---|---|---|---|---|
bf45575faada | a21ef499d9f0 | 6b16cb441fd2 | Mike Ruckman | Fixed more lint issues. | Mar 14 2017, 8:27 PM |
6b16cb441fd2 | 09155bf2bac3 | b04005a257b0 | Mike Ruckman | Update logic to parse compose metadata instead of having a hardcoded value. (Show More…) | Mar 14 2017, 8:10 PM |
1 | import fedmsg | 1 | import fedmsg | ||
---|---|---|---|---|---|
2 | import fedmsg.encoding | 2 | import fedmsg.encoding | ||
3 | import fedmsg.consumers | 3 | import fedmsg.consumers | ||
4 | 4 | | |||
5 | import json | ||||
6 | import requests | ||||
7 | | ||||
5 | from . import config | 8 | from . import config | ||
6 | from .jobtrigger import JobTrigger | 9 | from .jobtrigger import JobTrigger | ||
7 | from . import exceptions as exc | 10 | from . import exceptions as exc | ||
8 | 11 | | |||
9 | 12 | | |||
10 | def _pull_version_release(compose_id): | 13 | def _pull_version_release(compose_id): | ||
11 | """Splits out the relevant bits of the compose ID. Input requires the form | 14 | """Splits out the relevant bits of the compose ID. Input requires the form | ||
12 | "Fedora-TYPE-VERSION-Date.Serial" (ie, Fedora-Cloud-24-20170224.0) that fedmsg | 15 | "Fedora-TYPE-VERSION-Date.Serial" (ie, Fedora-Cloud-24-20170224.0) that fedmsg | ||
13 | spits out in compose_id.""" | 16 | spits out in compose_id.""" | ||
14 | 17 | | |||
15 | parts = compose_id.split('-') | 18 | parts = compose_id.split('-') | ||
16 | if len(parts) < 4: | 19 | if len(parts) < 4: | ||
17 | raise exc.TriggerMsgError("Provided compose_id did not contain" | 20 | raise exc.TriggerMsgError("Provided compose_id did not contain" | ||
18 | "all parts.") | 21 | "all parts.") | ||
19 | else: | 22 | else: | ||
20 | name = '-'.join(parts[:2]) | 23 | name = '-'.join(parts[:2]) | ||
21 | version = parts[1] | 24 | version = parts[1] | ||
22 | release = parts[2] | 25 | release = parts[2] | ||
23 | 26 | | |||
24 | return name, version, release | 27 | return name, version, release | ||
25 | 28 | | |||
26 | 29 | | |||
30 | def _fetch_metadata(compose_url): | ||||
31 | """This method simply isolates the one network call for the metadata out | ||||
32 | to make it easier to test the other logic. We'll presume that the 'requests' | ||||
33 | library does what it's supposed to. | ||||
34 | | ||||
35 | Input is the 'location' from fedmsg and it returns a json object from the | ||||
36 | metadata file.""" | ||||
37 | | ||||
38 | metadata_path = "/metadata/images.json" | ||||
39 | metadata = requests.get(compose_url + metadata_path) | ||||
40 | print metadata.status_code | ||||
41 | if metadata.status_code is not 200: | ||||
42 | raise exc.TriggerMsgError("Couldn't pull metadata from Koji.") | ||||
43 | | ||||
44 | metadata = json.loads(metadata.text) | ||||
45 | | ||||
46 | return metadata | ||||
47 | | ||||
48 | | ||||
49 | def _find_image(compose_url): | ||||
50 | """Parse out the images from the compose metadata to determine which test to | ||||
51 | to run. This does not include Rawhide composes, as those include more than | ||||
52 | one qcow2 image to test.""" | ||||
53 | | ||||
54 | metadata = _fetch_metadata(compose_url) | ||||
55 | | ||||
56 | x86_images = metadata['payload']['images']['CloudImages']['x86_64'] | ||||
57 | | ||||
58 | for image in x86_images: | ||||
59 | if image['format'] == 'qcow2': | ||||
60 | # Have to add the / here to make a valid URL because the compose in | ||||
61 | # the fedmsg doesn't have a trailing slash and the path in the | ||||
62 | # metadata doesn't have a leading slash. | ||||
63 | return compose_url + "/" + image['path'] | ||||
64 | | ||||
65 | | ||||
27 | def _process(msg): | 66 | def _process(msg): | ||
28 | """This method preps the incoming fedmsg data so the trigger can set | 67 | """This method preps the incoming fedmsg data so the trigger can set | ||
29 | off the task. Expects fedmsg.body data as input and returns a dict | 68 | off the task. Expects fedmsg.body data as input and returns a dict | ||
30 | for JobTrigger.do_trigger.""" | 69 | for JobTrigger.do_trigger.""" | ||
31 | 70 | | |||
32 | MESSAGE_TYPE = "CloudCompose" | 71 | MESSAGE_TYPE = "CloudCompose" | ||
33 | 72 | | |||
34 | if msg['msg']['status'] != "FINISHED": | 73 | if msg['msg']['status'] != "FINISHED": | ||
35 | raise exc.TriggerMsgError("Rejecting message because status not " | 74 | raise exc.TriggerMsgError("Rejecting message because status not " | ||
36 | "'FINISHED'.") | 75 | "'FINISHED'.") | ||
37 | 76 | | |||
38 | # Split this up to make the lines shorter | 77 | item = _find_image(msg['msg']['location']) | ||
39 | # FIXME: We shouldn't hard code these paths here | | |||
40 | item = ("{0}/CloudImages/x86_64/" | | |||
41 | "images/{1}.x86_64.qcow2").format(msg['msg']['location'], | | |||
42 | msg['msg']['compose_id']) | | |||
43 | 78 | | |||
44 | name, version, release = _pull_version_release(msg['msg']['compose_id']) | 79 | name, version, release = _pull_version_release(msg['msg']['compose_id']) | ||
45 | 80 | | |||
46 | if version == "Atomic": | 81 | if version == "Atomic": | ||
47 | MESSAGE_TYPE = "AtomicCompose" | 82 | MESSAGE_TYPE = "AtomicCompose" | ||
48 | 83 | | |||
49 | data = { | 84 | data = { | ||
50 | "_msg": msg, | 85 | "_msg": msg, | ||
Show All 34 Lines |
1 | import pytest | 1 | import pytest | ||
---|---|---|---|---|---|
2 | import json | 2 | import json | ||
3 | 3 | | |||
4 | # Only going to import the interesting bits | 4 | # Only going to import the interesting bits | ||
5 | from jobtriggers import cloud_compose_complete_msg | 5 | from jobtriggers import cloud_compose_complete_msg | ||
6 | from jobtriggers import exceptions as exc | 6 | from jobtriggers import exceptions as exc | ||
7 | 7 | | |||
8 | # Set up some dummy data to work with that's in various states of correct | 8 | # Set up some dummy data to work with that's in various states of correct | ||
9 | # These comprise just the interesting bits from the fedmsg that we want to | 9 | # These comprise just the interesting bits from the fedmsg that we want to | ||
10 | # consume with our trigger. | 10 | # consume with our trigger. | ||
11 | 11 | | |||
12 | location = "http://kojipkgs.fedoraproject.org/compose/Fedora-Cloud-24-20170224.0/compose" | | |||
13 | | ||||
14 | template_msg = ('{"msg": { "status": "FINISHED",' | 12 | template_msg = ('{"msg": { "status": "FINISHED",' | ||
15 | '"location":' | 13 | '"location":' | ||
16 | '"http://kojipkgs.fedoraproject.org/compose/Fedora-Cloud-24-20170224.0/compose",' | 14 | '"https://kojipkgs.fedoraproject.org/compose/Fedora-Cloud-25-20170313.0/compose",' | ||
17 | '"compose_id": ""}}') | 15 | '"compose_id": ""}}') | ||
18 | 16 | | |||
19 | msg_good = json.loads(template_msg) | 17 | msg_good = json.loads(template_msg) | ||
20 | msg_good['msg']['compose_id'] = "Fedora-Cloud-24-20170302.0" | 18 | msg_good['msg']['compose_id'] = "Fedora-Cloud-24-20170302.0" | ||
21 | 19 | | |||
22 | msg_bad_compose_id = json.loads(template_msg) | 20 | msg_bad_compose_id = json.loads(template_msg) | ||
23 | msg_bad_compose_id['msg']['compose_id'] = "Fedora-Cloud-23" | 21 | msg_bad_compose_id['msg']['compose_id'] = "Fedora-Cloud-23" | ||
24 | 22 | | |||
25 | msg_atomic = json.loads(template_msg) | 23 | msg_atomic = json.loads(template_msg) | ||
26 | msg_atomic['msg']['compose_id'] = "Fedora-Atomic-25-20170302.0" | 24 | msg_atomic['msg']['compose_id'] = "Fedora-Atomic-25-20170302.0" | ||
27 | 25 | | |||
28 | 26 | | |||
27 | @pytest.fixture(autouse=True) | ||||
28 | def _no_requests(monkeypatch): | ||||
29 | monkeypatch.setattr(cloud_compose_complete_msg, | ||||
30 | "_fetch_metadata", | ||||
31 | _fetch_metadata) | ||||
32 | | ||||
33 | | ||||
34 | @pytest.fixture(scope="module") | ||||
35 | def _fetch_metadata(compose_url): | ||||
36 | """This is a stub to provide mocked requests objects so we don't have | ||||
37 | to hit the network in our tests.""" | ||||
38 | | ||||
39 | # This is really ugly, but it's as sparse a dataset as we need to | ||||
40 | # complete the test. | ||||
41 | dummy_data = ('{"payload":' | ||||
42 | '{"images":' | ||||
43 | '{"CloudImages":' | ||||
44 | '{"x86_64": [' | ||||
45 | '{"format": "qcow2",' | ||||
46 | '"path": "/test/path/image.qcow2"' | ||||
47 | '}]' | ||||
48 | '}' | ||||
49 | '}' | ||||
50 | '}' | ||||
51 | '}') | ||||
52 | | ||||
53 | return json.loads(dummy_data) | ||||
54 | | ||||
55 | | ||||
29 | def test_process(): | 56 | def test_process(): | ||
30 | """Test that nothing fails with known good data.""" | 57 | """Test that nothing fails with known good data.""" | ||
58 | | ||||
31 | data = cloud_compose_complete_msg._process(msg_good) | 59 | data = cloud_compose_complete_msg._process(msg_good) | ||
32 | assert data['message_type'] == 'CloudCompose' | 60 | assert data['message_type'] == 'CloudCompose' | ||
33 | assert data['name'] == 'Fedora-Cloud' | 61 | assert data['name'] == 'Fedora-Cloud' | ||
34 | assert data['version'] == 'Cloud' | 62 | assert data['version'] == 'Cloud' | ||
35 | assert data['release'] == '24' | 63 | assert data['release'] == '24' | ||
36 | 64 | | |||
37 | 65 | | |||
38 | def test_process_atomic(): | 66 | def test_process_atomic(): | ||
39 | """Test that the detection of Atomic composes sets the correct | 67 | """Test that the detection of Atomic composes sets the correct | ||
40 | message_type, which would be "AtomicCompose".""" | 68 | message_type, which would be "AtomicCompose".""" | ||
41 | data = cloud_compose_complete_msg._process(msg_atomic) | | |||
42 | 69 | | |||
43 | print data | 70 | data = cloud_compose_complete_msg._process(msg_atomic) | ||
44 | 71 | | |||
45 | assert data['name'] == "Fedora-Atomic" | 72 | assert data['name'] == "Fedora-Atomic" | ||
46 | assert data['version'] == "Atomic" | 73 | assert data['version'] == "Atomic" | ||
47 | assert data['message_type'] == "AtomicCompose" | 74 | assert data['message_type'] == "AtomicCompose" | ||
48 | 75 | | |||
49 | 76 | | |||
50 | def test_pull_version_release(): | 77 | def test_pull_version_release(): | ||
51 | """Ensure that execution failes if the 'compose_id' is malformed.""" | 78 | """Ensure that execution failes if the 'compose_id' is malformed.""" | ||
52 | with pytest.raises(exc.TriggerMsgError): | 79 | with pytest.raises(exc.TriggerMsgError): | ||
53 | cloud_compose_complete_msg._process(msg_bad_compose_id) | 80 | cloud_compose_complete_msg._process(msg_bad_compose_id) |