Skip to content

Commit

Permalink
Merge pull request #17 from diggyk/master
Browse files Browse the repository at this point in the history
Added Slack support and dropped unused code
  • Loading branch information
gmjosack committed Jun 19, 2015
2 parents 1e14dfd + 7963ee8 commit 268fdfb
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 117 deletions.
4 changes: 4 additions & 0 deletions config/dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ database: "mysql://localhost:3306/emsdb?user=emsdb&passwd=testpw"
# The server to use to host queries
query_server: "http://localhost:5353/api/query"

# Slack integration (optional)
# slack_webhook: "https://hooks.slack.com/services/"
# slack_proxyhost: "proxyserver:port"

# This is the expiration (in seconds) of auth_tokens used for API calls
# Type: int
auth_token_expiry: 600
1 change: 0 additions & 1 deletion hermes/handlers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from .util import ApiHandler, PluginHelper
from .. import exc
from ..models import Host, EventType, Event, Labor, Fate, Quest
from ..util import qp_to_bool as qpbool, parse_set_query

from datetime import datetime
from dateutil import parser
Expand Down
98 changes: 41 additions & 57 deletions hermes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from sqlalchemy.types import Integer, String, Boolean
from sqlalchemy.types import DateTime

from .util import slack_message
from .settings import settings
import exc

Expand Down Expand Up @@ -627,7 +628,7 @@ def get_starting_fates(cls, session):
return Fate._starting_fates

@classmethod
def question_the_fates(cls, session, events, quest=None, flush=True):
def question_the_fates(cls, session, events, quest=None):
"""Look through the Fates and see if we need to create or close
Labors based on these Events.
Expand Down Expand Up @@ -844,6 +845,12 @@ def create(
session.rollback()
raise

slack_message("*Event:* {} = {} {}".format(
event.host.hostname,
event.event_type.category,
event.event_type.state
))

Fate.question_the_fates(session, [event], quest=quest)

return event
Expand All @@ -865,7 +872,11 @@ def create_many(cls, session, events, tx, quest=None):

events = session.query(Event).filter(Event.tx == tx).all()
log.info("Created {} events".format(len(events)))
Fate.question_the_fates(session, events, quest=quest, flush=False)


slack_message("*Events:* created {} events".format(len(events)))

Fate.question_the_fates(session, events, quest=quest)


def href(self, base_uri):
Expand Down Expand Up @@ -992,6 +1003,18 @@ def create(

session.flush()
session.commit()

slack_message(
"*Quest {}* created by {}: "
"{} hosts started with {} {}\n\t\"{}\"".format(
quest.id,
quest.creator,
len(hosts),
creation_event_type.category,
creation_event_type.state,
quest.description
)
)
return quest

def check_for_victory(self):
Expand All @@ -1010,6 +1033,10 @@ def check_for_victory(self):
self.update(
completion_time=datetime.utcnow()
)
slack_message("*Quest {}* completed:\n\t\"{}\"".format(
self.id,
self.description
))

@classmethod
def get_open_quests(cls, session):
Expand Down Expand Up @@ -1138,45 +1165,6 @@ class Labor(Model):
),
)

@classmethod
def create(
cls, session,
host, creation_event, quest=None, flush=True
):
"""Create an Labor
Args:
host: the Host to which this event pertains
creation_event: the Event that lead to the creation of this labor
quest: optional Quest if labor is part of a Quest creation
flush: should we flush now?
Returns:
a newly created Labor
"""
if host is None:
raise exc.ValidationError(
"Host cannot be null for an labor"
)
if creation_event is None:
raise exc.ValidationError(
"Creation Event cannot be null for an labor"
)

try:
obj = cls(
host=host, creation_event=creation_event, quest=quest
)
obj.add(session)
if flush:
session.flush()

except Exception:
session.rollback()
raise

return obj

@classmethod
def create_many(cls, session, labors):
"""Create multiple Labors
Expand All @@ -1190,6 +1178,10 @@ def create_many(cls, session, labors):
Labor.__table__.insert(), labors
)
session.flush()
slack_message("*Labors:* created {} labor{}".format(
len(labors),
"s" if len(labors) > 1 else ""
))

