VOL-2642 Add a Makefile, tests, and virtualenv
Convert common python and robot into a CORDRobot python module that can
be installed via standard python tools (pip) and from PyPI
Uses a fork of https://github.com/rasjani/robotframework-importresource,
which has been backported to Python 3.5 (used in Ubuntu 16.04
executors).
Reformatted and moved keywords so resource files are scoped to a
specific topic.
Added tox tests for library consistency
- flake8
- pylint
- robotframework-lint
- Ran robot against installed library to verify it can be loaded and
used
Added basic lint and tests to whole repo
Removed old tests:
- CORD <6.x era: SanityPhyPOD.robot, and onosUtils.py
Change-Id: I61265a9fb04034a086e20be1f7236a8793a218aa
diff --git a/cord-robot/CORDRobot/CORDDictUtils.py b/cord-robot/CORDRobot/CORDDictUtils.py
new file mode 100644
index 0000000..ea13212
--- /dev/null
+++ b/cord-robot/CORDRobot/CORDDictUtils.py
@@ -0,0 +1,330 @@
+# Copyright 2017-present Open Networking 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
+#
+# 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 __future__ import absolute_import, print_function
+
+import json
+import uuid
+import random
+import yaml
+import glob
+import string
+
+
+class CORDDictUtils(object):
+ @staticmethod
+ def listToDict(alist, intListIndex):
+ dictInfo = alist[int(intListIndex)]
+ return dictInfo
+
+ @staticmethod
+ def jsonToList(strFile, strListName):
+ data = json.loads(open(strFile).read())
+ # print "data...",data
+ dataList = data[strListName]
+ return dataList
+
+ def readFile(self, path, single=True):
+ dataDict = {}
+ for fileName in glob.glob(path):
+ print("Reading ", fileName)
+ data = open(fileName).read()
+ dataDict[fileName] = data
+ if bool(single):
+ return data
+ if not dataDict:
+ print("Failed to find the file!")
+ return None
+ return dataDict
+
+ def readFiles(self, path):
+ return self.readFile(path, single=False)
+
+ """
+ @method compare_dict
+ @Description: validates if contents of dict1 exists in dict2
+ @params: dict1 = input_data entered through api
+ dict2 = retrieved data from GET method
+ returns True if contents of dict1 exists in dict2
+ """
+
+ def compare_dict(self, dict1, dict2):
+ print("input data", dict1)
+ print("get data", dict2)
+ if dict1 is None or dict2 is None:
+ return False
+ if not isinstance(dict1, dict) or not isinstance(dict2, dict):
+ return False
+ if dict1 == {}:
+ return True
+ return self.compare_dict_recursive(dict1, dict2)
+
+ """
+ @method compare_dict_recursive
+ @Description: recursive function to validate if dict1 is a subset of dict2
+ returns True if contents of dict1 exists in dict2
+ """
+
+ def compare_dict_recursive(self, dict1, dict2):
+ for key1, value1 in dict1.items():
+ if key1 not in dict2.keys():
+ print("Missing key", key1, "in dict2")
+ return False
+ value2 = dict2[key1]
+ if isinstance(value1, dict) and isinstance(value2, dict):
+ if not self.compare_dict_recursive(value1, value2):
+ return False
+ else:
+ if value2 != value1:
+ print("Values of key", key1, "in two dicts are not equal")
+ return False
+ return True
+
+ """
+ @method compare_list_of_dicts
+ @Description: validates if contents of dicts in list1 exists in dicts of list2
+ returns True if for each dict in list1, there's a dict in list2 that contains its content
+ """
+
+ def compare_list_of_dicts(self, list1, list2):
+ for dict1 in list1:
+ if dict1 == {}:
+ continue
+ key = dict1.keys()[0]
+ value = dict1[key]
+ dict2 = self.getDictFromListOfDict(list2, key, value)
+ if dict2 == {}:
+ print(
+ "Comparison failed: no dictionaries found in list2 with key",
+ key,
+ "and value",
+ value,
+ )
+ return False
+ if not self.compare_dict(dict1, dict2):
+ print(
+ "Comparison failed: dictionary",
+ dict1,
+ "is not a subset of dictionary",
+ dict2,
+ )
+ return False
+ return True
+
+ """
+ @method search_dictionary
+ @Description: Searches for a key in the provided nested dictionary
+ @params: input_dict = dictionary to be searched
+ search_key = name of the key to be searched for
+ returns two values: search_key value and status of the search.
+ True if found (False when not found)
+
+ """
+
+ def search_dictionary(self, input_dict, search_key):
+ input_keys = input_dict.keys()
+ key_value = ""
+ found = False
+ for key in input_keys:
+ if key == search_key:
+ key_value = input_dict[key]
+ found = True
+ break
+ elif isinstance(input_dict[key], dict):
+ key_value, found = self.search_dictionary(
+ input_dict[key], search_key)
+ if found:
+ break
+ elif isinstance(input_dict[key], list):
+ if not input_dict[key]:
+ found = False
+ break
+ for item in input_dict[key]:
+ if isinstance(item, dict):
+ key_value, found = self.search_dictionary(
+ item, search_key)
+ if found:
+ break
+ return key_value, found
+
+ """
+ @method getDictFromListOfDict
+ return key_value,found
+ @Description: Searches for the dictionary in the provided list of dictionaries
+ that matches the value of the key provided
+ @params : List of dictionaries(getResponse Data from the URL),
+ SearchKey - Key that needs to be searched for (ex: account_num)
+ searchKeyValue - Value of the searchKey (ex: 21)
+ @Returns: Dictionary returned when match found for searchKey with the corresponding
+ searchKeyValue provided
+ """
+
+ def getDictFromListOfDict(self, getJsonDataList,
+ searchKey, searchKeyValue):
+ return_dict = {}
+ result = ""
+ for data in getJsonDataList:
+ print("data", data)
+ return_dict = {}
+ found = False
+ input_keys = data.keys()
+ for key in input_keys:
+ if key == searchKey and str(data[key]) == str(searchKeyValue):
+ found = True
+ return_dict = data
+ print("return_dict", return_dict)
+ break
+ elif isinstance(data[key], dict):
+ result, found = self.search_dictionary(
+ data[key], searchKey)
+ if found and str(result) == str(searchKeyValue):
+ return_dict = data
+ break
+ elif isinstance(data[key], list):
+ for item in data[key]:
+ if isinstance(item, dict):
+ result, found = self.search_dictionary(
+ data[key], searchKey)
+ if found and str(
+ result) == str(searchKeyValue):
+ return_dict = data
+ break
+ if return_dict:
+ break
+ return return_dict
+
+ """
+ @method getFieldValueFromDict
+ @params : search_dict - Dictionary to be searched
+ field - Key to be searched for (ex: account_num)
+ @Returns: Returns the value of the Key that was provided
+ """
+
+ def getFieldValueFromDict(self, search_dict, field):
+ results = ""
+ found = False
+ input_keys = search_dict.keys()
+ for key in input_keys:
+ print("key...", key)
+ if key == field:
+ results = search_dict[key]
+ if not results:
+ found = True
+ break
+ elif isinstance(search_dict[key], dict):
+ results, found = self.search_dictionary(
+ search_dict[key], field)
+ if found:
+ break
+ elif isinstance(search_dict[key], list):
+ if not search_dict[key]:
+ found = False
+ continue
+ for item in search_dict[key]:
+ if isinstance(item, dict):
+ results, found = self.search_dictionary(item, field)
+ if found:
+ break
+ if results:
+ break
+
+ return results
+
+ def setFieldValueInDict(self, input_dict, field, field_value):
+ input_dict[field] = field_value
+ return input_dict
+
+ """
+ @method getAllFieldValues
+ @params : getJsonDataDictList - List of dictionaries to be searched
+ fieldName - Key to be searched for (ex: instance_id)
+ @Returns: Returns the unique value of the Key that was provided
+ """
+
+ def getAllFieldValues(self, getJsonDataDictList, fieldName):
+ value_list = []
+ # uniqValue = "" - this is unused, commented out
+ uniq_list = []
+ for data in getJsonDataDictList:
+ fieldValue = ""
+ fieldValue = self.getFieldValueFromDict(data, fieldName)
+ value_list.append(fieldValue)
+ uniq_list = sorted(set(value_list))
+ if len(uniq_list) == 1:
+ pass # see above, unused?
+ # uniqValue = uniq_list[0]
+ else:
+ print("list of values found for ", fieldName, ";", uniq_list)
+ return fieldValue
+
+ def generate_uuid(self):
+ return uuid.uuid4()
+
+ def generate_random_number_from_blacklist(
+ self, blacklist, min=100, max=500, typeTag=False
+ ):
+ num = None
+ while num in blacklist or num is None:
+ num = random.randrange(int(min), int(max))
+ if typeTag:
+ return num
+ else:
+ return str(num)
+
+ def get_dynamic_resources(self, inputfile, resource):
+ resourceNames = []
+ names = {}
+ dnames = []
+ with open(inputfile, "r") as f:
+ contents = yaml.load(f)
+ resources = contents[resource]
+ for i in resources:
+ resourceNames.append(i["name"])
+ for i in resourceNames:
+ names["name"] = i
+ dnames.append(names.copy())
+ return dnames
+
+ def generate_random_value(
+ self, value, max_length=10, min_int=1, max_int=10000):
+ if value == "string":
+ return "".join(
+ random.choice(string.ascii_lowercase + string.digits)
+ for _ in range(max_length)
+ )
+ if value == "bool":
+ return random.choice([True, False])
+ if value == "int32" or value == "uint32":
+ return random.randint(min_int, max_int)
+ if value == "float":
+ return random.uniform(1, 10)
+ if value == "role":
+ return "admin"
+ if value == "direction":
+ return random.choice(["in", "out"])
+ if value == "flavor":
+ return random.choice(["m1.large", "m1.medium", "m1.small"])
+ if value == "vlan_tag":
+ return random.choice(["555", "1-4096", "ANY"])
+ if value == "ip_address":
+ return ".".join(str(random.randint(0, 255)) for _ in range(4))
+ else:
+ return None
+
+ def generate_random_slice_name(self):
+ random_name = "".join(
+ random.choice(
+ string.ascii_lowercase +
+ string.digits) for _ in range(10))
+ return "testloginbase" + random_name