Remove SDLWrapper now that it's in xapp frame. 97/2697/1 2.1.4
authorTommy Carpenter <tc677g@att.com>
Fri, 6 Mar 2020 14:41:57 +0000 (09:41 -0500)
committerTommy Carpenter <tc677g@att.com>
Fri, 6 Mar 2020 14:42:26 +0000 (09:42 -0500)
Issue-ID: RIC-228
Change-Id: I1f65d1b5a0029eb544d43c2c9294ef19c07d45d9
Signed-off-by: Tommy Carpenter <tc677g@att.com>
a1/data.py
container-tag.yaml
docs/developer-guide.rst
docs/release-notes.rst
integration_tests/a1mediator/Chart.yaml
setup.py
tests/test_controller.py
tests/test_data.py [deleted file]

index d537d54..45fe5de 100644 (file)
@@ -20,67 +20,24 @@ Represents A1s database and database access functions.
 import os
 import time
 from threading import Thread
-import msgpack
 from mdclogpy import Logger
-from ricsdl.syncstorage import SyncStorage
+from ricxappframe.xapp_sdl import SDLWrapper
 from a1.exceptions import PolicyTypeNotFound, PolicyInstanceNotFound, PolicyTypeAlreadyExists, CantDeleteNonEmptyType
 
-mdc_logger = Logger(name=__name__)
-
 
+# constants
 INSTANCE_DELETE_NO_RESP_TTL = int(os.environ.get("INSTANCE_DELETE_NO_RESP_TTL", 5))
 INSTANCE_DELETE_RESP_TTL = int(os.environ.get("INSTANCE_DELETE_RESP_TTL", 5))
-
 A1NS = "A1m_ns"
-
-
-class SDLWrapper:
-    """
-    This is a wrapper around the expected SDL Python interface.
-    The usage of POLICY_DATA will be replaced with  SDL when SDL for python is available.
-    The eventual SDL API is expected to be very close to what is here.
-
-    We use msgpack for binary (de)serialization: https://msgpack.org/index.html
-    """
-
-    def __init__(self):
-        self.sdl = SyncStorage()
-
-    def set(self, key, value):
-        """set a key"""
-        self.sdl.set(A1NS, {key: msgpack.packb(value, use_bin_type=True)})
-
-    def get(self, key):
-        """get a key"""
-        ret_dict = self.sdl.get(A1NS, {key})
-        if key in ret_dict:
-            return msgpack.unpackb(ret_dict[key], raw=False)
-
-        return None
-
-    def find_and_get(self, prefix):
-        """get all k v pairs that start with prefix"""
-        # note: SDL "*" usage is inconsistent with real python regex, where it would be ".*"
-        ret_dict = self.sdl.find_and_get(A1NS, "{0}*".format(prefix))
-        return {k: msgpack.unpackb(v, raw=False) for k, v in ret_dict.items()}
-
-    def delete(self, key):
-        """ delete a key"""
-        self.sdl.remove(A1NS, {key})
-
-    def healthcheck(self):
-        """checks if the sdl connection is healthy"""
-        return self.sdl.is_active()
-
-
-SDL = SDLWrapper()
-
 TYPE_PREFIX = "a1.policy_type."
 INSTANCE_PREFIX = "a1.policy_instance."
 METADATA_PREFIX = "a1.policy_inst_metadata."
 HANDLER_PREFIX = "a1.policy_handler."
 
 
+mdc_logger = Logger(name=__name__)
+SDL = SDLWrapper()
+
 # Internal helpers
 
 
@@ -123,7 +80,7 @@ def _type_is_valid(policy_type_id):
     """
     check that a type is valid
     """
-    if SDL.get(_generate_type_key(policy_type_id)) is None:
+    if SDL.get(A1NS, _generate_type_key(policy_type_id)) is None:
         raise PolicyTypeNotFound()
 
 
