Skip to content

Commit

Permalink
Add StorageIntegrity
Browse files Browse the repository at this point in the history
Problem:
Latest version of archivist now allows specifying whether the
asset is stored on the DLT or not.

Solution:
An enumerated StorageIntegrity type added to the assets.create()
method to allow specifying either LEDGER or TENANT_STORAGE. If
unspecified TENANT_STORAGE is used.

Signed-off-by: Paul Hewlett <phewlett76@gmail.com>
  • Loading branch information
eccles committed Jul 29, 2021
1 parent 348e5c5 commit f549ae5
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 5 deletions.
15 changes: 13 additions & 2 deletions archivist/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import logging
from typing import Dict, List, Optional
from copy import deepcopy

from archivist.storage_integrity import StorageIntegrity
from archivist.type_aliases import NoneOnError

# pylint:disable=unused-import # To prevent cyclical import errors forward referencing is used
Expand Down Expand Up @@ -107,15 +109,23 @@ class _AssetsClient:
def __init__(self, archivist: "type_helper.Archivist"):
self._archivist = archivist

def create(self, behaviours: List, attrs: Dict, *, confirm: bool = False) -> Asset:
def create(
self,
behaviours: List,
attrs: Dict,
*,
storage_integrity: StorageIntegrity = StorageIntegrity.TENANT_STORAGE,
confirm: bool = False,
) -> Asset:
"""Create asset
Creates asset with defined behaviours and attributes.
Args:
behaviours (list): list of accepted behaviours for this asset.
attrs (dict): attributes of created asset.
confirm (bool): if True wait for asset to be confirmed on DLT.
storage_integrity (StorageIntegrity): store asset on either ledger or tenant storage
confirm (bool): if True wait for asset to be confirmed.
Returns:
:class:`Asset` instance
Expand All @@ -125,6 +135,7 @@ def create(self, behaviours: List, attrs: Dict, *, confirm: bool = False) -> Ass
return self.create_from_data(
{
"behaviours": behaviours,
"storage_integrity": storage_integrity.name,
"attributes": attrs,
},
confirm=confirm,
Expand Down
17 changes: 17 additions & 0 deletions archivist/storage_integrity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Archivist Storage integrity
Enumerated type that allows user to select the storage option when
creating an asset.
"""

from enum import Enum


class StorageIntegrity(Enum):
"""Enumerate storage integrity options"""

#: Assets are stored on the DLT
LEDGER = 1
#: Assets are not stored on the DLT
TENANT_STORAGE = 2
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Jitsuin Archivist
archivist
timestamp
errors
storage_integrity

Indices and tables
==================
Expand Down
10 changes: 10 additions & 0 deletions docs/storage_integrity.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

.. _storage_integrity:

Storage Integrity
-----------------


.. automodule:: archivist.storage_integrity
:members:

23 changes: 20 additions & 3 deletions examples/create_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""

from archivist.archivist import Archivist
from archivist.storage_integrity import StorageIntegrity


def create_asset(arch):
Expand Down Expand Up @@ -39,17 +40,33 @@ def create_asset(arch):
"Attachments",
"RecordEvidence",
]
#
# store asset on the DLT or not. If DLT is not enabled for the user an error will occur if
# StorageIntegrity.LEDGER is specified. If unspecified then TENANT_STORAGE is used
# i.e. not stored on the DLT...
# storage_integrity = StorageIntegrity.TENANT_STORAGE
storage_integrity = StorageIntegrity.LEDGER

# The first argument is the behaviours of the asset
# The second argument is the attributes of the asset
# The third argument is wait for confirmation:
# The third argument indicates whether the asset is stored on the DLT or not.
# If not specifed the asset is not stored on the DLT (TENANT_STORAGE)
# The fourth argument is wait for confirmation:
# If @confirm@ is True then this function will not
# return until the asset is confirmed on the blockchain and ready
# to accept events (or an error occurs)
# After an asset is submitted to the blockchain (submitted),
#
# If storage_integrity = StorageIntegrity.LEDGER:
# After an asset is submitted to the blockchain,
# it will be in the "Pending" status.
# Once it is added to the blockchain, the status will be changed to "Confirmed"
return arch.assets.create(behaviours, attrs=attrs, confirm=True)
#
# If storage_integrity = StorageIntegrity.TENANT_STORAGE:
# The asset is simply stored in the backend (and not on the blockchain)
# and, once stored, the status will be changed to "Confirmed".
return arch.assets.create(
behaviours, attrs, storage_integrity=storage_integrity, confirm=True
)


