Implement unit test for logging 81/10281/6
authorhalil.cakal <halil.cakal@est.tech>
Tue, 17 Jan 2023 09:59:31 +0000 (09:59 +0000)
committerhalil.cakal <halil.cakal@est.tech>
Tue, 24 Jan 2023 16:07:27 +0000 (16:07 +0000)
Implement unit test for ToscaMeta class,
make logger config path relative, change print with new logger,
update README, add logger profile to container start parameters

Issue-ID: NONRTRIC-817
Change-Id: I2acf0bdea24d5bb7810c14663a4937d301011bac
Signed-off-by: halil.cakal <halil.cakal@est.tech>
17 files changed:
catalogue-enhanced-test/build_and_start.sh
catalogue-enhanced/README.md
catalogue-enhanced/api/rapp-catalogue-enhanced.yaml
catalogue-enhanced/pyproject.toml [new file with mode: 0644]
catalogue-enhanced/src/catalogue_manager.py
catalogue-enhanced/src/configuration/log_config.py
catalogue-enhanced/src/main.py
catalogue-enhanced/src/maincommon.py
catalogue-enhanced/src/repository/synchronized_rapp_registry.py
catalogue-enhanced/src/repository/tosca_meta.py [new file with mode: 0644]
catalogue-enhanced/src/start.sh
catalogue-enhanced/src/util.py [deleted file]
catalogue-enhanced/src/var_declaration.py
catalogue-enhanced/tests/test_log_config.py [new file with mode: 0644]
catalogue-enhanced/tests/test_sychronized_rapp_registry.py
catalogue-enhanced/tests/test_tosca_meta.py [new file with mode: 0644]
catalogue-enhanced/tests/unittest_setup.py

index 351f1df..e303a31 100755 (executable)
 # Make sure to run container including args as is this script
 
 print_usage() {
-    echo "Usage: ./build_and_start.sh"
+    echo "Usage: ./build_and_start.sh logger-dev|logger-prod"
     exit 1
 }
 
