def fedmsg_publish(*args, **kwargs): # pragma: no cover """ Try to publish a message on the fedmsg bus. """ if config.config["LEGACY_MESSAGING"]: # We catch Exception if we want :-p # pylint: disable=W0703 # Ignore message about fedmsg import # pylint: disable=F0401 kwargs["modname"] = "anitya" kwargs["cert_prefix"] = "anitya" kwargs["name"] = "relay_inbound" kwargs["active"] = True try: import fedmsg fedmsg.publish(*args, **kwargs) except Exception as err: _log.error(str(err)) else: try: message_class = message.get_class("anitya." + kwargs["topic"]) api.publish( message_class( topic="anitya.{}".format(kwargs["topic"]), body=kwargs["msg"] ) ) except ( fm_exceptions.ConnectionException, fm_exceptions.PublishException, ) as err: # For now, continue just logging the error. Once the messaging has # been untangled into SQLAlchemy events, it should probably result # in an exception and the client should try again later. _log.error(str(err))
def _log_message(kw, message): if kw["json_input"]: msg = fedmsg.encoding.loads(message) else: msg = {"log": message} fedmsg.publish(topic=kw["topic"], msg=msg, modname=kw["modname"])
def set_usage(session, pkgname, user, usage): """ Set the usage marker for a specified package. """ package = model.Package.by_name(session, pkgname) try: # Try to change an existing usage first. usageobj = model.Usage.get(session, package_id=package.id, user_id=user.id) if usage: return 'You already do not use %s' % pkgname session.delete(usageobj) message = 'You no longer use %s' % pkgname usage = False except NoResultFound: # If no usage was found, we need to add a new one. if not usage: return 'You already use %s' % pkgname usageobj = model.Usage(package_id=package.id, user_id=user.id) session.add(usageobj) message = 'Marked that you use %s' % pkgname session.add(usageobj) usage = True session.flush() fedmsg.publish('usage.toggle', msg=dict( user=user.__json__(session), package=package.__json__(session), usage=usage, )) return message
def add_tag(session, pkgname, tag, user): """ Add a provided tag to the specified package. """ tag = tag.lower() package = model.Package.by_name(session, pkgname) try: tagobj = model.Tag.get(session, package.id, tag) tagobj.like += 1 user.score += 1 except NoResultFound: # If no such tag exists, create a new one. But first.. if blacklisted(tag): raise ValueError("'%s' is not allowed." % tag) tagobj = model.Tag(package_id=package.id, label=tag) session.add(tagobj) session.flush() user.score += 2 voteobj = model.Vote(user_id=user.id, tag_id=tagobj.id, like=True) session.add(user) session.add(voteobj) session.flush() fedmsg.publish('tag.create', msg=dict( tag=tagobj, vote=voteobj, user=user, )) return 'Tag "%s" added to the package "%s"' % (tag, pkgname)
def webhook(provided_secret): # First, verify that the hashed url sent to us is the one that we provided # to zanata in the first place. salt = app.config['WEBHOOK_SALT'] payload = json.loads(flask.request.body) name = payload['project'] valid_secret = hmac.new(salt, name, hashlib.sha256).hexdigest() if provided_secret != valid_secret: error = "%s is not valid for %s" % (provided_secret, name) return error, 403 # XXX - Note that the validation mechanism we used above is not really # secure. An attacker could eavesdrop on the request and get the url and # then perform a replay attack (since the provided_secret will be the same # every time for each project). It would be better to use a shared salt # and then sign each message uniquely, but we'll have to wait until zanata # supports something like that. This will do in the mean time. # See https://bugzilla.redhat.com/show_bug.cgi?id=1213630 # Having verified the message, we're all set. Republish it on our bus. topic = camel2dot(payload['eventType'].split('.')[-1]) fedmsg.publish( modname='zanata', topic=topic, msg=payload, ) return "Everything is 200 OK"
def event(self, topic, template, content=None): """ Multi-purpose logging method. Logs messages to three different destinations: - To log file - The internal "events" queue for communicating back to the dispatcher. - The fedmsg bus. Messages are posted asynchronously to a zmq.PUB socket. """ content = content or {} what = template.format(**content) who = "worker-{0}".format(self.worker_num) self.callback.log("event: who: {0}, what: {1}".format(who, what)) self.events.put({"when": time.time(), "who": who, "what": what}) if self.opts.fedmsg_enabled and fedmsg: content["who"] = who content["what"] = what try: fedmsg.publish(modname="copr", topic=topic, msg=content) # pylint: disable=W0703 except Exception as e: # XXX - Maybe log traceback as well with traceback.format_exc() self.callback.log("failed to publish message: {0}".format(e))
def announce(**kwargs): """ Emit an announcement message to the FI bus. Example:: $ echo "Fedora Core 4 has been declared GOLD" | fedmsg-announce \ --link http://fedoraproject.org/news Technically this command is a simpler version of fedmsg-logger that emits on a special topic. It is expected that :term:`routing_policy` is specified such that only restricted parties can issue fedmsg announcements. This command expects its message to come from stdin. """ # This specifies that a special certificate should be used to sign this # message. At the sysadmin level, you are responsible for taking care of # two things: # 1) That the announce cert is readable only by appropriate persons. # 2) That the routing_policy is setup so that "announce.announcement" # messages are valid only if signed by such a certificate. kwargs['cert_prefix'] = "announce" # This just specifies that we should be talking to the fedmsg-relay. kwargs['active'] = True fedmsg.init(name='relay_inbound', **kwargs) # Read in and setup our message. Include the --link, even if it is None. message = "\n".join(map(str.strip, sys.stdin.readlines())) msg = dict(message=message, link=kwargs['link']) # Fire! fedmsg.publish(modname="announce", topic="announcement", msg=msg)
def send_message(cbtype, *args, **kws): if cbtype.startswith('post'): msgtype = cbtype[4:] else: msgtype = cbtype[3:] # Short-circuit ourselves for task events. They are very spammy and we are # only interested in state changes to scratch builds (parent tasks). if cbtype == 'postTaskStateChange': # only state changes if not kws.get('attribute', None) == 'state': return # only parent tasks if kws.get('info', {}).get('parent'): return # only scratch builds request = kws.get('info', {}).get('request', [{}])[-1] if not isinstance(request, dict) or not request.get('scratch'): return topic = camel_to_dots(msgtype) body = get_message_body(topic, *args, **kws) # We need this to distinguish between messages from primary koji # and the secondary hubs off for s390 and ppc. body['instance'] = 'primary' fedmsg.publish(topic=topic, msg=body, modname='buildsys')
def add_rating(session, pkgname, rating, user): """ Add the provided rating to the specified package. """ package = model.Package.by_name(session, pkgname) try: # Try to change an existing rating first. ratingobj = model.Rating.get(session, package_id=package.id, user_id=user.id) if ratingobj.rating == rating: message = 'Rating on package "%s" did not change' % (pkgname) else: ratingobj.rating = rating message = 'Rating on package "%s" changed to "%s"' % (pkgname, rating) except NoResultFound: # If no rating was found, we need to add a new one. ratingobj = model.Rating(package_id=package.id, user_id=user.id, rating=rating) session.add(ratingobj) user.score += 1 session.add(user) message = 'Rating "%s" added to the package "%s"' % (rating, pkgname) session.add(ratingobj) session.flush() fedmsg.publish('rating.update', msg=dict(rating=ratingobj.__json__(session), )) return message
def publish(topic, msg, force=False): """ Publish a message to fedmsg. By default, messages are not sent immediately, but are queued in a transaction "data manager". They will only get published after the sqlalchemy transaction completes successfully and will not be published at all if it fails, aborts, or rolls back. Specifying force=True to this function by-passes that -- messages are sent immediately. """ if not bodhi.config.config.get('fedmsg_enabled'): bodhi.log.warn("fedmsg disabled. not sending %r" % topic) return # Initialize right before we try to publish, but only if we haven't # initialized for this thread already. if not fedmsg_is_initialized(): init() if force: bodhi.log.debug("fedmsg skipping transaction and sending %r" % topic) fedmsg.publish(topic=topic, msg=msg) else: bodhi.log.debug("fedmsg enqueueing %r" % topic) manager = _managers_map.get_current_data_manager() manager.enqueue(topic, msg)
def run(shmelf): config = copy.deepcopy(self.config) import fedmsg fedmsg.init(**config) fedmsg.publish(topic=self.topic, msg=secret, modname="threadtest")
def fedmsg_publish(*args, **kwargs): # pragma: no cover ''' Try to publish a message on the fedmsg bus. ''' try: import fedmsg fedmsg.publish(*args, **kwargs) except Exception, err: warnings.warn(str(err))
def wrapper(self, *args, **kw): # Call the target plugin's original code first and save the # result. result = old_method.__func__(self, *args, **kw) # Include the owner of the meeting in the chairs dict just # in case they never explicitly #chair'd themselves. chairs = self.chairs chairs[self.owner] = chairs.get(self.owner, True) # Emit on "org.fedoraproject.prod.meetbot.meeting.start" fedmsg.publish( modname="meetbot", topic=topic, msg=dict( owner=self.owner, chairs=chairs, attendees=self.attendees, url=self.config.filename(url=True), meeting_topic=self._meetingTopic, topic=self.currenttopic, channel=self.channel, details=kw, # This includes the 'who' and 'what' ), ) # Return the original result from the target plugin. return result
def playbook_on_play_start(self, pattern): # This gets called once for each play.. but we just issue a message once # for the first one. One per "playbook" play = getattr(self, 'play', None) if play: # figure out where the playbook FILE is path = os.path.abspath(play.playbook.filename) # Bail out early without publishing if we're in --check mode if play.playbook.check: return if not self.playbook_path: fedmsg.publish( modname="ansible", topic="playbook.start", msg=dict( playbook=path, userid=getlogin(), extra_vars=play.playbook.extra_vars, inventory=play.playbook.inventory.host_list, playbook_checksum=play.playbook.check, check=play.playbook.check, ), ) self.playbook_path = path
def v2_playbook_on_play_start(self, play): # This gets called once for each play.. but we just issue a message once # for the first one. One per "playbook" if self.playbook: # figure out where the playbook FILE is path = os.path.abspath(self.playbook._file_name) # Bail out early without publishing if we're in --check mode if self.play_context.check_mode: return if not self.playbook_path: fedmsg.publish( modname="ansible", topic="playbook.start", msg=dict( playbook=path, userid=getlogin(), extra_vars=play._variable_manager.extra_vars, inventory=play._variable_manager._inventory.src(), playbook_checksum=secure_hash(path), check=self.play_context.check_mode, ), ) self.playbook_path = path
def tpc_finish(self, transaction): for topic, msg in self.uncommitted: bodhi.log.debug("fedmsg sending %r" % topic) fedmsg.publish(topic=topic, msg=msg) self.committed = copy.copy(self.uncommitted) _managers_map.remove(self) self._finish('committed')
def add_rating(session, pkgname, rating, user): """ Add the provided rating to the specified package. """ package = model.Package.by_name(session, pkgname) try: # Try to change an existing rating first. ratingobj = model.Rating.get(session, package_id=package.id, user_id=user.id) if ratingobj.rating == rating: message = 'Rating on package "%s" did not change' % ( pkgname) else: ratingobj.rating = rating message = 'Rating on package "%s" changed to "%s"' % ( pkgname, rating) except NoResultFound: # If no rating was found, we need to add a new one. ratingobj = model.Rating(package_id=package.id, user_id=user.id, rating=rating) session.add(ratingobj) user.score += 1 session.add(user) message = 'Rating "%s" added to the package "%s"' % (rating, pkgname) session.add(ratingobj) session.flush() fedmsg.publish('rating.update', msg=dict( rating=ratingobj.__json__(session), )) return message
def publish(topic, msg): # pragma: no cover ''' Send a message on the fedmsg bus. ''' try: import fedmsg fedmsg.publish(topic=topic, msg=msg) except Exception, err: warnings.warn(str(err))
def run(self): self.config["active"] = True self.config["name"] = "relay_inbound" fedmsg.init(**self.config) idx = self.config.get("msg_id") if not idx: print("--msg-id is required") sys.exit(1) print("Retrieving %r" % idx) url = self.config["datagrepper_url"] + "/id" resp = requests.get(url, params={"id": idx}) code = resp.status_code if code != 200: print("datagrepper request of %r failed. Status: %r" % (idx, code)) sys.exit(2) msg = resp.json() tokens = msg["topic"].split(".") modname = tokens[3] topic = ".".join(tokens[4:]) print("Broadcasting %r" % idx) fedmsg.publish(modname=modname, topic=topic, msg=msg["msg"]) print("OK.")
def send_fedmsgs_after_commit(session): """ Send queued fedmsgs after a database commit. This relies on the session ``info`` dictionary being populated. At the moment, this is done by calling the :func:`publish` function. In the future it should be done automatically using SQLAlchemy listeners. Args: session (sqlalchemy.orm.session.Session): The session that was committed. """ if 'fedmsg' in session.info: _log.debug('Emitting all queued fedmsgs for %r', session) # Initialize right before we try to publish, but only if we haven't # initialized for this thread already. if not fedmsg_is_initialized(): init() for topic, messages in session.info['fedmsg'].items(): _log.debug('emitting %d fedmsgs to the "%s" topic queued by %r', len(messages), topic, session) for msg in messages: fedmsg.publish(topic=topic, msg=msg) _log.debug('Emitted a fedmsg, %r, on the "%s" topic, queued by %r', msg, topic, session) # Tidy up after ourselves so a second call to commit on this session won't # send the same messages again. We cannot delete topic from fedmsg dict # because we cannot change dictionary size during iteration session.info['fedmsg'][topic] = []
def _create_branch(pkgname, branch, existing_branches): '''Create a specific branch for a package. :arg pkgname: Name of the package to branch :arg branch: Name of the branch to create :arg existing_branches: A list of the branches that already exist locally. ''' branch = branch.replace('*', '').strip() if branch == 'master': print 'ERROR: Proudly refusing to create master branch. Invalid repo?' print 'INFO: Please check %s repo' % pkgname return if branch in existing_branches: print 'ERROR: Refusing to create a branch %s that exists' % branch return try: _invoke(MKBRANCH, [branch, pkgname]) fedmsg.publish( topic='branch', modname='git', msg=dict( agent='pkgdb', name=pkgname, branch=branch, ), ) except ProcessError, e: if e.returnCode == 255: # This is a warning, not an error return raise
def branch_package(pkgname, requested_branches, existing_branches): '''Create all the branches that are listed in the pkgdb for a package. :arg pkgname: The package to create branches for :arg requested_branches: The branches to creates :arg existing_branches: A list of existing local branches ''' if VERBOSE: print 'Fixing package %s for branches %s' % (pkgname, requested_branches) # Create the devel branch if necessary exists = os.path.exists(os.path.join(GIT_FOLDER, '%s.git' % pkgname)) if not exists or 'master' not in existing_branches: _invoke(SETUP_PACKAGE, [pkgname]) if 'master' in requested_branches: requested_branches.remove('master') # SETUP_PACKAGE creates master fedmsg.publish( topic='branch', modname='git', msg=dict( agent='pkgdb', name=pkgname, branch='master', ), ) # Create all the required branches for the package # Use the translated branch name until pkgdb falls inline for branch in requested_branches: _create_branch(pkgname, branch, existing_branches)
def _publish_decision_update_fedmsg(self, decision): try: fedmsg.publish(topic='decision.update', msg=decision) self._inc(messaging_tx_sent_ok_counter) except Exception: log.exception('Error sending fedmsg message') self._inc(messaging_tx_failed_counter) raise
def notify(topic, msg): """ Takes a message topic, image name, an upload destination (ex. "EC2-eu-west-1"), and a status (ex. "failed"). Can also take an optional dictionary of addiitonal bits of information, such as an AMI ID for an image registered to AWS EC2. Emits a fedmsg appropriate for each image task (an upload or a test). """ fedmsg.publish(topic=topic, modname='fedimg', msg=msg)
def publish_to_fedmsg(topic, *args, **params): """ Publish the message to fedmsg with image_url, image_name, status and build_id """ try: fedmsg.publish(topic=topic, modname="autocloud", msg=params) except Exception as err: log.error(err)
def message(image_name, dest, status): """ Takes an upload destination (ex. "EC2-east") and a status (ex. "failed"). Emits a fedmsg appropriate for each image upload task. """ fedmsg.publish(topic='image.upload', modname='fedimg', msg={ 'image_name': image_name, 'destination': dest, 'status': status, })
def publish_new_waiver(session): """ A post-commit event hook that emits messages to a message bus. The messages can be published by either fedmsg-hub with zmq or stomp. This event is designed to be registered with a session factory:: >>> from sqlalchemy.event import listen >>> listen(MyScopedSession, 'after_commit', publish_new_waiver) The emitted message will look like:: { "username": "******", "i": 4, "timestamp": 1489686124, "msg_id": "2017-80e46243-e6f5-46df-8dcd-4d17809eb298", "topic": "org.fedoraproject.dev.waiverdb.waiver.new", "msg": { "comment": "Because I said so", "username": "******", "waived": true, "timestamp": "2017-03-16T17:42:04.209638", "product_version": "Satellite 6.3", "subject": "{\"a.nice.example\": \"this-is-a-really-nice-example\"}", "testcase": "t.e.s.t.case", "proxied_by": null, "id": 15 } } Args: session (sqlalchemy.orm.Session): The session that was committed to the database. This session is not active and cannot emit SQL. """ _log.debug('The publish_new_waiver SQLAlchemy event has been activated.') if current_app.config['MESSAGE_PUBLISHER'] == 'stomp': with stomp_connection() as conn: stomp_configs = current_app.config.get('STOMP_CONFIGS') for row in session.identity_map.values(): if isinstance(row, Waiver): _log.debug('Publishing a message for %r', row) msg = json.dumps(marshal(row, waiver_fields)) kwargs = dict(body=msg, headers={}, destination=stomp_configs['destination']) if stomp.__version__[0] < 4: kwargs['message'] = kwargs.pop( 'body') # On EL7, different sig. conn.send(**kwargs) else: for row in session.identity_map.values(): if isinstance(row, Waiver): _log.debug('Publishing a message for %r', row) fedmsg.publish(topic='waiver.new', msg=marshal(row, waiver_fields))
def callback(topic, msg): request = pyramid.threadlocal.get_current_request() settings = request.registry.settings if fedmsg and asbool(settings.get('tahrir.use_fedmsg', False)): fedmsg.publish( modname="fedbadges", topic=topic, msg=msg, )
def notify(self, openid, context, changed): obj = type(self).__name__.lower() topic = obj + ".update" fedmsg.publish(topic=topic, msg=dict( openid=openid, context=context, changed=changed, ))
def publishTask(): self.log.debug("CVS: publish: %d" % len(self.publish_queue)) for commit in self.publish_queue: fedmsg.publish(topic='commit', modname='cvs', active=True, name='relay_inbound', msg=commit) self.publish_queue = []
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 notify(self, openid, changed): obj = type(self).__name__.lower() topic = obj + ".update" fedmsg.publish( topic=topic, msg=dict( openid=openid, changed=changed, ) )
def send_message(cbtype, *args, **kws): if cbtype.startswith('post'): msgtype = cbtype[4:] else: msgtype = cbtype[3:] topic = camel_to_dots(msgtype) body = get_message_body(topic, *args, **kws) fedmsg.publish(topic=topic, msg=body, modname='koji')
def playbook_on_stats(self, stats): results = dict([(h, stats.summarize(h)) for h in stats.processed]) fedmsg.publish( modname="ansible", topic="playbook.complete", msg=dict( playbook=self.playbook, userid=getlogin(), results=results, ), )
def set_status(self, status, commit=True): if status == STATUS_OPEN: self.start_time = datetime.now() elif status in (STATUS_DONE, STATUS_FAILED): self.complete_time = datetime.now() self.status = status fedmsg.publish(topic='job.status.change', msg={'status': STRSTATUS[status], 'job': self}) db.session.add(self) db.session.commit()
def _log_message(self, kw, message): if kw['json_input']: msg = fedmsg.encoding.loads(message) else: msg = {'log': message} fedmsg.publish( topic=kw['topic'], msg=msg, modname=kw['modname'], )
def fedmsg_publish(*args, **kwargs): # pragma: no cover ''' Try to publish a message on the fedmsg bus. ''' ## We catch Exception if we want :-p # pylint: disable=W0703 ## Ignore message about fedmsg import # pylint: disable=F0401 try: import fedmsg fedmsg.publish(*args, **kwargs) except Exception, err: warnings.warn(str(err))
def fedmsg_publish(*args, **kwargs): # pragma: no cover ''' Try to publish a message on the fedmsg bus. ''' # We catch Exception if we want :-p # pylint: disable=W0703 # Ignore message about fedmsg import # pylint: disable=F0401 try: import fedmsg fedmsg.publish(*args, **kwargs) except Exception, err: warnings.warn(str(err))
def fedmsg_publish(*args, **kwargs): # pragma: no cover ''' Try to publish a message on the fedmsg bus. ''' # We catch Exception if we want :-p # pylint: disable=broad-except # Ignore message about fedmsg import # pylint: disable=import-error kwargs['modname'] = 'pagure' try: import fedmsg fedmsg.publish(*args, **kwargs) except Exception as err: warnings.warn(str(err))