def main():
Expand Down
72 changes: 72 additions & 0 deletions functests/execassets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
Test assets creation
"""

from copy import deepcopy
from os import environ
from unittest import TestCase

from archivist.archivist import Archivist
from archivist.storage_integrity import StorageIntegrity

# pylint: disable=fixme
# pylint: disable=missing-docstring
# pylint: disable=unused-variable

BEHAVIOURS = [
"RecordEvidence",
"Attachments",
]
ATTRS = {
"arc_firmware_version": "1.0",
"arc_serial_number": "vtl-x4-07",
"arc_description": "Traffic flow control light at A603 North East",
"arc_home_location_identity": "locations/115340cf-f39e-4d43-a2ee-8017d672c6c6",
"arc_display_type": "Traffic light with violation camera",
"some_custom_attribute": "value",
}


class TestAssetCreate(TestCase):
"""
Test Archivist Asset Create method
"""

maxDiff = None

def setUp(cls):
with open(environ["TEST_AUTHTOKEN"]) as fd:
auth = fd.read().strip()
cls.arch = Archivist(environ["TEST_ARCHIVIST"], auth=auth, verify=False)
cls.attrs = deepcopy(ATTRS)

def test_asset_create_tenant_storage(self):
"""
Test asset creation on tenant storage
"""
asset = self.arch.assets.create(
BEHAVIOURS,
self.attrs,
confirm=True,
)
self.assertEqual(
asset["storage_integrity"],
StorageIntegrity.TENANT_STORAGE.name,
msg="Incorrect asset storage integrity",
)

def test_asset_create_ledger(self):
"""
Test asset creation on ledger
"""
asset = self.arch.assets.create(
BEHAVIOURS,
self.attrs,
storage_integrity=StorageIntegrity.LEDGER,
confirm=True,
)
self.assertEqual(
asset["storage_integrity"],
StorageIntegrity.LEDGER.name,
msg="Incorrect asset storage integrity",
)
2 changes: 2 additions & 0 deletions unittests/testassets.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
ROOT,
)
from archivist.errors import ArchivistUnconfirmedError
from archivist.storage_integrity import StorageIntegrity

from .mock_response import MockResponse

Expand Down Expand Up @@ -78,6 +79,7 @@
# TBD: add properties as well
REQUEST = {
"behaviours": BEHAVIOURS,
"storage_integrity": StorageIntegrity.TENANT_STORAGE.name,
"attributes": ATTRS,
}
REQUEST_DATA = json.dumps(REQUEST)
Expand Down
32 changes: 32 additions & 0 deletions unittests/teststorage_integrity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Test storage integrity
"""

# pylint: disable=attribute-defined-outside-init
# pylint: disable=missing-docstring
# pylint: disable=too-few-public-methods

from unittest import TestCase

from archivist.storage_integrity import StorageIntegrity


class TestStorageIntegrity(TestCase):
"""
Test storage integrity for archivist
"""

def test_storage_integrity(self):
"""
Test storage_integrity
"""
self.assertEqual(StorageIntegrity.LEDGER.value, 1, msg="Incorrect value")
self.assertEqual(StorageIntegrity.LEDGER.name, "LEDGER", msg="Incorrect value")
self.assertEqual(
StorageIntegrity.TENANT_STORAGE.value, 2, msg="Incorrect value"
)
self.assertEqual(
StorageIntegrity.TENANT_STORAGE.name,
"TENANT_STORAGE",
msg="Incorrect value",
)

0 comments on commit f549ae5

Please sign in to comment.