Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add a pkgdb criteria checker.

  • Loading branch information...
commit c84fb8c76b40e8a122e040e43415c2cc554820bd 1 parent 6e857bb
@ralphbean ralphbean authored
View
53 fedbadges/rules.py
@@ -21,11 +21,15 @@
import datanommer.models
from fedbadges.utils import (
+ # These are all in-process utilities
construct_substitutions,
format_args,
single_argument_lambda_factory,
recursive_lambda_factory,
graceful,
+
+ # This makes a network API call
+ get_pkgdb_packages_for,
)
import logging
@@ -288,6 +292,7 @@ def matches(self, msg):
class Criteria(AbstractTopLevelComparator):
possible = set([
'datanommer',
+ 'pkgdb',
]).union(operators)
def __init__(self, *args, **kwargs):
@@ -300,6 +305,8 @@ def __init__(self, *args, **kwargs):
def _specialize(self):
if self.attribute == 'datanommer':
self.specialization = DatanommerCriteria(self.expected_value)
+ elif self.attribute == 'pkgdb':
+ self.specialization = PkgdbCriteria(self.expected_value)
# TODO -- expand this with other "backends" as necessary
#elif self.attribute == 'fas'
else:
@@ -319,6 +326,52 @@ class AbstractSpecializedComparator(AbstractComparator):
pass
+class PkgdbCriteria(AbstractSpecializedComparator):
+ required = possible = set([
+ 'owns',
+ ])
+
+ def __init__(self, *args, **kwargs):
+ super(PkgdbCriteria, self).__init__(*args, **kwargs)
+
+ # Validate the owns dict
+ if not isinstance(self._d['owns'], dict):
+ raise ValueError("'owns' must be a dict")
+
+ owns_fields = set(['user', 'packages'])
+ argued_fields = set(self._d['owns'].keys())
+
+ if not argued_fields.issubset(owns_fields):
+ raise KeyError(
+ "%r are not possible fields. Choose from %r" % (
+ argued_fields.difference(owns_fields),
+ owns_fields,
+ ))
+
+ if not owns_fields.issubset(argued_fields):
+ raise KeyError(
+ "%r are missing required fields." % (
+ owns_fields.difference(argued_fields),
+ ))
+
+ if not isinstance(self._d['owns']['packages'], list):
+ raise ValueError("'packages' must be a list")
+
+ def matches(self, msg):
+ """ A pkgdb criteria check checks if a user owns some packages. """
+
+ subs = construct_substitutions(msg)
+ expectation = format_args(copy.copy(self._d['owns']), subs)
+ expectation = recursive_lambda_factory(expectation, msg, name='msg')
+
+ actual_packages = get_pkgdb_packages_for(
+ config=fedmsg_config,
+ user=expectation['user'],
+ )
+
+ return set(expectation['packages']).issubset(actual_packages)
+
+
class DatanommerCriteria(AbstractSpecializedComparator):
required = possible = set([
'filter',
View
62 fedbadges/utils.py
@@ -1,15 +1,21 @@
""" Utilities for fedbadges that don't quite fit anywhere else. """
+import json
import types
import logging
log = logging.getLogger("moksha.hub")
import fedmsg
+import requests
+
+# This is used for our queries against pkgdb
+from dogpile.cache import make_region
+_cache = make_region()
+
# These are here just so they're available in globals()
# for compiling lambda expressions
-import json
import re
import fedmsg.config
import fedmsg.encoding
@@ -109,3 +115,57 @@ def notification_callback(topic, msg):
topic=topic,
msg=msg,
)
+
+
+def get_pkgdb_packages_for(config, username):
+ """ Retrieve the list of packages where the specified user some acl.
+
+ :arg config: a dict containing the fedmsg config
+ :arg username: the fas username of the packager whose packages are of
+ interest.
+ :return: a set listing all the packages where the specified user has
+ some ACL.
+
+ """
+
+ if not hasattr(_cache, 'backend'):
+ _cache.configure(**config['fedbadges.rules.cache'])
+
+ @_cache.cache_on_arguments()
+ def _getter(username):
+ if config.get('fedbadges.rules.utils.use_pkgdb2', True):
+ return _get_pkgdb2_packages_for(config, username)
+ else:
+ return _get_pkgdb1_packages_for(config, username)
+
+ return _getter(username)
+
+
+def _get_pkgdb2_packages_for(config, username):
+ log.debug("Requesting pkgdb2 packages for user %r" % username)
+ req = requests.get('{0}/packager/acl/{1}'.format(
+ config['fedbadges.rules.utils.pkgdb2_api_url'], username))
+ if not req.status_code == 200:
+ return set()
+ data = json.loads(req.text)
+ packages = set()
+ for pkgacl in data['acls']:
+ if pkgacl['status'] != 'Approved':
+ continue
+ packages.add(pkgacl['packagelist']['package']['name'])
+ log.debug("done talking with pkgdb2 for now.")
+ return packages
+
+
+# TODO -- delete this once pkgdb2 goes live.
+def _get_pkgdb1_packages_for(config, username):
+ log.debug("Requesting pkgdb1 packages for user %r" % username)
+ pkgdb1_base_url = 'https://admin.fedoraproject.org/pkgdb'
+ req = requests.get('{0}/users/packages/{1}?tg_format=json'.format(
+ pkgdb1_base_url, username))
+ if not req.status_code == 200:
+ return set()
+ data = json.loads(req.text)
+ packages = set([pkg['name'] for pkg in data['pkgs']])
+ log.debug("done talking with pkgdb1 for now.")
+ return packages
View
11 fedmsg.d/badges-global.py
@@ -28,4 +28,15 @@
issuer_contact='badges@fedoraproject.org',
),
},
+
+ # Some configuration for the pkgdb criteria handler
+ "fedbadges.rules.utils.use_pkgdb2": False,
+ "fedbadges.rules.utils.pkgdb2_api_url": "http://209.132.184.188/api/",
+ "fedbadges.rules.cache": {
+ "backend": "dogpile.cache.dbm",
+ "expiration_time": 300,
+ "arguments": {
+ "filename": "/var/tmp/fedbadges-cache.dbm",
+ },
+ },
}
View
2  requirements.txt
@@ -4,3 +4,5 @@ fedmsg_meta_fedora_infrastructure
PyYAML
datanommer.models
zope.sqlalchemy
+requests
+dogpile.cache
Please sign in to comment.
Something went wrong with that request. Please try again.