Drop all code handling autocloud test results

Autocloud was retired years ago, we don't need any of this any
more. Simplifies things quite a bit. Yay.

Signed-off-by: Adam Williamson <awilliam@redhat.com>
This commit is contained in:
Adam Williamson 2022-01-27 12:20:39 -08:00
commit d965a3725b
2 changed files with 18 additions and 257 deletions

View file

@ -21,7 +21,7 @@
"""Fedora nightly image finder."""
from collections import (OrderedDict, defaultdict)
from collections import OrderedDict
import datetime
import functools
import itertools
@ -38,9 +38,6 @@ import openqa_client.client
import openqa_client.exceptions
from openqa_client import const as oqc
from urllib.parse import urlencode
from urllib.request import Request
# HTML template
HTML_TEMPLATE = """
<!DOCTYPE html>
@ -92,33 +89,6 @@ def current_releases():
else:
return ['Rawhide']
def recursive_dict():
"""It's defaultdicts all the way down, Jim. Per
https://the.randomengineer.com/2015/04/28/python-recursive-defaultdict/
"""
return defaultdict(recursive_dict)
def datagrepper_query(topics, days):
"""Get messages on specified topics in the last X days."""
messages = []
secs = days * 24 * 60 * 60
page = 1
params = [('topic', topic) for topic in topics]
params.extend([('delta', secs), ('page', page)])
baseurl = 'https://apps.fedoraproject.org/datagrepper/raw'
nxt = True
while nxt:
url = '?'.join((baseurl, urlencode(params)))
headers = {'Content-type': 'application/json'}
req = Request(url, headers=headers)
resp = fedfind.helpers.download_json(req)
messages.extend(message['msg'] for message in resp['raw_messages'])
page += 1
params[-1] = ('page', page)
if resp['pages'] < page:
nxt = False
return messages
def get_cell(image):
"""Build a results table cell for an image. This is a bit complex
and looks pretty messy in-line in add_group, so it's split out
@ -136,18 +106,13 @@ def get_cell(image):
# cell to include the failed test links popups.
# First build the links div:
faillinks = ['Failed tests:']
if image['openqa']:
fails = [(str(job['id']), job['test']) for job in image['openqa']
if job['result'] not in (oqc.JOB_RESULT_PASSED, oqc.JOB_RESULT_SOFTFAILED)]
if fails:
faillinks.extend(
[Element('a', "openQA: {0} ({1})".format(jobid, jobtest),
href='https://openqa.fedoraproject.org/tests/{0}'.format(jobid))
for (jobid, jobtest) in fails])
elif image['autocloud']:
job = str(image['autocloud']['job_id'])
url = 'https://apps.fedoraproject.org/autocloud/jobs/{0}/output'.format(job)
faillinks.append(Element('a', "Autocloud: " + job, href=url))
fails = [(str(job['id']), job['test']) for job in image['openqa']
if job['result'] not in (oqc.JOB_RESULT_PASSED, oqc.JOB_RESULT_SOFTFAILED)]
if fails:
faillinks.extend(
[Element('a', "openQA: {0} ({1})".format(jobid, jobtest),
href='https://openqa.fedoraproject.org/tests/{0}'.format(jobid))
for (jobid, jobtest) in fails])
faillinksdiv = Element('div', faillinks, cssclass='faillinks')
# now wrap it and the image link in the cell div:
imglink = lnpart(cssclass='failedlink')
@ -281,7 +246,6 @@ class Image(dict):
# we always want these keys to exist, so set default values
# *BEFORE* super __init__
self['openqa'] = []
self['autocloud'] = []
super(Image, self).__init__(*args, **kwargs)
@property
@ -334,23 +298,11 @@ class Image(dict):
if any tests failed, True if all tests passed, None if we have
no test results.
"""
openqa = autocloud = None
res = None
if self.get('openqa'):
openqa = all(job['result'] in (oqc.JOB_RESULT_PASSED, oqc.JOB_RESULT_SOFTFAILED)
res = all(job['result'] in (oqc.JOB_RESULT_PASSED, oqc.JOB_RESULT_SOFTFAILED)
for job in self['openqa'])
if self.get('autocloud'):
autocloud = self['autocloud']['status'] == 'success'
# if any test type failed, 'False'
if any(tests is False for tests in (openqa, autocloud)):
return False
# else if any test type passed, 'True', because others must be
# 'True' or 'None'
if any(tests is True for tests in (openqa, autocloud)):
return True
# else None, because all must be 'None'
else:
return None
return res
def matches(self, other):
"""Check if this Image represents the same image as another
@ -492,13 +444,6 @@ class Nightlies(object):
composes.append(cid)
self.add_images(composes)
self.update_openqa(composes)
# autocloud: pull messages from datagrepper, since there is no
# API
topics = ('org.fedoraproject.prod.autocloud.image.success',
'org.fedoraproject.prod.autocloud.image.failed')
self.update_autocloud(datagrepper_query(topics, days))
self.write_data()
def add_images(self, composes):
@ -599,45 +544,6 @@ class Nightlies(object):
"flavor %s, arch %s, compose %s", flavor, arch, compose)
logger.info("openQA update done")
def update_autocloud(self, messages):
"""Update data based on Autocloud test results. As the API
still isn't available, we can only run on fedmsg output for
now, so we expect to be passed fedmsg message dicts.
"""
updated = set()
for message in messages:
imgurl = message.get('compose_url', message.get('image_url'))
filename = imgurl.split('/')[-1]
compose = message.get('compose_id')
logger.info("Processing Autocloud result for %s", filename)
matches = []
# find the image by filename and compose ID (for newer-style
# messages). If there isn't one and we haven't updated the
# built data for this compose, update it and try again.
while True:
matches = [image for image in self.data if
image['path'].split('/')[-1] == filename]
# we only get a compose ID for newer-style messages
if compose:
matches = [match for match in matches if match['compose'] == compose]
if matches or compose in updated:
break
else:
self.add_images([compose])
updated.add(compose)
# no match
if not matches:
logger.warning("update_autocloud: No Image found for %s", filename)
elif len(matches) > 1:
logger.warning("update_autocloud: More than one Image found for %s", filename)
else:
# AFAIK there's just one 'test event' per image in
# autocloud; whenever we get a message we can just call
# that the current autocloud 'status' for the image and
# stuff it in the image dict, overriding whatever was
# there before
matches[0]['autocloud'] = message
def find_latest(self, rel, group, arch):
"""Find 'last built' and 'last known good' for a specific
release, group and arch.
@ -703,8 +609,7 @@ class Nightlies(object):
class NightlyConsumer(object):
"""A fedora-messaging consumer that updates the data when a new
compose appears, when openQA testing for a compose completes, and
when autocloud testing for an image completes.
compose appears or when openQA testing for a compose completes.
"""
def __init__(self):
self.datafile = fedora_messaging.config.conf["consumer_config"].get("datafile")
@ -749,11 +654,6 @@ class NightlyConsumer(object):
self.log.info("Updating for openQA results of compose %s", compose)
# set the method to run
meth = functools.partial(nightlies.update_openqa, [compose])
else:
# autocloud image tests done
image = message.body.get('compose_url', message.body.get('image_url'))
self.log.info("Updating for Autocloud results of image %s", image)
meth = functools.partial(nightlies.update_autocloud, [message.body])
# do the update
meth()
nightlies.write_data()

View file

@ -29,80 +29,6 @@ import pytest
import fedora_nightlies
import openqa_client.const as oqc
# Fake PDC output; filtered down from real output for conciseness
# old autocloud format
PDC1 = {
"arguments": {
"page": 1,
"rows_per_page": 1,
"start": 1460847632.0,
"topics": [
"org.fedoraproject.prod.autocloud.image.failed",
"org.fedoraproject.prod.autocloud.image.success"
],
"users": []
},
"count": 1,
"pages": 2,
"raw_messages": [
{
"i": 644,
"msg": {
"buildid": 13696295,
"image_name": "Fedora-Cloud-Base-Vagrant-Libvirt",
"image_url": "https://kojipkgs.fedoraproject.org//work/tasks/6295/13696295/Fedora-Cloud-Base-Vagrant-Rawhide-20160418.n.0.x86_64.vagrant-libvirt.box",
"job_id": 1992,
"release": "Rawhide",
"status": "failed"
},
"msg_id": "2016-266296ba-a338-4429-9118-5a0d9d15a606",
"source_name": "datanommer",
"source_version": "0.6.5",
"timestamp": 1460966406.0,
"topic": "org.fedoraproject.prod.autocloud.image.failed"
}
],
"total": 2
}
# new autocloud format
PDC2 = {
"arguments": {
"page": 2,
"rows_per_page": 1,
"start": 1460847632.0,
"topics": [
"org.fedoraproject.prod.autocloud.image.failed",
"org.fedoraproject.prod.autocloud.image.success"
],
"users": []
},
"count": 1,
"pages": 2,
"raw_messages": [
{
"i": 260,
"msg": {
"compose_id": "Fedora-Atomic-24-20160712.0",
"compose_url": "http://kojipkgs.fedoraproject.org/compose//twoweek/Fedora-Atomic-24-20160712.0/compose/CloudImages/x86_64/images/Fedora-Cloud-Base-Vagrant-24-20160712.0.x86_64.vagrant-libvirt.box",
"family": "Base",
"image_name": "Fedora-Cloud-Base-Vagrant-24-20160712.0",
"job_id": 193,
"release": "atomic",
"status": "success",
"type": "vagrant-libvirt"
},
"msg_id": "2016-ea3e5ed2-923d-44a9-8402-716c6d168d4c",
"source_name": "datanommer",
"source_version": "0.6.5",
"timestamp": 1468345355.0,
"topic": "org.fedoraproject.prod.autocloud.image.success"
}
],
"total": 2
}
def _fake_get_current(branched=False):
"""Fake fedfind.helpers.get_current_release for case when there is
a Branched. Return 24 if branched is true, otherwise 23.
@ -111,26 +37,6 @@ def _fake_get_current(branched=False):
return 24
return 23
def _fake_download_json(request):
"""Fake fedfind.helpers.download_json. Returns two pages of fake
PDC-ish output. Checks the URL contains correct params for the
test.
"""
# first position arg to the Request mock is URL
url = request.get_full_url()
if 'delta=604800' not in url:
raise ValueError("Invalid delta! URL: {0}".format(url))
if not all('topic=org.fedoraproject.prod.autocloud.image.{0}'.format(topic) in url
for topic in ['failed', 'success']):
raise ValueError("Missing topic(s)! URL: {0}".format(url))
if 'page=1' in url:
return PDC1
elif 'page=2' in url:
return PDC2
else:
# make sure we never get here
raise ValueError("Invalid page!")
class FakeElement(object):
"""Mock 'Element' class which just stores the args it was called
@ -162,34 +68,6 @@ def test_current_releases_no_branched(fakecurr):
fedora_nightlies.CURRENT_RELEASES = []
assert fedora_nightlies.current_releases() == ['Rawhide']
def test_recursive_dict():
"""This should behave like, well, a recursive dict. So check
setting a value in a dict some crazy number of levels down,
and check that an instance several levels down is still a
collections.defaultdict.
"""
recdict = fedora_nightlies.recursive_dict()
recdict[1][2][3][4][5][6][7][8] = "boy, it's dark down here"
assert recdict[1][2][3][4][5][6][7][8] == "boy, it's dark down here"
assert isinstance(recdict['foo']['bar'], collections.defaultdict)
@mock.patch('fedfind.helpers.download_json', _fake_download_json)
def test_datagrepper_query():
"""datagrepper_query should get the multi-page data correctly
and return the list of actual fedmsgs (it throws away the rest
of the data, for now at least; if that changes, this test will
need changing too). Note, some checking is done in _fake_download
_json here (I couldn't figure a way to mock the Request that's
passed to download_json such that we can check its properties
here).
"""
topics = ["org.fedoraproject.prod.autocloud.image.failed",
"org.fedoraproject.prod.autocloud.image.success"]
ret = fedora_nightlies.datagrepper_query(topics, 7)
assert len(ret) == 2
assert ret[0]['job_id'] == 1992
assert ret[1]['job_id'] == 193
# we're not testing the behaviour of Element here, so use FakeElement
@mock.patch('fedora_nightlies.Element', FakeElement)
def test_get_cell_pass():
@ -202,7 +80,7 @@ def test_get_cell_pass():
compose = "Fedora-Rawhide-20160418.n.0"
url = "https://kojipkgs.fedoraproject.org/compose/rawhide/Fedora-Rawhide-20160418.n.0/compose/CloudImages/x86_64/images/Fedora-Cloud-Base-Rawhide-20160418.n.0.x86_64.qcow2"
image = fedora_nightlies.Image({
'autocloud': {'status': "success"},
'openqa': [{'result': "passed"}],
'compose': compose,
'url': url
})
@ -376,42 +254,25 @@ def test_image():
assert img.release == "29"
# newly-instantiated image must always have these attributes
assert img['openqa'] == []
assert img['autocloud'] == []
assert img.group == "AtomicHost dvd-ostree"
assert img.openqa_flavor == "AtomicHost-dvd_ostree-iso"
# test passed/failed/None test combinations work correctly
# None
assert img.testspass is None
# test various passed/failed test combinations work correctly
# ac pass oq none
img['autocloud'] = {'status': "success"}
assert img.testspass is True
# ac pass oq pass
# Pass
img['openqa'] = [{'result': oqc.JOB_RESULT_PASSED}]
assert img.testspass is True
# ac pass oq fail
# Fail
img['openqa'] = [{'result': oqc.JOB_RESULT_FAILED}]
assert img.testspass is False
# ac fail oq fail
img['autocloud'] = {'status': "failed"}
assert img.testspass is False
# ac fail oq pass
img['openqa'] = [{'result': oqc.JOB_RESULT_PASSED}]
assert img.testspass is False
# ac fail oq none
img['openqa'] = []
assert img.testspass is False
# ac none oq pass
img['autocloud'] = []
img['openqa'] = [{'result': oqc.JOB_RESULT_PASSED}]
assert img.testspass is True
# ac none oq softfail
# Softfail
img['openqa'] = [{'result': oqc.JOB_RESULT_SOFTFAILED}]
assert img.testspass is True
# clone image to test matches
img2 = fedora_nightlies.Image(img)
img2['openqa'] = []
img2['autocloud'] = {'status': "failed"}
# same image with different test results should match
assert img.matches(img2)