diff --git a/lib/Bastion/CARP.py b/lib/Bastion/CARP.py new file mode 100644 index 0000000..826541f --- /dev/null +++ b/lib/Bastion/CARP.py @@ -0,0 +1,171 @@ +""" +Bastion.CARP + +Common Action-Result/Report Protocol +""" +class ReplyStatus(tuple): + DEFAULT_CATEGORY_GLOSS = { + '1': 'FYI', + '2': 'Success', + '3': 'Inconclusive', + '4': 'Failure', + '5': 'Fault' + } + + DEFAULT_CODE_GLOSS = { + 100: "FYI", + 200: "ok", + 201: "created", + 202: "accepted", + 204: "no content", + 207: "multi-status", + 300: "inconclusive", + 302: "found", + 304: "not modified", + 400: "error in request", + 401: "not authorized", + 403: "forbidden", + 404: "not found", + 412: "precondition failed", + 416: "range not satisfiable", + 500: "exception", + } + + def __new__(cls, *args): + if len(args) == 1: + arg = args[0] + + if isinstance(arg, cls): + return arg + + if isinstance(arg, int): + code = int(arg) + category = str(code)[0] + phrase = cls.DEFAULT_CODE_GLOSS[code] if (code in cls.DEFAULT_CODE_GLOSS) else cls.DEFAULT_CATEGORY_GLOSS[category] + return cls(code, phrase) + + if isinstance(arg, str): + if arg.isdigit( ): + return cls( int(arg) ) + + if isinstance(arg, (tuple, list)): + if len(arg) == 2: + return cls(arg[0], arg[1]) + + if len(args) == 2: + code = int(args[0]) + phrase = str(args[1]) + return tuple.__new__(cls, (code, phrase)) + + code = property(operator.itemgetter(0)) + gloss = property(operator.itemgetter(1)) + + def __repr__(self): + return "{}: {}".format(self.code, self.gloss) + + @property + def title(self): + return self.DEFAULT_CATEGORY_GLOSS[self.category] + + @property + def category(self): + return str(self.code)[0] + + @property + def indicates_success(self): + return (self.category in ('1', '2')) + + @property + def indicates_failure(self): + return (self.category in ('4','5')) + + @property + def is_inconclusive(self): + return (self.category in ('3',)) + + +ReplyStatus.FYI = ReplyStatus(100) +ReplyStatus.Ok = ReplyStatus(200) +ReplyStatus.Created = ReplyStatus(201) +ReplyStatus.Accepted = ReplyStatus(202) +ReplyStatus.NoContent = ReplyStatus(204) +ReplyStatus.Multiple = ReplyStatus(207) +ReplyStatus.Inconclusive = ReplyStatus(300) +ReplyStatus.Found = ReplyStatus(302) +ReplyStatus.NotModified = ReplyStatus(304) +ReplyStatus.Failed = ReplyStatus(400) +ReplyStatus.Unauthorized = ReplyStatus(401) +ReplyStatus.Forbidden = ReplyStatus(403) +ReplyStatus.NotFound = ReplyStatus(404) +ReplyStatus.RangeError = ReplyStatus(416) +ReplyStatus.Exception = ReplyStatus(500) +ReplyStatus.Fault = ReplyStatus.Exception +ReplyStatus.Crashed = ReplyStatus(500) + +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]") + + + + +fortress.push = HPSSPushAction(fortress) + +fortress.push(models) + + +class PushRequest(isRequest): + def __init__(self): + pass + + +class PushAction(isAction): + def __init__(self, vault): + self.vault = vault + + def do(self, *args, **kwargs): + return self.crashed("not implemented, yet!") + + +