diff --git a/roles/badges/backend/files/fedbadges_utils.py b/roles/badges/backend/files/fedbadges_utils.py new file mode 100644 index 0000000000..c80bcd2b75 --- /dev/null +++ b/roles/badges/backend/files/fedbadges_utils.py @@ -0,0 +1,154 @@ +""" Utilities for fedbadges that don't quite fit anywhere else. """ + +import types + +import logging +log = logging.getLogger("moksha.hub") + +import fedmsg +import fedora.client +import requests + +# These are here just so they're available in globals() +# for compiling lambda expressions +import json +import re +import fedmsg.config +import fedmsg.encoding +import fedmsg.meta + +# Imports for fasjson support +import os +import requests +import requests.exceptions +from gssapi import Credentials, exceptions +from requests_gssapi import HTTPSPNEGOAuth + + +def construct_substitutions(msg): + """ Convert a fedmsg message into a dict of substitutions. """ + subs = {} + for key1 in msg: + if isinstance(msg[key1], dict): + subs.update(dict([ + ('.'.join([key1, key2]), val2) + for key2, val2 in construct_substitutions(msg[key1]).items() + ])) + subs[key1] = msg[key1] + elif isinstance(msg[key1], basestring): + subs[key1] = msg[key1].lower() + else: + subs[key1] = msg[key1] + return subs + + +def format_args(obj, subs): + """ Recursively apply a substitutions dict to a given criteria subtree """ + + if isinstance(obj, dict): + for key in obj: + obj[key] = format_args(obj[key], subs) + elif isinstance(obj, list): + return [format_args(item, subs) for item in obj] + elif isinstance(obj, basestring) and obj[2:-2] in subs: + obj = subs[obj[2:-2]] + elif isinstance(obj, (int, float)): + pass + else: + obj = obj % subs + + return obj + + +def single_argument_lambda_factory(expression, argument, name='value'): + """ Compile and execute a lambda expression with a single argument """ + + code = compile("lambda %s: %s" % (name, expression), __file__, "eval") + func = types.LambdaType(code, globals())() + return func(argument) + + +def recursive_lambda_factory(obj, arg, name='value'): + """ Given a dict, find any lambdas, compile, and execute them. """ + + if isinstance(obj, dict): + for key in obj: + if key == 'lambda': + # If so, *replace* the parent dict with the result of the expr + obj = single_argument_lambda_factory(obj[key], arg, name) + break + else: + obj[key] = recursive_lambda_factory(obj[key], arg, name) + elif isinstance(obj, list): + return [recursive_lambda_factory(e, arg, name) for e in obj] + else: + pass + + return obj + + +def graceful(default_return_value): + """ A decorator that gracefully handles exceptions. """ + + def decorate(method): + def inner(self, *args, **kwargs): + try: + return method(self, *args, **kwargs) + except Exception as e: + log.exception(e) + log.error("From method: %r self: %r args: %r kwargs: %r" % ( + method, self, args, kwargs)) + return default_return_value + return inner + return decorate + + +def notification_callback(topic, msg): + """ This is a callback called by tahrir_api whenever something + it deems important has happened. + + It is just used to publish fedmsg messages. + """ + fedmsg.publish( + topic=topic, + msg=msg, + ) + + +def user_exists_in_fas(config, user): + """ Return true if the user exists in FAS. """ + if config.get("fasjson_base_url", False): + # fasjson_client not available in python2, so just use requests + os.environ["KRB5_CLIENT_KTNAME"] = config.get("keytab") + try: + creds = Credentials(usage="initiate") + except exceptions.GSSError as e: + log.error("GSSError trying to authenticate to fasjson", e) + gssapi_auth = HTTPSPNEGOAuth(opportunistic_auth=True, creds=creds) + session = requests.Session() + session.auth = gssapi_auth + return session.get(config['fasjson_base_url']+"users/"+user+"/").ok + else: + default_url = 'https://admin.fedoraproject.org/accounts/' + fas2 = fedora.client.AccountSystem( + base_url=config['fas_credentials'].get('base_url', default_url), + username=config['fas_credentials']['username'], + password=config['fas_credentials']['password'], + ) + return bool(fas2.person_by_username(user)) + +def get_pagure_authors(authors): + """ Extract the name of pagure authors from + a dictionary + + Args: + authors (list): A list of dict that contains fullname and name key. + """ + authors_name = [] + for item in authors: + if isinstance(item, dict): + try: + authors_name.append(item["name"]) + except KeyError: + raise Exception("Multiple recipients : name not found in the message") + return authors_name diff --git a/roles/badges/backend/tasks/main.yml b/roles/badges/backend/tasks/main.yml index 17f5810a4e..bdf4f0824a 100644 --- a/roles/badges/backend/tasks/main.yml +++ b/roles/badges/backend/tasks/main.yml @@ -229,3 +229,13 @@ tags: - badges - badges/backend + +# https://raw.githubusercontent.com/fedora-infra/fedbadges/fasjson/fedbadges/utils.py +- name: hotfix fedbadges with version from fasjson branch + copy: + src: fedbadges_utils.py + dest: /usr/lib/python2.7/site-packages/fedbadges/utils.py + when: env == "staging" + tags: + - badges + - badges/backend diff --git a/roles/badges/backend/templates/badges-awarder.py b/roles/badges/backend/templates/badges-awarder.py index cfe85e7c8d..2355f5ffba 100644 --- a/roles/badges/backend/templates/badges-awarder.py +++ b/roles/badges/backend/templates/badges-awarder.py @@ -35,16 +35,13 @@ config = { # The badges backend (fedmsg-hub) uses this to build a fas cache of ircnicks # to fas usernames so it can act appropriately on certain message types. "fas_credentials": { - {% if env == 'staging' %} - "base_url": "https://accounts.stg.fedoraproject.org/", - {% endif %} "username": "{{fedoraDummyUser}}", "password": "{{fedoraDummyUserPassword}}", }, {% if env == 'staging' %} - "fasjson_base_url": "https://fasjson.stg.fedoraproject.org/v1/" - "keytab": "/etc/krb5.badges-backend_badges-backend01.stg.iad2.fedoraproject.org.keytab" + "fasjson_base_url": "https://fasjson.stg.fedoraproject.org/v1/", + "keytab": "/etc/krb5.badges-backend_badges-backend01.stg.iad2.fedoraproject.org.keytab", {% endif %} diff --git a/roles/badges/backend/templates/datanommer.py b/roles/badges/backend/templates/datanommer.py index daf635a159..747b91f476 100644 --- a/roles/badges/backend/templates/datanommer.py +++ b/roles/badges/backend/templates/datanommer.py @@ -1,6 +1,6 @@ config = { {% if env == "staging" %} - 'datanommer.sqlalchemy.url': 'postgresql://{{datanommerDBUser}}:{{datanommerDBPassword}}@db-datanommer.stg.iad2.fedoraproject.org/datanommer2', + 'datanommer.sqlalchemy.url': 'postgresql://{{datanommerDBUser}}:{{datanommerDBPassword}}@db-datanommer01.stg.iad2.fedoraproject.org/datanommer2', {% else %} 'datanommer.sqlalchemy.url': 'postgresql://{{datanommerDBUser}}:{{datanommerDBPassword}}@db-datanommer/datanommer', {% endif %}