-if [ $# -ge 1 ]; then
+if [ $# -ne 1 ]; then
+    print_usage
+fi
+
+if [ $1 == "logger-dev" ]; then
+    ACTIVE_LOGGER="-e ACTIVE_LOGGER=dev"
+elif  [ $1 == "logger-prod" ]; then
+    ACTIVE_LOGGER="-e ACTIVE_LOGGER=prod"
+else
     print_usage
 fi
 
@@ -42,4 +50,4 @@ echo "Starting rapp catalogue enhanced..."
 echo "PWD path: "$PWD
 
 #Run the container in interactive mode with host networking driver which allows docker to access localhost, unsecure port 9096, secure port 9196
-docker run --network host --rm -it -p 9096:9096 -p 9196:9196 -e ALLOW_HTTP=true --volume "$PWD/certificate:/usr/src/app/cert" --name rappcatalogueenhanced rapp_catalogue_enhanced_image
+docker run --network host --rm -it -p 9096:9096 -p 9196:9196 -e ALLOW_HTTP=true $ACTIVE_LOGGER --volume "$PWD/certificate:/usr/src/app/cert" --name rappcatalogueenhanced rapp_catalogue_enhanced_image
index 2b493e7..070d345 100644 (file)
@@ -1,6 +1,6 @@
 ## License
 
-Copyright (C) 2022 Nordix Foundation.
+Copyright (C) 2022-2023 Nordix Foundation.
 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
@@ -13,85 +13,92 @@ 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.
 
-# O-RAN-SC Non-RT RIC rAPP Catalogue Enhanced
+# O-RAN-SC Non-RT RIC rApp Catalogue Enhanced
 
 The O-RAN Non-RT RIC rApp Catalogue Enhanced provides an OpenApi 3.0 REST API for services to register/unregister themselves and discover other services.
 
-The O-RAN Non-RT RIC rApp Catalogue Enhanced module supports GET, PUT and DELETE operations (version of the OpenAPI yaml file):
+The O-RAN Non-RT RIC rApp Catalogue Enhanced module supports GET, PUT and DELETE operations. For the specifications please refer to [OpenAPI.yaml] ./api/rapp-catalogue-enhanced.yaml
 
-| Yaml file                    |     Version         |
-| -----------------------------|-------------------- |
-| rapp-catalogue-enhanced.yaml |      1.0.0          |
+|Yaml file                    |     Version         |
+|-----------------------------|-------------------- |
+|rapp-catalogue-enhanced.yaml |      1.0.0          |
 
 The overall folder structure is (relative to the location of this README file):
 
 | Dir              | Description |
 | ---------------- | ----------- |
-|.                 |Dockerfile and README.md |
-|api               |The OpenApi yaml |
-|src               |Python source code |
+|.                 |Dockerfile, container-tag.yaml, nginx.conf, pyproject.toml, tox.ini and README.md |
+|api               |The OpenApi yaml rapp-catalogue-enhanced.yaml |
+|src               |Python source codes includes sub-directories repository, configuration, and start.sh |
 |certificate       |A self-signed certificate and a key |
-|tests             |Pytest fixture and test setup utility |
+|config            |Configuration files such as logger.yaml |
+|csar              |CSAR files such as csar/rapp1.csar |
+|tests             |Python unit tests, Pytest fixture, and test setup utility |
+
+The other folder structure (catalogue-enhanced-test) that includes tests implemented in bash via Curl:
+
+| Dir              | Description |
+| ---------------- | ----------- |
+|.                 |build_and_start.sh, and basic_test.sh |
+|common            |compare_json.py and test_commons.sh are the utilities to compare json files |
+|jsonfiles         |JSON scripts related to API responses |
 
 The application is being implemented in Python programming language.
 
-The rApp Catalogue Enhanced module handles the requests that are defined in the OpenAPI yaml file. All these requests are implemented in the catalogue_manager.py module in the src folder. In addition, a number of utility functions are also supported and implemented by the main.py and payload_logging.py in the source folder.
+The rApp Catalogue Enhanced module handles the requests that are defined in the OpenAPI YAML file. All these requests are implemented in the catalogue_manager.py module in the src folder. The CRUD operations of rApps have been implemented in synchronized blocks so that multi-thread access could not lead to inconsistency of the data. In addition, the logging functions are also supported and implemented by payload_logging.py and log_config.py in the configuration folder.
 
-The section below outlines the supported open api rest-based operations as well as the utility operations.
+The section below outlines the supported OpenAPI rest-based operations as well as the utility operations.
 
 # Ports and certificates
 
-The rApp Catalogue Enhanced module normally opens the port 9096 for http. If a certificate and a key are provided the module will open port 9196 for https instead. The port 9196 is only opened if a valid certificate and key is found.
-The certificate and key shall be placed in the same directory and the directory shall be mounted to /usr/src/app/cert in the container.
+The rApp Catalogue Enhanced module normally opens the port 9096 for HTTP. If a certificate and a key are provided the module will open port 9196 for HTTPS instead. The port 9196 is only opened if a valid certificate and key is found. The certificate and key shall be placed in the same directory and the directory shall be mounted to /usr/src/app/cert in the container.
 
 | Port     | Protocol |
 | -------- | ----- |
 | 9096     | http  |
 | 9196     | https |
 
-The directory certificate contains a self-signed cert. Use the script generate_cert_and_key.sh to generate a new certificate and key. The password of the certificate must be set 'test'.
-The same urls are availables on both the http port 9096 and the https port 9196. If using curl and https, the flag -k shall be given to make curl ignore checking the certificate.
+The directory certificate contains a self-signed cert. Use the script generate_cert_and_key.sh to generate a new certificate and key. The password of the certificate must be set 'test'. The same urls are availables on both the http port 9096 and the https port 9196. If using CURL and HTTPS, the flag -k shall be given to make curl ignore checking the certificate.
 
-# Supported operations in Non-RT RIC rAPP Catalogue Enhanced
+# Supported operations in Non-RT RIC rApp Catalogue Enhanced
 
-For the complete yaml specification, see [OpenAPI.yaml](../api/rapp-catalogue-enhanced.yaml)
+For the complete YAML specification, see [OpenAPI.yaml](./api/rapp-catalogue-enhanced.yaml)
 
 URIs for server:
 
 | Function              | Path and parameters |
 | --------------------- | ------------------- |
-|  GET, Query all rapp ids | localhost:9096/rappcatalogue |
-|  GET, Query rapp by rapp id | localhost:9096/rappcatalogue/<rapp_id> |
-|  GET, Query API list by rapp id and service type | localhost:9096/rappcatalogue/<rapp_id>/<service_type> |
-|  GET, Validate and query TOSCA.meta file content by rapp id | localhost:9096/rappcatalogue/csar/<rapp_id>/toscameta |
-|  PUT, Register rapp | localhost:9096/rappcatalogue/<rapp_id> |
-|  DELETE, Unregister rapp | localhost:9096/rappcatalogue/<rapp_id> |
+|GET, Query all rapp ids | localhost:9096/rappcatalogue |
+|GET, Query rapp by rapp id | localhost:9096/rappcatalogue/<rapp_id> |
+|GET, Query API list by rapp id and service type | localhost:9096/rappcatalogue/<rapp_id>/<service_type> |
+|GET, Validate and query TOSCA.meta file content by rapp id | localhost:9096/rappcatalogue/csar/<rapp_id>/toscameta |
+|PUT, Register rapp | localhost:9096/rappcatalogue/<rapp_id> |
+|DELETE, Unregister rapp | localhost:9096/rappcatalogue/<rapp_id> |
 
 
 # Admin functions
 
 | Function              | Path and parameters |
 | --------------------- | ------------------- |
-|  POST, Delete all existing rapp definitions | localhost:9096/deleteall |
+|POST, Delete all existing rapp definitions | localhost:9096/deleteall |
 
 
 # Start and test of the Non-RT RIC rAPP Catalogue Enhanced
 
 First, download the plt/rappcatalogue repo on gerrit:
+
 git clone "https://gerrit.o-ran-sc.org/r/a/nonrtric/plt/rappcatalogue"
 
-Goto the main directory, 'rappcatalogue/catalogue-enhanced-test'.
-This folder contains a script to build and start the rAPP Catalogue Enhanced (as a container in interactive mode), a script for basic testing as well as json files for the test script.
+Goto the main directory, 'rappcatalogue/catalogue-enhanced-test'. This folder contains a script to build and start the rApp Catalogue Enhanced (as a container in interactive mode), a script for basic testing as well as JSON files for the test script.
 
-Note that test can be performed both using the nonsecure http port and the secure https port.
+Note that test can be performed both using the nonsecure HTTP port and the secure HTTPS port.
 
 Build and start the rApp catalogue enhanced containers:
 
 ./build_and_start.sh
 
-This will build and start the container in interactive mode. The built container only resides in the local docker repository.
-Note, the default port is 9096 for http and 9196 for https. When running the rapp catalogue enhanced as a container, the defualt ports can be re-mapped to any port on the localhost.
+This will build and start the container in interactive mode. The built container only resides in the local docker repository. When running the rApp Catalogue Enhanced as a container, the defualt ports can be re-mapped to any port on the localhost.
 
 In a second terminal, go to the same folder and run the basic test script, basic_test.sh nonsecure|secure.
 
-This script runs a number of tests towards the rapp catalogue enhanced to make sure it works properply.
+This script runs a number of tests towards the rApp Catalogue Enhanced to make sure it works properply.
index 262bcce..cb194b2 100644 (file)
@@ -290,3 +290,10 @@ components:
         application/problem+json:
           schema:
             "$ref": "#/components/schemas/ProblemDetails"
+
+    512-ToscaMetaNotValid:
+      description: 'TOSCA.meta content is not valid'
+      content:
+        application/problem+json:
+          schema:
+            "$ref": "#/components/schemas/ProblemDetails"
diff --git a/catalogue-enhanced/pyproject.toml b/catalogue-enhanced/pyproject.toml
new file mode 100644 (file)
index 0000000..5c41678
--- /dev/null
@@ -0,0 +1,25 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2023 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  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.
+#  ============LICENSE_END=================================================
+#
+
+# pyproject.toml
+[tool.pytest.ini_options]
+pythonpath = [
+  ".", "src", "config",
+]
+testpaths = [
+    "tests",
+]
index b87dcfd..d1a0470 100644 (file)
@@ -23,7 +23,7 @@ from jsonschema import validate
 from var_declaration import synchronized_rapp_registry
 from zipfile import ZipFile
 from io import TextIOWrapper
-from util import ToscametaFormatChecker
+from repository.tosca_meta import ToscaMeta
 
 # Constsants
 APPL_JSON='application/json'
@@ -93,7 +93,6 @@ def query_api_list_by_rapp_id_and_service_type(rappid, servicetype):
       arr_filtered_api_list = [arr_item for arr_item in arr_api_list if arr_item['serviceType'] == service_type]
       return (arr_filtered_api_list, 200)
     except Exception as err:
-      print('An error occured:', err)
       pjson=create_problem_json(None, "The rapp definition is corrupt or missing.", 400, None, rapp_id)
       return Response(json.dumps(pjson), 400, mimetype=APPL_PROB_JSON)
 
@@ -115,12 +114,13 @@ def query_tosca_meta_content_by_rapp_id(rappid):
         else:
           tosca_meta.append(line.strip())
 
-    print('TOSCA.meta content:', tosca_meta)
-    is_valid= validate_tosca_meta_format(tosca_meta)
+    try:
+      validate_tosca_meta_format(tosca_meta)
+      return Response(json.dumps(tosca_meta), 200, mimetype=APPL_JSON)
+    except Exception as err:
+      pjson=create_problem_json(None, err, 512, None, rapp_id)
+      return Response(json.dumps(pjson), 512, mimetype=APPL_PROB_JSON)
 
-    if is_valid== True:
-      content= tosca_meta
-      return Response(json.dumps(content), 200, mimetype=APPL_JSON)
   else:
     pjson=create_problem_json(None, "The rapp does not exist.", 404, None, rapp_id)
     return Response(json.dumps(pjson), 404, mimetype=APPL_PROB_JSON)
@@ -134,16 +134,9 @@ def validate_tosca_meta_format(toscameta):
     csar_tag = split_and_strip(toscameta[1])
     crby_tag = split_and_strip(toscameta[2])
 
-    checker = ToscametaFormatChecker(file_tag, csar_tag, crby_tag)  # util.py: validater
-    result = checker.validate()
-
-    if result == True:  # Log: Validated or NOT
-      print('Validated:', checker)
-    else:
-      print('NOT Validated:', checker)
-    return result
-
-  return False
+    ToscaMeta(file_tag, csar_tag, crby_tag)
+  else:
+    raise ValueError("More lines than expected in Tosca.meta")
 
 # Helper: Splits given string by colon and strip
 def split_and_strip(string):
@@ -159,11 +152,7 @@ def open_zip_and_filter(filename):
       for file_name in file_names:
         if file_name.endswith('TOSCA.meta'):
           return TextIOWrapper(zip_object.open(file_name))  # TextIOWrapper: provides buffered text stream
-
-      pjson=create_problem_json(None, "TOSCA.meta file is corrupt or missing.", 400, None, rapp_id)
-      return Response(json.dumps(pjson), 400, mimetype=APPL_PROB_JSON)
   except Exception as err:
-    print('An error occured:', err)
     pjson=create_problem_json(None, "The CSAR zip content is corrupt or missing.", 400, None, rapp_id)
     return Response(json.dumps(pjson), 400, mimetype=APPL_PROB_JSON)
   finally:
@@ -205,5 +194,7 @@ def create_error_response(code):
       return(create_problem_json(None, "Service unavailable", 503, "The provider is currently unable to handle the request due to a temporary overload", None))
     elif code == 507:
       return(create_problem_json(None, "Insufficient storage", 507, "The method could not be performed on the resource because the provider is unable to store the representation needed to successfully complete the request", None))
+    elif code == 512:
+      return(create_problem_json(None, "Tosca.meta not valid", 512, "TOSCA.meta content is not valid", None))
     else:
       return(create_problem_json(None, "Unknown", code, "Not implemented response code", None))
index 6741760..0840bf2 100644 (file)
@@ -20,19 +20,20 @@ import logging.config
 import os
 import yaml
 
-DEFAULT_LEVEL= logging.INFO
-LOG_CONFIG_PATH= '/usr/src/app/config/logger.yaml'
+from maincommon import active_logger_profile
 
-def init_logger(log_cfg_path= LOG_CONFIG_PATH):
+log= logging.getLogger(active_logger_profile)
 
-  if os.path.exists(log_cfg_path):
-    with open(log_cfg_path, 'r') as cfg_file:
-      try:
-        config = yaml.safe_load(cfg_file.read())
-        logging.config.dictConfig(config)
-      except Exception as e:
-        print('Error with log config file: ', e)
-        logging.basicConfig(level= DEFAULT_LEVEL)
-  else:
-    logging.basicConfig(level= DEFAULT_LEVEL)
-    print('Log config file not found, using INFO log configuration instead')
+class Logger:
+
+  def __init__(self, log_cfg_path= None):
+    if log_cfg_path and os.path.exists(log_cfg_path):
+      with open(log_cfg_path, 'r') as cfg_file:
+        try:
+          config = yaml.safe_load(cfg_file.read())
+          logging.config.dictConfig(config)
+          log.debug('Logging config has initialized with config path: %s and profile: %s', log_cfg_path, active_logger_profile)
+        except Exception as e:
+          log.exception('Error with log-config file: ', e)
+    else:
+      log.debug('No config file found,  using default logger with profile: %s', active_logger_profile)
index 951f4b4..5dda795 100644 (file)
 #
 
 import sys
+import os
 
 from flask import Response, Flask
 from var_declaration import app, synchronized_rapp_registry
-from configuration.log_config import init_logger
+from configuration.log_config import Logger
 
 # App var need to be initialized
 import configuration.payload_logging
 
 # Constants
 TEXT_PLAIN='text/plain'
+LOG_CONFIG_REL_PATH= '/config/logger.yaml'
+
+# Base path for the container as working directory
+WORKDIR= os.environ['WORKDIR']
 
 # Check alive function
 @app.route('/', methods=['GET'])
@@ -47,5 +52,10 @@ if len(sys.argv) >= 2 and isinstance(sys.argv[1], int):
 app.add_api('rapp-catalogue-enhanced.yaml')
 
 if __name__ == '__main__':
-  init_logger()
+
+  if WORKDIR is not None:
+    Logger(WORKDIR+LOG_CONFIG_REL_PATH)
+  else:
+    Logger()
+
   app.run(port=port_number, host="0.0.0.0", threaded=False)
index 20370f1..64c713e 100644 (file)
@@ -1,5 +1,5 @@
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2022 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2022-2023 Nordix Foundation. All rights reserved.
 #  ========================================================================
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
 #
 
 import os
-import sys
 
-# Must exist
-apipath = os.environ['APIPATH']
+# Get ACTIVE_LOGGER env variable, otherwise use the default logger profile
+active_logger_profile= os.getenv('ACTIVE_LOGGER', 'prod')
 
-# Make sure the api path for the open api yaml file is set, otherwise exit
-def check_apipath():
-    if (apipath is None):
-        print("Env APIPATH not set. Exiting....")
-        sys.exit(1)
+# Get APIPATH env variable, otherwise use the default path
+apipath= os.getenv('APIPATH', '/usr/src/app/api')
index 1cfca6c..7331b16 100644 (file)
@@ -19,16 +19,19 @@ from threading import RLock
 import time
 import logging
 
+from maincommon import active_logger_profile
+
+log= logging.getLogger(active_logger_profile)
+
 class SychronizedRappRegistry:
 
   def __init__(self):
     self.lock= RLock()
     self._rapps= {}
-    self.logger= logging.getLogger('dev')
 
   def set_rapp(self, rapp_id, data):
     with self.lock:
-      self.logger.debug('Acquired a lock in set_rapp for the rapp: %s', rapp_id)
+      log.debug('Acquired a lock in set_rapp for the rapp: %s', rapp_id)
       if rapp_id in self._rapps.keys():
         self._rapps[rapp_id]= data
         return 200
@@ -38,24 +41,24 @@ class SychronizedRappRegistry:
 
   def del_rapp(self, rapp_id):
     with self.lock:
-      self.logger.debug('Acquired a lock in del_rapp for the rapp: %s', rapp_id)
+      log.debug('Acquired a lock in del_rapp for the rapp: %s', rapp_id)
       if rapp_id in self._rapps.keys():
         del self._rapps[rapp_id]
         return rapp_id
 
   def get_rapp(self, rapp_id):
     with self.lock:
-      self.logger.debug('Acquired a lock in get_rapp for the rapp: %s', rapp_id)
+      log.debug('Acquired a lock in get_rapp for the rapp: %s', rapp_id)
       if rapp_id in self._rapps.keys():
         return self._rapps[rapp_id]
 
   def clear_rapps(self):
     with self.lock:
-      self.logger.debug('Acquired a lock in clear_rapps')
+      log.debug('Acquired a lock in clear_rapps')
       if self._rapps.keys():
         self._rapps.clear()
 
   def get_rapps_keys(self):
     with self.lock:
-      self.logger.debug('Acquired a lock in get_rapps_keys')
+      log.debug('Acquired a lock in get_rapps_keys')
       return self._rapps.keys()
diff --git a/catalogue-enhanced/src/repository/tosca_meta.py b/catalogue-enhanced/src/repository/tosca_meta.py
new file mode 100644 (file)
index 0000000..5164e14
--- /dev/null
@@ -0,0 +1,54 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2022-2023 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  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.
+#  ============LICENSE_END=================================================
+#
+
+
+class ToscaMeta:
+
+  """
+  A utility class aims to check required fields and their format
+  in TOSCA.meta file in accordance with TOSCA specs.
+  """
+
+  TOSCA= 'TOSCA-Meta-File-Version'
+  CSAR= 'CSAR-Version'
+  CREATEDBY= 'Created-By'
+
+  def __init__(self, file_tag, csar_tag, createdby_tag):
+    self.file_tag = self.is_valid_file_tag(file_tag)
+    self.csar_tag = self.is_valid_csar_tag(csar_tag)
+    self.createdby_tag = self.is_valid_createdby_tag(createdby_tag)
+
+  def is_valid_file_tag(self, file_tag):
+    if file_tag!= ToscaMeta.TOSCA:
+      raise ValueError("File tag should be like TOSCA-Meta-File-Version.")
+
+    return file_tag
+
+  def is_valid_csar_tag(self, csar_tag):
+    if csar_tag!= ToscaMeta.CSAR:
+      raise ValueError("CSAR tag should be like CSAR-Version.")
+
+    return csar_tag
+
+  def is_valid_createdby_tag(self, createdby_tag):
+    if createdby_tag!= ToscaMeta.CREATEDBY:
+      raise ValueError("Created tag should like Created-By.")
+
+    return createdby_tag
+
+  def __str__(self):  # __str__: returns display string
+    return '[TOSCA.meta: %s, %s, %s]' % (self.file_tag, self.csar_tag, self.createdby_tag)
index e425208..6b98bb9 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2022 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2022-2023 Nordix Foundation. All rights reserved.
 #  ========================================================================
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
 export APIPATH=$PWD/api
 echo "APIPATH set to: "$APIPATH
 
+# Set PYTHONPATH for module import
+export PYTHONPATH=$PWD/src
+echo "PYTHONPATH set to: "$PYTHONPATH
+
+# Set WORKDIR for the container
+export WORKDIR=$PWD
+echo "WORKDIR set to: "$WORKDIR
+
 cd src
 
 # Start nginx
diff --git a/catalogue-enhanced/src/util.py b/catalogue-enhanced/src/util.py
deleted file mode 100644 (file)
index 31261fd..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#  ============LICENSE_START===============================================
-#  Copyright (C) 2022 Nordix Foundation. All rights reserved.
-#  ========================================================================
-#  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.
-#  ============LICENSE_END=================================================
-#
-
-class ToscametaFormatChecker:
-  """
-  A utility class aims to check required fields and their format
-  in TOSCA.meta file in accordance with TOSCA specs.
-  """
-  def __init__(self, file_ver, csar_ver, created_by):
-    self.file_ver = file_ver
-    self.csar_ver = csar_ver
-    self.created_by = created_by
-
-  def validate(self):
-
-    if (self.file_ver == 'TOSCA-Meta-File-Version' and
-        self.csar_ver == 'CSAR-Version' and
-        self.created_by == 'Created-By'):
-
-      return True
-    else:
-      return False
-
-  def __str__(self):  # __str__: returns display string
-    return '[TOSCA.meta: %s, %s, %s]' % (self.file_ver, self.csar_ver, self.created_by)
-
-# Unit tests for class: ToscametaFormatChecker
-if __name__ == '__main__':
-  toscameta_t = ToscametaFormatChecker('TOSCA-Meta-File-Version', 'CSAR-Version', 'Created-By')
-  assert toscameta_t.validate() is True
-
-  toscameta_f = ToscametaFormatChecker('TOSCA-Meta-File-Versn', 'CSAR-Version', 'Created-By')
-  assert toscameta_f.validate() is False
index c222f26..8ae6276 100644 (file)
 #  ============LICENSE_END=================================================
 #
 
-from threading import RLock
+import connexion
+
 from maincommon import apipath
 from repository.synchronized_rapp_registry import SychronizedRappRegistry
 
-import os
-import sys
-import connexion
+#Main app
+app= connexion.App(__name__, specification_dir=apipath)
 
 synchronized_rapp_registry= SychronizedRappRegistry()
 
-#Main app
-app = connexion.App(__name__, specification_dir=apipath)
-
diff --git a/catalogue-enhanced/tests/test_log_config.py b/catalogue-enhanced/tests/test_log_config.py
new file mode 100644 (file)
index 0000000..2e79c2c
--- /dev/null
@@ -0,0 +1,70 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2023 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  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.
+#  ============LICENSE_END=================================================
+#
+
+import unittest
+import logging
+import logging.config
+import os
+import yaml
+
+from configuration.log_config import Logger
+
+LOG_CONFIG_PATH= '../config/logger.yaml'
+
+class TestLogConfig(unittest.TestCase):
+  """
+  Unit tests for TestLogConfig class
+  """
+
+  def test_log_config_does_not_exist_then_use_root_logger(self):
+    Logger()
+
+    logger= logging.getLogger()
+    self.assertEqual('root', logger.name)
+    self.assertEqual(logging.WARNING, logger.level)
+
+  def test_log_config_exist_then_logger_dev_exist(self):
+    Logger(LOG_CONFIG_PATH)
+
+    logger= logging.getLogger('dev')
+    self.assertEqual('dev', logger.name)
+
+  def test_log_config_exist_then_logger_dev_handlers_exist(self):
+    Logger(LOG_CONFIG_PATH)
+
+    logger= logging.getLogger('dev')
+    handlers= [handler.name for handler in logger.handlers]
+
+    self.assertEqual(['console', 'file'], handlers)
+
+  def test_log_config_exist_then_check_logger_prod_exists(self):
+    Logger(LOG_CONFIG_PATH)
+
+    logger= logging.getLogger('prod')
+    self.assertEqual('prod', logger.name)
+
+  def test_log_config_exist_then_logger_prod_handlers_exist(self):
+    Logger(LOG_CONFIG_PATH)
+
+    logger= logging.getLogger('prod')
+    handlers= [handler.name for handler in logger.handlers]
+
+    self.assertEqual(['console'], handlers)
+
+if __name__ == '__main__':
+    unittest.main()
+
index 6341b9d..1b2c6ca 100644 (file)
 #
 
 import unittest
-from unittest_setup import setup_env
-from threading import Thread
-
-#Setup env and import paths
-setup_env()
 
-from var_declaration import SychronizedRappRegistry
+from threading import Thread
+from repository.synchronized_rapp_registry import SychronizedRappRegistry
 
 class TestSynchronizedRappRegistry(unittest.TestCase):
   """
diff --git a/catalogue-enhanced/tests/test_tosca_meta.py b/catalogue-enhanced/tests/test_tosca_meta.py
new file mode 100644 (file)
index 0000000..5132757
--- /dev/null
@@ -0,0 +1,51 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2023 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  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.
+#  ============LICENSE_END=================================================
+#
+
+import unittest
+import logging
+import logging.config
+import os
+import yaml
+
+from repository.tosca_meta import ToscaMeta
+
+class TestToscaMeta(unittest.TestCase):
+
+  """
+  Unit tests for ToscaMeta class
+  """
+
+  def test_toscameta_throws_exception_due_invalid_file_tag(self):
+    with self.assertRaises(ValueError) as ve:
+      ToscaMeta('TOSCA-Meta-File-Versio', 'CSAR-Version', 'Created-By')
+
+    self.assertEqual(str(ve.exception), 'File tag should be like TOSCA-Meta-File-Version.')
+
+  def test_toscameta_throws_exception_due_invalid_csar_tag(self):
+    with self.assertRaises(ValueError) as ve:
+      ToscaMeta('TOSCA-Meta-File-Version', 'CSAR-ersion', 'Created-By')
+
+    self.assertEqual(str(ve.exception), 'CSAR tag should be like CSAR-Version.')
+
+  def test_toscameta_throws_exception_due_invalid_createdby_tag(self):
+    with self.assertRaises(ValueError) as ve:
+      ToscaMeta('TOSCA-Meta-File-Version', 'CSAR-Version', 'CreatedBy')
+
+    self.assertEqual(str(ve.exception), 'Created tag should like Created-By.')
+
+if __name__ == '__main__':
+    unittest.main()
index e14d3ae..d3ccdba 100644 (file)
@@ -38,6 +38,7 @@ def setup_env():
   testdata = cwd+"../../catalogue-enhanced-test/jsonfiles/"
 
   #Env var to setup version and host logging
+  os.environ['WORKDIR'] = cwd
   os.environ['APIPATH'] = cwd+"../api/"
   os.environ['REMOTE_HOSTS_LOGGING'] = "ON"