Skip to content

Commit

Permalink
Common Action Reporting Protocol (CARP) module
Browse files Browse the repository at this point in the history
  • Loading branch information
ndenny committed Oct 28, 2024
1 parent 2e75d38 commit dd20f8f
Showing 1 changed file with 82 additions and 52 deletions.
134 changes: 82 additions & 52 deletions lib/Bastion/CARP.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
Common Action-Result/Report Protocol
"""
import uuid


class ReplyStatus(tuple):
DEFAULT_CATEGORY_GLOSS = {
'1': 'FYI',
Expand All @@ -29,6 +32,7 @@ class ReplyStatus(tuple):
412: "precondition failed",
416: "range not satisfiable",
500: "exception",
599: "crash and burn"
}

def __new__(cls, *args):
Expand Down Expand Up @@ -100,72 +104,98 @@ def is_inconclusive(self):
ReplyStatus.RangeError = ReplyStatus(416)
ReplyStatus.Exception = ReplyStatus(500)
ReplyStatus.Fault = ReplyStatus.Exception
ReplyStatus.Crashed = ReplyStatus(500)
ReplyStatus.Crashed = ReplyStatus(599)

ResultStatus = ReplyStatus #-- Alias for ReplyStatus


class isAction:
def __init__(self):
self.request = None
self.result = None
self.log = [ ]

def __call__(self, *args, **kwargs):
self.request = Request(self.name, args, kwargs)
self.do(*args, **kwargs)
return self.result()

def debug(self, msg):
pass

def info(self, msg):
pass

def warn(self, msg):
pass

def error(self, msg):
pass

def critical(self, msg):
pass


class isHpssAction(isAction):
def __init__(self, vault):
isAction.__init__(self)
self.vault = vault


class PushAction(isHpssAction):
def do(self, *args, **kwargs):
self.critical("action is not yet implemented")
self.fail("not implemented, yet!")



fortress.push("[@alfisol:oobabooga/models]")
class isReceipt:
def __init__(self, request, status, brief, obj, context = None, **kwargs):
#-- request is a 2-tuple of (action, [arg1, ...])
#-- status is an instance of ReplyStatus
#-- brief is an arbitrary (assumed human readable) text string
#-- obj is any JSON serializable object.
#-- context, if given, is a dict of extra key-value associations.
if not isinstance(status, ReplyStatus):
raise ValueError("status must be of type ReplyStatus")

self.RID = kwargs.get('ID', str(uuid.uuid4()))
self.action = request[0]
self.args = request[1]
self.status = status
self.brief = str(msg)
self.body = obj
self.context = { }

if context is not None:
self.context = context.copy()

def toJDN(self, **kwargs):
#-- receipts have FOUR top level sections: request, result, context, and data.
#-- result is the http-like status code and message, e.g. (200, "Ok")
#-- brief is a single text string that is a human readable summary of the receipt.
#-- context is an arbitrary set of key-value pairs
#-- data is a JSON serializable object that is the body of the receipt.
if callable(getattr(obj, 'toJDN', None)):
payload = obj.toJDN()
else:
payload = obj

jdn = { }

jdn['request'] = {
'ID': self.RID,
'action': self.action,
'args': list(self.args),
'context': self.context.copy(),
}
jdn['request']['result'] = {
'status': self.status.code,
'message': self.status.gloss,
'summary': self.brief,
}
jdn['request']['result']['body'] = {
'data': payload
}
return jdn

@property
def succeeded(self):
return self.status.indicates_success

@property
def failed(self):
return self.status.indicates_failure

@property
def inconclusive(self):
return self.status.is_inconclusive

fortress.push = HPSSPushAction(fortress)

fortress.push(models)
class Receipt(isReceipt):
pass


class PushRequest(isRequest):
def __init__(self):
pass
class Report(isReceipt):
def __init__(self, status, brief, doc, obj = None, **kwargs):
isReceipt.__init__(self, status, brief, obj, **kwargs)
self.report = doc

def toJDN(self, **kwargs):
jdn = isReceipt.toJDN(self, **kwargs)
jdn['request']['result']['report'] = str(self.report)
return jdn

class PushAction(isAction):
def __init__(self, vault):
self.vault = vault

def do(self, *args, **kwargs):
return self.crashed("not implemented, yet!")
def SUCCEEDED(doc, obj = None, **kwargs):
return Report(ReplyStatus.Ok, doc, obj, **kwargs)

def FAILED(doc, obj = None, **kwargs):
return CARP(ReplyStatus.Failed, doc, obj, **kwargs)

def CRASHED(doc, obj = None, **kwargs):
return CARP(ReplyStatus.Crashed, doc, obj, **kwargs)

SUCCESS = SUCCEEDED
FAILURE = FAILED
CRASH = CRASHED

0 comments on commit dd20f8f

Please sign in to comment.