Add greenwave query to done handler

Signed-off-by: Valerij Maljulin <vmaljuli@redhat.com>
This commit is contained in:
Valerij Maljulin
2019-05-09 18:42:25 +02:00
parent 4b5618f079
commit 95bacc4e15
4 changed files with 258 additions and 43 deletions

View File

@@ -24,6 +24,7 @@
import requests
import json
from functools import reduce
from module_build_service import log, conf
from module_build_service.errors import GreenwaveError
@@ -34,14 +35,63 @@ class Greenwave(object):
Initialize greenwave instance with config
"""
self.url = conf.greenwave_url
if not self.url:
raise GreenwaveError("No Greenwave URL set")
self._decision_context = conf.greenwave_decision_context
if not self.decision_context:
raise GreenwaveError("No Greenwave decision context set")
self._subj_type = conf.greenwave_subject_type
self._gw_timeout = conf.greenwave_timeout
def _greenwave_query(self, query_type, payload=None):
"""
Make a query to greenwave
:param query_type: will be part of url
:type query_type: str
:param payload: request payload used in 'decision' query
:type payload: str
:return: response
:rtype: dict
"""
query_func = requests.post if payload else requests.get
kwargs = {"url": "{0}/{1}".format(self.url, query_type), "timeout": self.timeout}
if payload:
kwargs["headers"] = {"Content-Type": "application/json"}
kwargs["data"] = payload
try:
response = query_func(**kwargs)
except requests.exceptions.Timeout:
raise GreenwaveError("Greenwave request timed out")
except Exception as exc:
error_message = "Unspecified greenwave request error" \
'(original exception was: "{0}")'.format(str(exc))
log.exception(error_message)
raise GreenwaveError(error_message)
try:
resp_json = response.json()
except ValueError:
log.debug("Greenwave response content (status {0}): {1}".format(
response.status_code, response.text
))
raise GreenwaveError("Greenwave returned invalid JSON.")
log.debug(
'Query to Greenwave (%s) result: status=%d, content="%s"',
(kwargs["url"], response.status_code, resp_json)
)
if response.status_code == 200:
return resp_json
try:
err_msg = resp_json["message"]
except KeyError:
err_msg = response.text
raise GreenwaveError("Greenwave returned {0} status code. Message: {1}".format(
response.status_code, err_msg
))
def query_decision(self, build, prod_version):
"""
Query decision to greenwave
@@ -58,36 +108,69 @@ class Greenwave(object):
"subject_type": self.subject_type,
"subject_identifier": build.nvr_string
}
url = "{0}/decision".format(self.url)
headers = {"Content-Type": "application/json"}
try:
response = requests.post(
url=url, headers=headers, data=json.dumps(payload), timeout=self.timeout)
except requests.exceptions.Timeout:
raise GreenwaveError("Greenwave request timed out")
except Exception as exc:
log.exception(str(exc))
raise GreenwaveError("Greenwave request error")
return self._greenwave_query('decision', json.dumps(payload))
def query_policies(self, return_all=False):
"""
Query policies to greenwave
:param return_all: Return all policies, if False select by subject_type and decision_context
:type return_all: bool
:return: response
:rtype: dict
"""
response = self._greenwave_query('policies')
if return_all:
return response
try:
resp_json = response.json()
except ValueError:
log.debug("Greenwave response content (status {0}): {1}".format(
response.status_code, response.text))
raise GreenwaveError("Greenwave returned invalid JSON.")
log.debug('Query to Greenwave result: status=%d, content="%s"',
(response.status_code, resp_json))
if response.status_code == 200:
return resp_json
try:
err_msg = resp_json["message"]
selective_resp = {
"policies": [
pol for pol in response["policies"]
if pol["decision_context"] == self.decision_context
and pol["subject_type"] == self.subject_type
]
}
except KeyError:
err_msg = response.text
raise GreenwaveError("Greenwave returned {0} status code. Message: {1}".format(
response.status_code, err_msg))
log.exception("Incorrect greenwave response (Mandatory key is missing)")
raise GreenwaveError("Incorrect greenwave response (Mandatory key is missing)")
return selective_resp
def get_product_versions(self):
"""
Return a set of product versions according to decision_context and subject_type
:return: product versions
:rtype: set
"""
return reduce(
lambda old, new: old.union(new),
[pol["product_versions"] for pol in self.query_policies()["policies"]],
set()
)
def check_gating(self, build):
"""
Query decision to greenwave
:param build: build object
:type build: module_build_service.models.ModuleBuild
:return: True if at least one GW response contains policies_satisfied set to true
:rtype: bool
"""
try:
versions = self.get_product_versions()
except GreenwaveError:
log.warning('An error occured while getting a product versions')
return False
for ver in versions:
try:
if self.query_decision(build, ver)["policies_satisfied"]:
# at least one positive result is enough
return True
except (KeyError, GreenwaveError) as exc:
log.warning('Incorrect greenwave result "%s", ignoring', str(exc))
return False
@property
def url(self):
@@ -96,8 +179,9 @@ class Greenwave(object):
@url.setter
def url(self, value):
value = value.rstrip("/")
if value:
self._url = value
if not value:
raise GreenwaveError("No Greenwave URL set")
self._url = value
@property
def decision_context(self):
@@ -114,3 +198,10 @@ class Greenwave(object):
@timeout.setter
def timeout(self, value):
self._gw_timeout = value
try:
greenwave = Greenwave()
except GreenwaveError:
log.warning('Greenwave is not configured or configured improperly')
greenwave = None