@@ -132,7 +89,7 @@ def _instance_is_valid(policy_type_id, policy_instance_id):
     check that an instance is valid
     """
     _type_is_valid(policy_type_id)
-    if SDL.get(_generate_instance_key(policy_type_id, policy_instance_id)) is None:
+    if SDL.get(A1NS, _generate_instance_key(policy_type_id, policy_instance_id)) is None:
         raise PolicyInstanceNotFound
 
 
@@ -142,7 +99,7 @@ def _get_statuses(policy_type_id, policy_instance_id):
     """
     _instance_is_valid(policy_type_id, policy_instance_id)
     prefixes_for_handler = "{0}{1}.{2}.".format(HANDLER_PREFIX, policy_type_id, policy_instance_id)
-    return list(SDL.find_and_get(prefixes_for_handler).values())
+    return list(SDL.find_and_get(A1NS, prefixes_for_handler).values())
 
 
 def _get_instance_list(policy_type_id):
@@ -151,7 +108,7 @@ def _get_instance_list(policy_type_id):
     """
     _type_is_valid(policy_type_id)
     prefixes_for_type = "{0}{1}.".format(INSTANCE_PREFIX, policy_type_id)
-    instancekeys = SDL.find_and_get(prefixes_for_type).keys()
+    instancekeys = SDL.find_and_get(A1NS, prefixes_for_type).keys()
     return [k.split(prefixes_for_type)[1] for k in instancekeys]
 
 
@@ -160,9 +117,9 @@ def _clear_handlers(policy_type_id, policy_instance_id):
     delete all the handlers for a policy instance
     """
     all_handlers_pref = _generate_handler_prefix(policy_type_id, policy_instance_id)
-    keys = SDL.find_and_get(all_handlers_pref)
+    keys = SDL.find_and_get(A1NS, all_handlers_pref)
     for k in keys:
-        SDL.delete(k)
+        SDL.delete(A1NS, k)
 
 
 def _get_metadata(policy_type_id, policy_instance_id):
@@ -171,7 +128,7 @@ def _get_metadata(policy_type_id, policy_instance_id):
     """
     _instance_is_valid(policy_type_id, policy_instance_id)
     metadata_key = _generate_instance_metadata_key(policy_type_id, policy_instance_id)
-    return SDL.get(metadata_key)
+    return SDL.get(A1NS, metadata_key)
 
 
 def _delete_after(policy_type_id, policy_instance_id, ttl):
@@ -185,8 +142,8 @@ def _delete_after(policy_type_id, policy_instance_id, ttl):
 
     # ready to delete
     _clear_handlers(policy_type_id, policy_instance_id)  # delete all the handlers
-    SDL.delete(_generate_instance_key(policy_type_id, policy_instance_id))  # delete instance
-    SDL.delete(_generate_instance_metadata_key(policy_type_id, policy_instance_id))  # delete instance metadata
+    SDL.delete(A1NS, _generate_instance_key(policy_type_id, policy_instance_id))  # delete instance
+    SDL.delete(A1NS, _generate_instance_metadata_key(policy_type_id, policy_instance_id))  # delete instance metadata
     mdc_logger.debug("type {0} instance {1} deleted".format(policy_type_id, policy_instance_id))
 
 
@@ -197,7 +154,7 @@ def get_type_list():
     """
     retrieve all type ids
     """
-    typekeys = SDL.find_and_get(TYPE_PREFIX).keys()
+    typekeys = SDL.find_and_get(A1NS, TYPE_PREFIX).keys()
     # policy types are ints but they get butchered to strings in the KV
     return [int(k.split(TYPE_PREFIX)[1]) for k in typekeys]
 
@@ -207,9 +164,9 @@ def store_policy_type(policy_type_id, body):
     store a policy type if it doesn't already exist
     """
     key = _generate_type_key(policy_type_id)
-    if SDL.get(key) is not None:
+    if SDL.get(A1NS, key) is not None:
         raise PolicyTypeAlreadyExists()
-    SDL.set(key, body)
+    SDL.set(A1NS, key, body)
 
 
 def delete_policy_type(policy_type_id):
@@ -218,7 +175,7 @@ def delete_policy_type(policy_type_id):
     """
     pil = get_instance_list(policy_type_id)
     if pil == []:  # empty, can delete
-        SDL.delete(_generate_type_key(policy_type_id))
+        SDL.delete(A1NS, _generate_type_key(policy_type_id))
     else:
         raise CantDeleteNonEmptyType()
 
@@ -228,7 +185,7 @@ def get_policy_type(policy_type_id):
     retrieve a type
     """
     _type_is_valid(policy_type_id)