@classmethod
def achieve_many(cls, session, labor_dicts):
Expand All @@ -1208,6 +1200,14 @@ def achieve_many(cls, session, labor_dicts):
completion_event=event, completion_time=datetime.utcnow(),
flush=False, commit=False
)

slack_message("*Labor {}* completed.\n\t{}: {} {} => {} {}".format(
labor.id, labor.host.hostname,
labor.creation_event.event_type.category,
labor.creation_event.event_type.state,
labor.completion_event.event_type.category,
labor.completion_event.event_type.state
))
if labor.quest and labor.quest not in quests:
quests.append(labor.quest)
session.flush()
Expand Down Expand Up @@ -1248,22 +1248,6 @@ def acknowledge(self, user):
"""
self.update(ack_time=datetime.utcnow(), ack_user=user)

def achieve(self, event, flush=True, commit=True):
"""Mark an labor as completed.
Args:
event: the event that closed this labor
flush: should we flush the database right away?
commit: should we commit the database right away?
"""
self.update(
completion_event=event, completion_time=datetime.utcnow(),
flush=flush, commit=commit
)

if self.quest:
self.quest.check_for_victory()

def add_to_quest(self, quest):
"""Tie this labor to a particular Quest
Expand Down
2 changes: 2 additions & 0 deletions hermes/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def __getattr__(self, name):
"num_processes": 1,
"database": None,
"query_server": "http://localhost:5353/api/query",
"slack_webhook": None,
"slack_proxyhost": None,
"debug": False,
"domain": "localhost",
"port": 8990,
Expand Down
86 changes: 28 additions & 58 deletions hermes/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,41 @@
Project-wide utilities.
"""

import collections
import logging
import tornado
from jinja2 import Environment, PackageLoader
import requests

from .settings import settings
from .version import __version__


log = logging.getLogger(__name__)

_TRUTHY = set([
"true", "yes", "1", ""
])

def slack_message(message):
"""Post a message to Slack if a webhook as been defined.
def qp_to_bool(arg):
return str(arg).lower() in _TRUTHY


#: Namedtuple for resultant items from ``parse_set_query()``
SetQuery = collections.namedtuple('SetQuery', 'action name value')


def parse_set_query(query):
Args:
message: the content of the Slack post
"""
Parse a representation of set operations for attribute/value pairs into
(action, name, value) and return a list of ``SetQuery`` objects.
Computes left-to-right evaluation, where the first character indicates the
set operation:
+ "+" indicates a union
+ "-" indicates a difference
+ no marker indicates an intersection
For example::
>>> parse_set_query('+owner=team-networking')
[SetQuery(action='union', name='owner', value='team-networking')]
>>> parse_set_query('foo=bar')
[SetQuery(action='intersection', name='foo', value='bar')]
>>> parse_set_query('foo=bar -owner=team-networking')
[SetQuery(action='intersection', name='foo', value='bar'),
SetQuery(action='difference', name='owner', value='team-networking')]
:param query:
Set query string
"""
log.debug('Incoming query = %r' % (query,))
queries = query.split()

attributes = []
for q in queries:
if q.startswith('+'):
action = 'union'
q = q[1:]
elif q.startswith('-'):
action = 'difference'
q = q[1:]
else:
action = 'intersection'

name, _, value = q.partition('=')
attributes.append(SetQuery(action, name, value))

log.debug('Outgoing attributes = %r' % (attributes,))
return attributes
if not settings.slack_webhook:
return

if settings.slack_proxyhost:
proxies = {
"http": "http://{}".format(settings.slack_proxyhost),
"https": "http://{}".format(settings.slack_proxyhost)
}
else:
proxies = None

json = {
"text": message,
"username": "Hermes Log",
"icon_emoji": ":hermes:",
}
try:
log.info("{} {}".format(settings.slack_webhook, json))
response = requests.post(
settings.slack_webhook, json=json, proxies=proxies
)
except Exception as exc:
log.warn("Error writing to Slack: {}".format(exc.message))
2 changes: 1 addition & 1 deletion hermes/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.24"
__version__ = "0.1.26"

0 comments on commit 268fdfb

Please sign in to comment.