now managing event content file fields

master
Marek Isalski 6 years ago
parent 0533a3101f
commit 4fac492255

@ -16,6 +16,9 @@ class Event( object ):
return "content/event/" + os.path.basename( self.path ) return "content/event/" + os.path.basename( self.path )
def open( self ): def open( self ):
if os.path.exists( self.path ):
self.read()
return False
for path in glob.glob( self.glob ): for path in glob.glob( self.glob ):
if os.path.exists( path ): if os.path.exists( path ):
self.path = path self.path = path
@ -24,21 +27,84 @@ class Event( object ):
return True return True
def write( self ): def write( self ):
outfile = open( self.path, 'w', encoding = "utf-8" ) outdata = ( '''\
outfile.write( ( '''\
--- ---
%(yaml)s %(yaml)s
--- ---
%(md)s %(md)s
''' % { 'yaml': yaml.dump( self.fields, default_flow_style = False ), ''' % { 'yaml': yaml.dump( self.fields, default_flow_style = False ),
'md': self.doc, 'md': self.doc,
} ) ) } )
outfile = open( self.path, 'w', encoding = "utf-8" )
outfile.write( outdata )
return outdata
def read( self ): def read( self ):
indata = open( self.path, 'r', encoding = "utf-8" ).read() indata = open( self.path, 'r', encoding = "utf-8" ).read()
try: ( pre, yamldata, docdata ) = re.split( "^---$", indata, flags = re.MULTILINE )
( pre, yamldata, docdata ) = re.split( "^---$", indata, flags = re.MULTILINE ) self.fields = yaml.load( yamldata )
except ValueError:
return
self.yaml = yaml.load( yamldata )
self.doc = docdata.strip() self.doc = docdata.strip()
def set_title( self, title ):
self.fields[ '$title@' ] = title
def set_slug( self, slug ):
self.fields[ '$slug' ] = slug
def set_published( self, published ):
if not self.fields.get( '$date' ):
self.fields[ '$date' ] = {}
if not self.fields[ '$date' ].get( 'published' ):
self.fields[ '$date' ][ 'published' ] = published
return published
def set_started( self, started ):
if not self.fields.get( '$date' ):
self.fields[ '$date' ] = {}
self.fields[ '$date' ][ 'started' ] = started
return started
def set_expected( self, expected ):
if not self.fields.get( '$date' ):
self.fields[ '$date' ] = {}
self.fields[ '$date' ][ 'expected' ] = expected
return expected
def set_finished( self, finished ):
if not self.fields.get( '$date' ):
self.fields[ '$date' ] = {}
self.fields[ '$date' ][ 'finished' ] = finished
return finished
def set_resolved( self, resolved ):
if not self.fields.get( '$date' ):
self.fields[ '$date' ] = {}
self.fields[ '$date' ][ 'resolved' ] = resolved
return resolved
def add_timeline( self, time, line ):
if not self.fields.get( 'timeline' ):
self.fields[ 'timeline' ] = []
self.fields[ 'timeline' ].append( { 'time': time, 'line': line } )
def _toggle( self, fieldname ):
if self.fields.get( fieldname ):
del self.fields[ fieldname ]
else:
self.fields[ fieldname ] = True
return " ".join( [ x for x in [ 'incident', 'degraded', 'maintenance', 'notice', 'ok' ] if self.fields.get( x ) ] )
def toggle_incident( self ):
return self._toggle( 'incident' )
def toggle_degraded( self ):
return self._toggle( 'degraded' )
def toggle_maintenance( self ):
return self._toggle( 'maintenance' )
def toggle_notice( self ):
return self._toggle( 'notice' )
def toggle_ok( self ):
return self._toggle( 'ok' )

160
fih.py

