-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathgenerate_skillet_preview.py
133 lines (112 loc) · 4.53 KB
/
generate_skillet_preview.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 12-12-19 nembery@paloaltonetworks.com
import os
import re
import sys
from lxml import etree
from skilletlib import Panoply
from skilletlib.exceptions import LoginException
from skilletlib.exceptions import SkilletLoaderException
config_source = os.environ.get("skillet_source", "offline")
if config_source == "offline":
# grab our two configs from the environment
base_config_path = os.environ.get("BASE_CONFIG", "")
latest_config_path = os.environ.get("LATEST_CONFIG", "")
with open(base_config_path, "r") as bcf:
base_config = bcf.read()
with open(latest_config_path, "r") as lcf:
latest_config = lcf.read()
p = Panoply()
snippets = p.generate_skillet_from_configs(base_config, latest_config)
else:
# each variable will be present in the environ dict on the 'os' module
username = os.environ.get("TARGET_USERNAME", "admin")
password = os.environ.get("TARGET_PASSWORD", "")
ip = os.environ.get("TARGET_IP", "")
config_source = os.environ.get("CONFIG_SOURCE", "candidate")
snippets = list()
try:
device = Panoply(hostname=ip, api_username=username, api_password=password, debug=False)
if config_source == "specific":
config_version = os.environ.get("CONFIG_VERSION", "-1")
previous_config = device.get_configuration(config_source=config_version)
latest_config = device.get_configuration(config_source="running")
elif config_source == "candidate":
previous_config = device.get_configuration(config_source="running")
latest_config = device.get_configuration(config_source="candidate")
else:
# use previous config by default
previous_config = device.get_configuration(config_source="-1")
latest_config = device.get_configuration(config_source="running")
snippets = device.generate_skillet_from_configs(previous_config, latest_config)
if len(snippets) == 0 and config_source == "candidate":
print("No Candidate Configuration can be found to use to build a skillet!")
sys.exit(2)
elif len(snippets) == 0:
print(f"No changes found between {previous_config} and {latest_config}")
sys.exit(2)
except SkilletLoaderException as se:
print("Error Executing Skillet")
print(se)
sys.exit(1)
except LoginException as le:
print("Error Logging into device")
print(le)
sys.exit(1)
latest_doc = etree.fromstring(latest_config)
print("#" * 80)
print(" ")
print("The following xpaths were found to be modified:")
print(" ")
print("-" * 80)
print(" ")
for s in snippets:
name = s.get("name", "")
snippet_xpath = s.get("xpath")
full_xpath = s.get("full_xpath", "")
print(f'<a href="#{name}">{full_xpath}</a>')
xpath = re.sub("^/config", ".", snippet_xpath)
# parent_element_xpath = '.' + "/".join(xpath.split('/')[:-1])
parent_elements = latest_doc.xpath(xpath)
if not parent_elements:
print("something is broken here")
continue
parent_element = parent_elements[0]
element_string = s.get("element", "")
# find child element index
index = 0
found = False
for child in parent_element:
cs = etree.tostring(child).decode("UTF-8")
cs_stripped = cs.strip()
whitespace_match = re.search(r"(\s+)$", cs)
if whitespace_match:
whitespace = whitespace_match.group()
else:
whitespace = ""
if element_string == cs_stripped:
# found our child index
found = True
parent_element.remove(child)
title = snippet_xpath.replace('"', "'")
wrapped_child_element = etree.fromstring(
f'<span id="{name}" class="text-danger" title="{title}">{element_string}{whitespace}</span>'
)
parent_element.insert(index, wrapped_child_element)
break
index = index + 1
if not found:
print("did not find this, odd")
def rp(match):
return "&nsbp;" * len(match.group())
latest_config_formatted = etree.tostring(latest_doc, pretty_print=True).decode("UTF-8")
latest_config_html = latest_config_formatted.replace("<", "<").replace(">", ">")
fixed_config_html_1 = re.sub(
r'<span id="(.*?)" class="(.*?)" title="(.*?)">', r'<span class="\2" id="\1" title="\3">', latest_config_html
)
fixed_config_html_2 = re.sub(r"</span>", r"</span>", fixed_config_html_1)
print("-" * 80)
print(fixed_config_html_2)
print("-" * 80)
print("#" * 80)
# later gator
sys.exit(0)