Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ sudo: true

python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"

addons:
apt:
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ jsnap2py -i test_interface.conf -o interface.yml
```
For more information please refer [jsnap2py-wiki] (https://github.com/Juniper/jsnapy/wiki/7.-jsnap2py)


Logging:
--------
Log related details will be extracted from "logging.yml" in jsnapy.cfg file.
Default path is "/etc/jsnapy/logging.yml"

CONTRIBUTORS
-------------

Expand Down
2 changes: 1 addition & 1 deletion development.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-r requirements.txt

coverage==4.0.0 # http://nedbatchelder.com/code/coverage/
coverage # http://nedbatchelder.com/code/coverage/
mock==1.0.1 # http://www.voidspace.org.uk/python/mock/
nose # http://nose.readthedocs.org/en/latest/
pep8 # https://github.com/jcrocholl/pep8
Expand Down
14 changes: 7 additions & 7 deletions lib/jnpr/jsnapy/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def expression_evaluator(self, elem_test, op, x_path, id_list, iter, teston,
ele_list = ele_list + [elements.strip()
for elements
in xml_paras.split(',') if
elements.strip() is not '']
elements.strip() != '']
else:
ele_list = [elements.strip()
for elements in ele.split(',')]
Expand All @@ -226,7 +226,7 @@ def expression_evaluator(self, elem_test, op, x_path, id_list, iter, teston,
is_skipped = False
if testop in [
'no-diff', 'list-not-less', 'list-not-more', 'delta']:
if check is True or action is "check":
if check is True or action == "check":
xml1 = self.get_xml_reply(db, snap1)
xml2 = self.get_xml_reply(db, snap2)
if xml2 is None:
Expand Down Expand Up @@ -255,7 +255,7 @@ def expression_evaluator(self, elem_test, op, x_path, id_list, iter, teston,
else:
# if check is used with uni operand test operator then use
# second snapshot file
if check is True or action is "check":
if check is True or action == "check":
pre_snap = self.get_xml_reply(db, snap1)
post_snap = self.get_xml_reply(db, snap2)
else:
Expand Down Expand Up @@ -353,7 +353,7 @@ def expression_builder(self, sub_expr, parent_op=None, **kwargs):
expr = '{0} {1}'.format(parent_op,ret_expr[0])
elif len(ret_expr) >= 1 :
expr = ' {0} '.format(parent_op).join(ret_expr)
if expr is not '':
if expr != '':
expr = '(' +expr+ ')'
return expr

Expand Down Expand Up @@ -383,7 +383,7 @@ def compare_reply(
top_ignore_null = ignore_null_list[0].get('ignore-null')
#### extract all test cases in given test file ####
tests = [t for t in tests if ('iterate' in t or 'item' in t)]
if not len(tests) and (check is True or action is "check"):
if not len(tests) and (check is True or action == "check"):
res = self.compare_xml(op, db, teston, snap1, snap2)
if res is False:
op.no_failed = op.no_failed + 1
Expand Down Expand Up @@ -436,7 +436,7 @@ def compare_reply(
}
final_boolean_expr = self.expression_builder(testcases, None, **kwargs)
#for cases where skip was encountered due to ignore-null
if final_boolean_expr is '' or final_boolean_expr is None or final_boolean_expr == str(None):
if final_boolean_expr == '' or final_boolean_expr is None or final_boolean_expr == str(None):
continue

result = eval(final_boolean_expr)
Expand Down Expand Up @@ -752,7 +752,7 @@ def generate_test_files(

# if check is true then call function to compare two
# snapshots ####
if (check is True or action is "check") and reply_format == 'xml':
if (check is True or action == "check") and reply_format == 'xml':
if db.get('check_from_sqlite') is False:
snapfile2 = self.generate_snap_file(
device,
Expand Down
76 changes: 50 additions & 26 deletions lib/jnpr/jsnapy/jsnapy.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def chk_database(self, config_file, pre_snapfile,
"Specify name of the database.",
extra=self.log_detail)
exit(1)
if check is True or self.args.diff is True or action is "check":
if check == True or self.args.diff == True or action == "check":
if 'compare' in list(d) and d['compare'] is not None:
strr = d['compare']
if not isinstance(strr, str):
Expand Down Expand Up @@ -369,32 +369,21 @@ def get_hosts(self):
sys.exit(1)
self.login(output_file)

def generate_rpc_reply(self, dev, output_file, hostname, config_data):
def generate_rpc_reply(self, dev, output_file, hostname, config_data, test_cases=None):
"""
Generates rpc-reply based on command/rpc given and stores them in snap_files
:param dev: device handler
:param output_file: filename to store snapshots
:param hostname: hostname of device
:param config_data : data of main config file
:param test_cases : list of test cases to be executed
"""
val = None
test_files = []
for tfile in config_data.get('tests'):
if not os.path.isfile(tfile):
tfile = os.path.join(
expanduser(get_path(
'DEFAULT',
'test_file_path')),
tfile)
if os.path.isfile(tfile):
test_file = open(tfile, 'r')
test_files.append(yaml.load(test_file, Loader=yaml.FullLoader))
else:
self.logger.error(
colorama.Fore.RED +
"ERROR!! File %s is not found for taking snapshots" %
tfile, extra=self.log_detail)

if test_cases is not None:
test_files = test_cases
else :
test_files = self.extract_test_cases(config_data)
g = Parser()
for tests in test_files:
val = g.generate_reply(tests, dev, output_file, hostname, self.db)
Expand Down Expand Up @@ -453,6 +442,9 @@ def login(self, output_file):
:param output_file: name of snapshot file
"""
self.host_list = []
config_data = self.main_file
if config_data is not None:
test_cases = self.extract_test_cases(config_data)
if self.args.hostname is None:
host_dict={}
try:
Expand Down Expand Up @@ -537,7 +529,8 @@ def login(self, output_file):
hostname,
username,
password,
output_file
output_file,
test_cases
),
kwargs= key_value
)
Expand All @@ -554,7 +547,7 @@ def login(self, output_file):
self.host_list.append(hostname)
port = self.args.port
key_value = {'port': port} if port is not None else {}
self.connect(hostname, username, password, output_file, **key_value)
self.connect(hostname, username, password, output_file, test_cases, **key_value)

def get_test(self, config_data, hostname, snap_file, post_snap, action):
"""
Expand Down Expand Up @@ -628,7 +621,32 @@ def get_test(self, config_data, hostname, snap_file, post_snap, action):
self.q.put(res)
return res

def connect(self, hostname, username, password, output_file,
def extract_test_cases(self, config_data):
"""
extract the test cases from the file and returns them
:param config_data: the data passed in the config file
:return: the list of testcases
"""
test_files = []
for tfile in config_data.get('tests'):
# tfile gets details of the test/files to be parsed.
if not os.path.isfile(tfile):
tfile = os.path.join(
expanduser(get_path(
'DEFAULT',
'test_file_path')),
tfile)
if os.path.isfile(tfile):
test_file = open(tfile, 'r')
test_files.append(yaml.load(test_file, Loader=yaml.FullLoader))
else:
self.logger.error(
colorama.Fore.RED +
"ERROR!! File %s is not found for taking snapshots" %
tfile, extra=self.log_detail)
return test_files

def connect(self, hostname, username, password, output_file, testcases,
config_data=None, action=None, post_snap=None, **kwargs):
"""
connect to device and calls the function either to generate snapshots
Expand All @@ -647,7 +665,7 @@ def connect(self, hostname, username, password, output_file,
if 'local' in config_data:
self.args.local = True

if (self.args.snap is True or action is "snap") or ( (self.args.snapcheck is True or action is "snapcheck") and self.args.local is not True ):
if (self.args.snap is True or action == "snap") or ( (self.args.snapcheck is True or action == "snapcheck") and self.args.local is not True ):
self.logger.info(
colorama.Fore.BLUE +
"Connecting to device %s ................", hostname, extra=self.log_detail)
Expand Down Expand Up @@ -675,6 +693,7 @@ def connect(self, hostname, username, password, output_file,
username,
password,
output_file,
testcases,
config_data,
action,
post_snap,
Expand All @@ -696,7 +715,8 @@ def connect(self, hostname, username, password, output_file,
dev,
output_file,
hostname,
config_data)
config_data,
testcases)
self.snap_q.put(res)
dev.close()
if self.args.check is True or self.args.snapcheck is True or self.args.diff is True or action in [
Expand Down Expand Up @@ -789,6 +809,7 @@ def multiple_device_details(
self.host_list.append(hostname)
host_dict[hostname] = deepcopy(host)

test_cases = self.extract_test_cases(config_data)
for (hostname, key_value) in iteritems(host_dict):
username = key_value.get('username')
password = key_value.get('passwd')
Expand All @@ -800,6 +821,7 @@ def multiple_device_details(
username,
password,
pre_name,
test_cases,
config_data,
action,
post_name),
Expand Down Expand Up @@ -847,10 +869,10 @@ def extract_data(
except Exception as ex:
self.logger.error(
colorama.Fore.RED +
"ERROR!! config file %s is not present" %
"ERROR!! hosts not defined in file or some error in data" %
ex,
extra=self.log_detail)
raise Exception("config file is not present ", ex)
raise Exception("Incorrect config file or data ", ex)
else:
self.args.local = local
if config_data.__contains__(
Expand Down Expand Up @@ -880,11 +902,13 @@ def extract_data(
#pre_name = hostname + '_' + pre_name if not os.path.isfile(pre_name) else pre_name
# if action is "check":
# post_name= hostname + '_' + post_name if not os.path.isfile(post_name) else post_name
testcase = self.extract_test_cases(config_data)
val.append(self.connect(
hostname,
username,
password,
pre_name,
testcase,
config_data,
action,
post_name,
Expand Down Expand Up @@ -941,7 +965,7 @@ def extract_dev_data(
if 'local' in config_data:
local = True

if action is "snap" or ( action is "snapcheck" and local is False ) :
if action == "snap" or ( action == "snapcheck" and local is False ) :
try:
res.append(self.generate_rpc_reply(
dev,
Expand Down
3 changes: 3 additions & 0 deletions lib/jnpr/jsnapy/logging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ formatters:
format: "%(asctime)s - %(name)s - %(levelname)s - %(hostname)s ............. \n %(message)s"
simple:
format: "%(hostname)s-- %(message)s"
debug:
format: "%(message)s :::: [%(filename)s:%(lineno)d] [%(hostname)s] [%(levelname)s]"
#Helpful in debugging issues in the code
default:
format: "%(message)s"
default_file:
Expand Down
28 changes: 20 additions & 8 deletions lib/jnpr/jsnapy/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2294,10 +2294,11 @@ def no_diff(self, x_path, ele_list, err_mssg,

ele_xpath1 = data1.get(k).xpath(ele_list[0])
ele_xpath2 = data2.get(k).xpath(ele_list[0])
val_list1 = [element.text.strip() for element in ele_xpath1] if len(

val_list1 = [element.text.strip() if element.text else None for element in ele_xpath1] if len(
ele_xpath1) != 0 else None
val_list2 = [element.text.strip() if element.text else None for element in ele_xpath1] if len(
ele_xpath1) != 0 else None
val_list2 = [element.text.strip() for element in ele_xpath2] if len(
ele_xpath2) != 0 else None

predict[ele_list[0]] = val_list1
postdict[ele_list[0]] = val_list2
Expand Down Expand Up @@ -2386,6 +2387,11 @@ def no_diff(self, x_path, ele_list, err_mssg,

def list_not_less(
self, x_path, ele_list, err_mssg, info_mssg, teston, iter, id_list, test_name, xml1, xml2, ignore_null=None):
"""
Checks if all the occurrence of the passed XML element is present in the first snapshot but not present in
second snapshot.
if ignore-null is set to true and element is not present in first snapshot, the test will be skipped
"""
self.print_testmssg("list-not-less")
res = True
tresult = {
Expand All @@ -2406,9 +2412,7 @@ def list_not_less(
id_val = {}

pre_nodes, post_nodes = self._find_xpath(iter, x_path, xml1, xml2)

if not pre_nodes or not post_nodes:

if not pre_nodes:
if self._is_ignore_null(ignore_null):
self.logger_testop.debug(colorama.Fore.YELLOW +
"SKIPPING!! Nodes are not present in given Xpath: <{}>".format(
Expand Down Expand Up @@ -2497,6 +2501,7 @@ def list_not_less(
deepcopy(node_value_failed))

else:
postdict[ele_list[0]] = val1
count_pass = count_pass + 1
message = self._print_message(
info_mssg,
Expand Down Expand Up @@ -2584,6 +2589,11 @@ def list_not_less(

def list_not_more(
self, x_path, ele_list, err_mssg, info_mssg, teston, iter, id_list, test_name, xml1, xml2, ignore_null=None):
"""
Checks if all the occurrence of the passed XML element is present in the second snapshot but not present in
first snapshot.
if ignore-null is set to true and element is not present in second snapshot, the test will be skipped
"""
self.print_testmssg("list-not-more")
res = True
tresult = {
Expand All @@ -2604,7 +2614,8 @@ def list_not_more(
id_val = {}

pre_nodes, post_nodes = self._find_xpath(iter, x_path, xml1, xml2)
if not pre_nodes or not post_nodes:

if not post_nodes:

if self._is_ignore_null(ignore_null):
self.logger_testop.debug(colorama.Fore.YELLOW +
Expand Down Expand Up @@ -2632,7 +2643,7 @@ def list_not_more(
predata = self._get_data(id_list, pre_nodes, ignore_null)
postdata = self._get_data(id_list, post_nodes, ignore_null)

if not predata:
if not postdata:
self.logger_testop.debug(colorama.Fore.YELLOW +
"SKIPPING!! Nodes are not present for given IDs: {}".format(
id_list),
Expand Down Expand Up @@ -2690,6 +2701,7 @@ def list_not_more(
ele_xpath2[0].getparent().tag), extra=self.log_detail)
else:
count_pass = count_pass + 1
predict[ele_list[0]] = val2
message = self._print_message(
info_mssg,
iddict,
Expand Down
4 changes: 2 additions & 2 deletions lib/jnpr/jsnapy/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
# All rights reserved.
#

__version__ = "1.3.2"
DATE = "2018-May-31"
__version__ = "1.3.3.dev0"
DATE = "2018-June-01"
Loading