From f48e6a5df8fb6f277e0335818b4307100e8bb43c Mon Sep 17 00:00:00 2001 From: Nathan Denny Date: Tue, 3 Dec 2024 09:10:28 -0500 Subject: [PATCH] refactoring the result, receipt, report subsystem --- lib/Bastion/CARP.py | 33 +++++++++++++++++---------------- lib/Bastion/Movers/CARP.py | 27 +-------------------------- lib/Bastion/Movers/SFTP.py | 3 +-- lib/Bastion/Packers/CARP.py | 13 ++++++++++--- lib/Bastion/Vaults/SFTP.py | 12 ------------ 5 files changed, 29 insertions(+), 59 deletions(-) diff --git a/lib/Bastion/CARP.py b/lib/Bastion/CARP.py index 6febfde..4a6aafc 100644 --- a/lib/Bastion/CARP.py +++ b/lib/Bastion/CARP.py @@ -220,15 +220,23 @@ def changed(self, *args): def toJDN(self, **kwargs): jdn = isReceipt.toJDN(self, **kwargs) - jdn['request']['result']['report'] = str(self) + jdn['request']['result']['report'] = self.body return jdn @property def body(self): if getattr(self, '_body', None) is None: - self._body = str(self) + #-- encode my object, if I have one, to a YAML string. + if self.record: + self._body = toJDN(self.record) + else: + self._body = "" return self._body + def __str__(self): + return yaml.dump(self.toJDN(), default_flow_style = False, sort_keys = True) + + class ReportException(Report): def __init__(self, request, *args, **kwargs): @@ -239,7 +247,7 @@ def __init__(self, request, *args, **kwargs): status = args[0] errobj = args[1] else: - status = ReplyStatus.failed + status = ReplyStatus.Failed errobj = args[0] assert status.indicates_failure, "ReportException must be created with a reply status indicating failure" @@ -251,33 +259,26 @@ def __init__(self, request, *args, **kwargs): self.xname = type(xobj).__name__ self.xmsg = str(xobj) + def + def __str__(self): return ''.join( traceback.format_exception(self.xobj) ) - class Request(isRequest): #-- Subclasses can set their own REPORT. #-- This is used mostly in the convenience methods: .succeeded, .failed, etc. REPORTS = { } #-- An optional mapping of ReplyStatus code to report class or function. def succeeded(self, *args, **kwargs): - status = ReplyStatus.Ok - mkReport = self.REPORTS.get(status.code, Report) - return mkReport(self, status, *args, **kwargs) + return Report(self, ResultStatus.Ok, *args, **kwargs) def failed(self, *args, **kwargs): - status = ReplyStatus.Failed - mkReport = self.REPORTS.get(status.code, Report) - return mkReport(self, status, *args, **kwargs) + return Report(self, ResultStatus.Failed, *args, **kwargs) def crashed(self, *args, **kwargs): - status = ReplyStatus.Crashed - mkReport = self.REPORTS.get(status.code, Report) - return mkReport(self, status, *args, **kwargs) + return Report(self, ResultStatus.Crashed, *args, **kwargs) def inconclusive(self, *args, **kwargs) - status = ReplyStatus.Inconclusive - mkReport = self.REPORTS.get(status.code, Report) - return mkReport(self, status, *args, **kwargs) + return Report(self, ResultStatus.Inconclusive, *args, **kwargs) diff --git a/lib/Bastion/Movers/CARP.py b/lib/Bastion/Movers/CARP.py index 27f937a..d540884 100644 --- a/lib/Bastion/Movers/CARP.py +++ b/lib/Bastion/Movers/CARP.py @@ -14,32 +14,7 @@ from Bastion.Common import Thing, Unknown import Bastion.Model from Bastion.Curator import Manifest, BLONDE, Snap -from Bastion.CARP import Request, Receipt - - -class PackRequest(Request): - REPORT = PackReport - - def __init__(self, asset, spooled, basis = None, **kwargs): - Request.__init__(self, kwargs.get("action", "pack")) - - self.context['asset'] = str(asset.CURIE) - self.context['halo'] = str(asset.halo) - - if basis: - self.context['detail'] = 'D' - self.context['basis'] = str(kwargs['basis']) - self.context['whence'] = kwargs['whence'].isoformat() - if 'genus' in kwargs: - self.context['genus'] = kwargs['genus'] - else: - self.context['detail'] = 'F' - - -class PackReport(Receipt): - def __init__(self, request, status, doc, obj = None, **kwargs): - Report.__init__(self, request, status, doc, obj, **kwargs) - +from Bastion.CARP import Request, Receipt, ResultStatus class PutRequest(Request): diff --git a/lib/Bastion/Movers/SFTP.py b/lib/Bastion/Movers/SFTP.py index 55b7ced..47f91cc 100644 --- a/lib/Bastion/Movers/SFTP.py +++ b/lib/Bastion/Movers/SFTP.py @@ -50,7 +50,6 @@ def provision(self, *args): repo = self.scurler / ark.site / ark.zone / ark.asset return repo.mkdir(parents = True, exist_ok = True) - def pack(self, asset, basis = None, **kwargs): """ Given a local asset, I package (.tar, .zip, etc) the asset into my scratch (spool) space. @@ -110,7 +109,7 @@ def push(self, asset, basis = None, **kwargs): """ packed = self.pack(asset, basis, **kwargs) - xferrd = self.put(packed.spooled, packed.opts['tag']) + transferred = self.put(packed.spooled, packed.opts['tag']) if transferred: #-- clean up! diff --git a/lib/Bastion/Packers/CARP.py b/lib/Bastion/Packers/CARP.py index 2bff559..83799f2 100644 --- a/lib/Bastion/Packers/CARP.py +++ b/lib/Bastion/Packers/CARP.py @@ -8,9 +8,13 @@ logger = logging.getLogger(__name__) +class PackReport(Report): + def __init__(self, request, status, obj = None, **kwargs): + Report.__init__(self, request, status, obj, **kwargs) -class PackRequest(Bastion.CARP.Request): - def __init__(self, asset, basis = None, **kwargs): + +class PackRequest(Request): + def __init__(self, asset, spooled, basis = None, **kwargs): #-- Which asset will be packed? #-- If differential backup, what basis is used for determining changes? Request.__init__(self, kwargs.get("action", "pack")) @@ -20,10 +24,13 @@ def __init__(self, asset, basis = None, **kwargs): if basis: self.context['detail'] = 'D' - self.context['basis'] = str(basis) + self.context['basis'] = str(kwargs['basis']) self.context['whence'] = kwargs['whence'].isoformat() if 'genus' in kwargs: self.context['genus'] = kwargs['genus'] else: self.context['detail'] = 'F' + def succeeded(self, catalog, *args, **kwargs): + return PackReport(self, ResultStatus.Ok, catalog) + diff --git a/lib/Bastion/Vaults/SFTP.py b/lib/Bastion/Vaults/SFTP.py index c6da1b1..82f7123 100644 --- a/lib/Bastion/Vaults/SFTP.py +++ b/lib/Bastion/Vaults/SFTP.py @@ -85,18 +85,6 @@ def bank(self): #--------------------------------------- #-- BEGIN Bastion.Model.Vault PROTOCOL | #↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ - def provision(self, *args): - """ - provision(ark) - ensures that the site, zone, and asset folders exist. - provision(site, zone, asset_name) - an alias for provision(ark) - """ - if len(args) == 1: - return self._provision_ark( args[0] ) - elif len(args) == 3: - return self._provision_site_zone_asset( args[0], args[1], args[2] ) - else: - raise ValueError - def pack(self, asset, basis = None, **kwargs): """ Given a local asset, I package (.tar, .zip, etc) the asset into my scratch (spool) space.