-    return SDL.get(_generate_type_key(policy_type_id))
+    return SDL.get(A1NS, _generate_type_key(policy_type_id))
 
 
 # Instances
@@ -243,13 +200,13 @@ def store_policy_instance(policy_type_id, policy_instance_id, instance):
 
     # store the instance
     key = _generate_instance_key(policy_type_id, policy_instance_id)
-    if SDL.get(key) is not None:
+    if SDL.get(A1NS, key) is not None:
         # Reset the statuses because this is a new policy instance, even if it was overwritten
         _clear_handlers(policy_type_id, policy_instance_id)  # delete all the handlers
-    SDL.set(key, instance)
+    SDL.set(A1NS, key, instance)
 
     metadata_key = _generate_instance_metadata_key(policy_type_id, policy_instance_id)
-    SDL.set(metadata_key, {"created_at": creation_timestamp, "has_been_deleted": False})
+    SDL.set(A1NS, metadata_key, {"created_at": creation_timestamp, "has_been_deleted": False})
 
 
 def get_policy_instance(policy_type_id, policy_instance_id):
@@ -257,7 +214,7 @@ def get_policy_instance(policy_type_id, policy_instance_id):
     Retrieve a policy instance
     """
     _instance_is_valid(policy_type_id, policy_instance_id)
-    return SDL.get(_generate_instance_key(policy_type_id, policy_instance_id))
+    return SDL.get(A1NS, _generate_instance_key(policy_type_id, policy_instance_id))
 
 
 def get_instance_list(policy_type_id):
@@ -279,6 +236,7 @@ def delete_policy_instance(policy_type_id, policy_instance_id):
     metadata_key = _generate_instance_metadata_key(policy_type_id, policy_instance_id)
     existing_metadata = _get_metadata(policy_type_id, policy_instance_id)
     SDL.set(
+        A1NS,
         metadata_key,
         {"created_at": existing_metadata["created_at"], "has_been_deleted": True, "deleted_at": deleted_timestamp},
     )
@@ -306,7 +264,7 @@ def set_policy_instance_status(policy_type_id, policy_instance_id, handler_id, s
     """
     _type_is_valid(policy_type_id)
     _instance_is_valid(policy_type_id, policy_instance_id)
-    SDL.set(_generate_handler_key(policy_type_id, policy_instance_id, handler_id), status)
+    SDL.set(A1NS, _generate_handler_key(policy_type_id, policy_instance_id, handler_id), status)
 
 
 def get_policy_instance_status(policy_type_id, policy_instance_id):
index 65db8b3..2507613 100644 (file)
@@ -1,4 +1,4 @@
 # The Jenkins job uses this string for the tag in the image name
 # for example nexus3.o-ran-sc.org:10004/my-image-name:my-tag
 ---
-tag: 2.1.3
+tag: 2.1.4
index b37b2c4..3e11e19 100644 (file)
@@ -29,9 +29,9 @@ This project follows semver. When changes are made, the versions are in:
 
 4) ``integration_tests/a1mediator/Chart.yaml``
 
-6) ``a1/openapi.yaml`` (this is an API version, not a software version; no need to bump on patch changes)
+5) ``a1/openapi.yaml`` (this is an API version, not a software version; no need to bump on patch changes)
 
-7) in the it/dep repo that contains a1 helm chart, ``values.yaml``, ``Chart.yml``
+6) in the ric-plt repo that contains a1 helm chart, ``values.yaml``, ``Chart.yml``
 
 
 Version bumping rmr
index e39ec3a..0ca68d5 100644 (file)
@@ -14,6 +14,13 @@ and this project adheres to `Semantic Versioning <http://semver.org/>`__.
    :depth: 3
    :local:
 
+[2.1.4] - 3/6/2020
+-------------------
+::
+
+    * SDL Wrapper was moved into the python xapp framework; use it from there instead.
+
+
 [2.1.3] - 2/13/2020
 -------------------
 ::
index 3072609..bc20e74 100644 (file)
@@ -1,4 +1,4 @@
 apiVersion: v1
 description: A1 Helm chart for Kubernetes
 name: a1mediator