@ -53,34 +53,34 @@ def channel_name_to_raw_incident_number( channel_name ):
return channel_name[ len( app.config[ "MATTERMOST_INCIDENT_CHANNEL_PREFIX" ] ): ] return channel_name[ len( app.config[ "MATTERMOST_INCIDENT_CHANNEL_PREFIX" ] ): ]
def mattermost_incident_command( command, args, channel_id, raw_incident_number ): def mattermost_incident_command( command, args, channel_id, raw_incident_number, user_name ):
app.mm.posts.create_post( options = { 'channel_id': channel_id, channel = app.mm.channels.get_channel( channel_id )
'message': "### Executing `" + command + "`...", slug = slugify.slugify( channel[ 'purpose' ] )
} ) ev = event.Event( path = app.config[ "STATUS_EVENT_SCHEME" ] % { "incident_number": raw_incident_number,
"slug": slug,
},
glob = app.config[ "STATUS_EVENT_GLOB" ] % { "incident_number": raw_incident_number,
},
)
if command == "PUBLISH": if command == "PUBLISH":
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "### `PUBLISH` requested by @%s!" % user_name,
} )
# update local repository
cmdline = app.config[ "MERCURIAL_BIN" ] + " update" cmdline = app.config[ "MERCURIAL_BIN" ] + " update"
message = exec_to_message( cmdline ) message = exec_to_message( cmdline )
app.mm.posts.create_post( options = { 'channel_id': channel_id, app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': message, 'message': message,
} ) } )
channel = app.mm.channels.get_channel( channel_id ) # create/update event content file
slug = slugify.slugify( channel[ 'purpose' ] )
ev = event.Event( path = app.config[ "STATUS_EVENT_SCHEME" ] % { "incident_number": raw_incident_number,
"slug": slug,
},
glob = app.config[ "STATUS_EVENT_GLOB" ] % { "incident_number": raw_incident_number,
},
)
new = ev.open() new = ev.open()
ev.doc = channel[ 'header' ] ev.doc = channel[ 'header' ]
ev.fields[ '$title@' ] = channel[ 'purpose' ] ev.set_title( channel[ 'purpose' ] )
ev.fields[ '$slug' ] = raw_incident_number ev.set_slug( raw_incident_number )
if not ev.fields.get( '$date' ): ev.set_published( datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" ) )
ev.fields[ '$date' ] = {}
if not ev.fields[ '$date' ].get( 'published' ):
ev.fields[ '$date' ][ 'published' ] = datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" )
written = ev.write() written = ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id, app.mm.posts.create_post( options = { 'channel_id': channel_id,
@ -101,7 +101,15 @@ def mattermost_incident_command( command, args, channel_id, raw_incident_number
app.mm.posts.create_post( options = { 'channel_id': channel_id, app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': message, 'message': message,
} ) } )
else:
cmdline = app.config[ "MERCURIAL_BIN" ] + " commit -m 'update event for incident " + raw_incident_number + " via FIH' " + ev.path_short()
message = exec_to_message( cmdline )
if message:
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': message,
} )
# pull, merge, commit
for pull_from in app.config[ "MERCURIAL_PUSH_TO" ]: for pull_from in app.config[ "MERCURIAL_PUSH_TO" ]:
cmdline = app.config[ "MERCURIAL_BIN" ] + " pull " + pull_from cmdline = app.config[ "MERCURIAL_BIN" ] + " pull " + pull_from
message = exec_to_message( cmdline ) message = exec_to_message( cmdline )
@ -123,7 +131,16 @@ def mattermost_incident_command( command, args, channel_id, raw_incident_number
app.mm.posts.create_post( options = { 'channel_id': channel_id, app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': message, 'message': message,
} ) } )
# push updated repository
for pull_from in app.config[ "MERCURIAL_PUSH_TO" ]:
cmdline = app.config[ "MERCURIAL_BIN" ] + " push " + pull_from
message = exec_to_message( cmdline )
if message:
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': message,
} )
for deploy_to in app.config[ "GROW_DEPLOY_TO" ]: for deploy_to in app.config[ "GROW_DEPLOY_TO" ]:
cmdline = app.config[ "GROW_BIN" ] + " deploy -f " + deploy_to cmdline = app.config[ "GROW_BIN" ] + " deploy -f " + deploy_to
message = exec_to_message( cmdline ) message = exec_to_message( cmdline )
@ -132,34 +149,98 @@ def mattermost_incident_command( command, args, channel_id, raw_incident_number
'message': message, 'message': message,
} ) } )
app.mm.posts.create_post( options = { 'channel_id': request.form[ 'channel_id' ],
'message': "### `PUBLISH` completed!",
} )
elif command == "START": elif command == "START":
pass new = ev.open()
started = ev.set_started( args or datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" ) )
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Event start date set by %s to: `%s`" % ( user_name, started ),
} )
elif command == "ETR": elif command == "ETR":
pass new = ev.open()
expected = ev.set_expected( args or datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" ) )
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Event estimated time of resolution set by %s to: `%s`" % ( user_name, expected ),
} )
elif command == "FINISHED":
new = ev.open()
finished = ev.set_finished( args or datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" ) )
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Event finished time set by %s to: `%s`" % ( user_name, finished ),
} )
elif command == "RESOLVED": elif command == "RESOLVED":
pass new = ev.open()
elif command == "CLOSED": resolved = ev.set_resolved( args or datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" ) )
pass ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Event resolved time set by %s to: `%s`" % ( user_name, resolved ),
} )
elif command == "TIMELINE": elif command == "TIMELINE":
pass if not args:
return "You need to specify some text to add to the timeline..."
new = ev.open()
ev.add_timeline( time = datetime.datetime.utcnow().strftime( "%Y-%m-%d %H:%M" ), line = args )
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Timeline entry added by @%s:\n\n> %s" % ( user_name, args ),
} )
elif command == "INCIDENT": elif command == "INCIDENT":
pass new = ev.open()
flags = ev.toggle_incident()
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Flags set by @%s to: `%s`" % ( user_name, flags ),
} )
elif command == "DEGRADED": elif command == "DEGRADED":
pass new = ev.open()
flags = ev.toggle_degraded()
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Flags set by @%s to: `%s`" % ( user_name, flags ),
} )
elif command == "MAINTENANCE": elif command == "MAINTENANCE":
pass new = ev.open()
flags = ev.toggle_maintenance()
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Flags set by @%s to: `%s`" % ( user_name, flags ),
} )
elif command == "NOTICE": elif command == "NOTICE":
pass new = ev.open()
flags = ev.toggle_notice()
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Flags set by @%s to: `%s`" % ( user_name, flags ),
} )
elif command == "OK": elif command == "OK":
pass new = ev.open()
flags = ev.toggle_ok()
ev.write()
app.mm.posts.create_post( options = { 'channel_id': channel_id,
'message': "Flags set by @%s to: `%s`" % ( user_name, flags ),
} )
else: else:
return "WTF command?" return "WTF command?"
app.mm.posts.create_post( options = { 'channel_id': request.form[ 'channel_id' ], return ""
'message': "### Finished `" + command + "`!",
} )
return "OK"
def mattermost_incident_start( description, team_id, user_name, user_id, channel_id ): def mattermost_incident_start( description, team_id, user_name, user_id, channel_id ):
raw_incident_number = incident.generate_raw_incident_number() raw_incident_number = incident.generate_raw_incident_number()
@ -199,10 +280,10 @@ The contents of this channel are strictly confidential.
## Status Updates ## Status Updates
* add an update: **/incident TIMELINE** _text_ * add an update: **/incident TIMELINE** _text_
* set the incident start: **/incident START** _%(now)s_ (UTC) * set the event start: **/incident START** _%(now)s_ (UTC)
* set the incident ETR: **/incident ETR** _%(now)s_ (UTC) * set the event ETR: **/incident ETR** _%(now)s_ (UTC)
* set the incident resolved time: **/incident RESOLVED** _%(now)s_ (UTC) * set the event finished time: **/incident FINISHED** _%(now)s_ (UTC)
* set the incident finished time: **/incident CLOSED** _%(now)s_ (UTC) * set the event closure time: **/incident RESOLVED** _%(now)s_ (UTC)
Again, don't forget to **/incident PUBLISH** once making changes. Again, don't forget to **/incident PUBLISH** once making changes.
@ -248,6 +329,7 @@ def mattermost_incident():
return mattermost_incident_command( command = text[ 0 ].upper(), return mattermost_incident_command( command = text[ 0 ].upper(),
args = " ".join( text[ 1: ] ), args = " ".join( text[ 1: ] ),
channel_id = request.form[ 'channel_id' ], channel_id = request.form[ 'channel_id' ],
user_name = request.form[ 'user_name' ],
raw_incident_number = raw_incident_number, raw_incident_number = raw_incident_number,
) )
else: else:

Loading…
Cancel
Save