-version: 2.1.3
+version: 2.1.4
index db13d40..87ba3ab 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,7 @@ from setuptools import setup, find_packages
 
 setup(
     name="a1",
-    version="2.1.3",
+    version="2.1.4",
     packages=find_packages(exclude=["tests.*", "tests"]),
     author="Tommy Carpenter",
     description="RIC A1 Mediator for policy/intent changes",
@@ -30,9 +30,9 @@ setup(
         "Flask",
         "connexion[swagger-ui]",
         "gevent",
-        "msgpack",
         "rmr>=2.2.0",
         "mdclogpy",
+        "ricxappframe>=0.2.0",
         "ricsdl>=2.0.3,<3.0.0",
     ],
     package_data={"a1": ["openapi.yaml"]},
index bbfe996..0601bbc 100644 (file)
@@ -20,7 +20,7 @@ tests for controller
 import time
 import json
 from rmr.rmr_mocks import rmr_mocks
-from ricsdl.syncstorage import SyncStorage
+from ricxappframe.xapp_sdl import SDLWrapper
 from ricsdl.exceptions import RejectedByBackend, NotConnected, BackendError
 from a1 import a1rmr, data
 
@@ -232,7 +232,8 @@ def _verify_instance_and_status(client, expected_instance, expected_status, expe
 def setup_module():
     """module level setup"""
 
-    data.SDL.sdl = SyncStorage(fake_db_backend="dict")
+    # swap sdl for the fake backend
+    data.SDL = SDLWrapper(use_fake_sdl=True)
 
     def noop():
         pass
@@ -351,7 +352,7 @@ def test_bad_instances(client, monkeypatch, adm_type_good):
 
     # test 503 handlers
 
-    def monkey_set(key, value):
+    def monkey_set(ns, key, value):
         # set a key override function that throws sdl errors on certain keys
         if key == "a1.policy_type.111":
             raise RejectedByBackend()
diff --git a/tests/test_data.py b/tests/test_data.py
deleted file mode 100644 (file)
index b148b23..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-tests data functions
-"""
-# ==================================================================================
-#       Copyright (c) 2019-2020 Nokia
-#       Copyright (c) 2018-2020 AT&T Intellectual Property.
-#
-#   Licensed under the Apache License, Version 2.0 (the "License");
-#   you may not use this file except in compliance with the License.
-#   You may obtain a copy of the License at
-#
-#          http://www.apache.org/licenses/LICENSE-2.0
-#
-#   Unless required by applicable law or agreed to in writing, software
-#   distributed under the License is distributed on an "AS IS" BASIS,
-#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#   See the License for the specific language governing permissions and
-#   limitations under the License.
-# ==================================================================================
-from a1 import data
-from ricsdl.syncstorage import SyncStorage
-
-
-def setup_module():
-    """module level setup"""
-    data.SDL.sdl = SyncStorage(fake_db_backend="dict")
-
-
-def test_sdl_raw():
-    """
-    test raw sdl functions
-    """
-    data.SDL.set("as.df1", "data")
-    data.SDL.set("as.df2", "data2")
-    assert data.SDL.get("as.df1") == "data"
-    assert data.SDL.get("as.df2") == "data2"
-    assert data.SDL.find_and_get("as.df1") == {"as.df1": "data"}
-    assert data.SDL.find_and_get("as.df2") == {"as.df2": "data2"}
-    assert data.SDL.find_and_get("as.df") == {"as.df1": "data", "as.df2": "data2"}
-    assert data.SDL.find_and_get("as.d") == {"as.df1": "data", "as.df2": "data2"}
-    assert data.SDL.find_and_get("as.") == {"as.df1": "data", "as.df2": "data2"}
-    assert data.SDL.find_and_get("asd") == {}
-
-    # delete 1
-    data.SDL.delete("as.df1")
-    assert data.SDL.get("as.df1") is None
-    assert data.SDL.get("as.df2") == "data2"
-
-    # delete 2
-    data.SDL.delete("as.df2")
-    assert data.SDL.get("as.df2") is None
-
-    assert data.SDL.find_and_get("as.df") == {}
-    assert data.SDL.find_and_get("") == {}