ttp_templates 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ttp_templates-0.1.0/LICENSE +21 -0
- ttp_templates-0.1.0/PKG-INFO +246 -0
- ttp_templates-0.1.0/README.md +229 -0
- ttp_templates-0.1.0/setup.cfg +11 -0
- ttp_templates-0.1.0/setup.py +37 -0
- ttp_templates-0.1.0/test/test_ttp_templates_methods.py +85 -0
- ttp_templates-0.1.0/test/test_yang_ietf_interfaces.py +99 -0
- ttp_templates-0.1.0/ttp_templates/__init__.py +2 -0
- ttp_templates-0.1.0/ttp_templates/ttp_templates.py +109 -0
- ttp_templates-0.1.0/ttp_templates.egg-info/PKG-INFO +246 -0
- ttp_templates-0.1.0/ttp_templates.egg-info/SOURCES.txt +12 -0
- ttp_templates-0.1.0/ttp_templates.egg-info/dependency_links.txt +1 -0
- ttp_templates-0.1.0/ttp_templates.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 apraksim
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ttp_templates
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Template Text Parser Templates collections
|
|
5
|
+
Home-page: https://github.com/dmulyalin/ttp_templates
|
|
6
|
+
Author: Denis Mulyalin
|
|
7
|
+
Author-email: d.mulyalin@gmail.com
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description: # Template Text Parser Templates
|
|
10
|
+
|
|
11
|
+
This repository contains a collection of [TTP](https://github.com/dmulyalin/ttp) templates.
|
|
12
|
+
|
|
13
|
+
If you solved a problem using TTP and feel that your work can be
|
|
14
|
+
useful to other people, feel free to raise an issue or submit pull request to
|
|
15
|
+
include your template(s) in this repository.
|
|
16
|
+
|
|
17
|
+
## Sample usage
|
|
18
|
+
|
|
19
|
+
This example demonstrates how to parse `Test Platform` output for `show run | sec interface` command using `platform/test_platform_show_run_pipe_sec_interface.txt` template.
|
|
20
|
+
<details><summary>Code</summary>
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from ttp_templates import parse_output
|
|
24
|
+
import pprint
|
|
25
|
+
|
|
26
|
+
data = """
|
|
27
|
+
interface GigabitEthernet1/3.251
|
|
28
|
+
description Customer #32148
|
|
29
|
+
encapsulation dot1q 251
|
|
30
|
+
ip address 172.16.33.10 255.255.255.128
|
|
31
|
+
shutdown
|
|
32
|
+
!
|
|
33
|
+
interface GigabitEthernet1/3.251
|
|
34
|
+
description Customer #32148
|
|
35
|
+
encapsulation dot1q 251
|
|
36
|
+
ip address 172.16.33.10 255.255.255.128
|
|
37
|
+
shutdown
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
result = parse_output(
|
|
41
|
+
data=data,
|
|
42
|
+
platform="Test Platform",
|
|
43
|
+
command="show run | sec interface"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
pprint.pprint(result)
|
|
47
|
+
|
|
48
|
+
# prints:
|
|
49
|
+
# [[[{'description': 'Customer #32148',
|
|
50
|
+
# 'disabled': True,
|
|
51
|
+
# 'dot1q': '251',
|
|
52
|
+
# 'interface': 'GigabitEthernet1/3.251',
|
|
53
|
+
# 'ip': '172.16.33.10',
|
|
54
|
+
# 'mask': '255.255.255.128'},
|
|
55
|
+
# {'description': 'Customer #32148',
|
|
56
|
+
# 'disabled': True,
|
|
57
|
+
# 'dot1q': '251',
|
|
58
|
+
# 'interface': 'GigabitEthernet1/3.251',
|
|
59
|
+
# 'ip': '172.16.33.10',
|
|
60
|
+
# 'mask': '255.255.255.128'}]]]
|
|
61
|
+
```
|
|
62
|
+
</details>
|
|
63
|
+
|
|
64
|
+
Sample code to parse `Cisco IOS` output in a structure compatible with `ietf-interfaces` YANG module.
|
|
65
|
+
<details><summary>Code</summary>
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from ttp_templates import get_template
|
|
69
|
+
from ttp import ttp
|
|
70
|
+
import pprint
|
|
71
|
+
|
|
72
|
+
data1 = """
|
|
73
|
+
interface GigabitEthernet1/3.251
|
|
74
|
+
description Customer #32148
|
|
75
|
+
encapsulation dot1q 251
|
|
76
|
+
ip address 172.16.33.10 255.255.255.128
|
|
77
|
+
shutdown
|
|
78
|
+
!
|
|
79
|
+
interface GigabitEthernet1/4
|
|
80
|
+
description vCPEs access control
|
|
81
|
+
ip address 172.16.33.10 255.255.255.128
|
|
82
|
+
!
|
|
83
|
+
"""
|
|
84
|
+
data2 = """
|
|
85
|
+
interface GigabitEthernet1/5
|
|
86
|
+
description Works data
|
|
87
|
+
ip mtu 9000
|
|
88
|
+
!
|
|
89
|
+
interface GigabitEthernet1/7
|
|
90
|
+
description Works data v6
|
|
91
|
+
ipv6 address 2001::1/64
|
|
92
|
+
ipv6 address 2001:1::1/64
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
template = get_template(yang="ietf-interfaces", platform="cisco_ios")
|
|
96
|
+
parser = ttp(template=template)
|
|
97
|
+
|
|
98
|
+
parser.add_input(data1)
|
|
99
|
+
parser.add_input(data2)
|
|
100
|
+
|
|
101
|
+
parser.parse()
|
|
102
|
+
res = parser.result()
|
|
103
|
+
pprint.pprint(res)
|
|
104
|
+
|
|
105
|
+
# prints:
|
|
106
|
+
# [{'comment': '',
|
|
107
|
+
# 'exception': {},
|
|
108
|
+
# 'result': [{'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'down',
|
|
109
|
+
# 'description': 'Customer '
|
|
110
|
+
# '#32148',
|
|
111
|
+
# 'enabled': False,
|
|
112
|
+
# 'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
113
|
+
# 'netmask': '255.255.255.128',
|
|
114
|
+
# 'origin': 'static'}]},
|
|
115
|
+
# 'if-index': 1,
|
|
116
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
117
|
+
# 'name': 'GigabitEthernet1/3.251',
|
|
118
|
+
# 'oper-status': 'unknown',
|
|
119
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
120
|
+
# 'type': 'iana-if-type:ethernetCsmacd'},
|
|
121
|
+
# {'admin-status': 'up',
|
|
122
|
+
# 'description': 'vCPEs '
|
|
123
|
+
# 'access '
|
|
124
|
+
# 'control',
|
|
125
|
+
# 'enabled': True,
|
|
126
|
+
# 'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
127
|
+
# 'netmask': '255.255.255.128',
|
|
128
|
+
# 'origin': 'static'}]},
|
|
129
|
+
# 'if-index': 1,
|
|
130
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
131
|
+
# 'name': 'GigabitEthernet1/4',
|
|
132
|
+
# 'oper-status': 'unknown',
|
|
133
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
134
|
+
# 'type': 'iana-if-type:ethernetCsmacd'}]}},
|
|
135
|
+
# {'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'up',
|
|
136
|
+
# 'description': 'Works '
|
|
137
|
+
# 'data',
|
|
138
|
+
# 'enabled': True,
|
|
139
|
+
# 'ietf-ip:ipv4': {'mtu': 9000},
|
|
140
|
+
# 'if-index': 1,
|
|
141
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
142
|
+
# 'name': 'GigabitEthernet1/5',
|
|
143
|
+
# 'oper-status': 'unknown',
|
|
144
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
145
|
+
# 'type': 'iana-if-type:ethernetCsmacd'},
|
|
146
|
+
# {'admin-status': 'up',
|
|
147
|
+
# 'description': 'Works '
|
|
148
|
+
# 'data '
|
|
149
|
+
# 'v6',
|
|
150
|
+
# 'enabled': True,
|
|
151
|
+
# 'ietf-ip:ipv6': {'address': [{'ip': '2001::1',
|
|
152
|
+
# 'origin': 'static',
|
|
153
|
+
# 'prefix-length': 64},
|
|
154
|
+
# {'ip': '2001:1::1',
|
|
155
|
+
# 'origin': 'static',
|
|
156
|
+
# 'prefix-length': 64}]},
|
|
157
|
+
# 'if-index': 1,
|
|
158
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
159
|
+
# 'name': 'GigabitEthernet1/7',
|
|
160
|
+
# 'oper-status': 'unknown',
|
|
161
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
162
|
+
# 'type': 'iana-if-type:ethernetCsmacd'}]}}],
|
|
163
|
+
# 'valid': {0: True, 1: True}}]
|
|
164
|
+
```
|
|
165
|
+
</details>
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# How templates collections structured
|
|
169
|
+
|
|
170
|
+
This repository contains three collections of templates corresponding to folder names:
|
|
171
|
+
|
|
172
|
+
* `platform` collection - mimics [ntc-templates](https://github.com/networktocode/ntc-templates) API and follows same naming rule
|
|
173
|
+
* `yang` collection - contains templates capable of producing YANG compatible structures out of text data
|
|
174
|
+
* `misc` collection - miscellaneous templates for various use cases organized in folders
|
|
175
|
+
|
|
176
|
+
**Platform collection templates files naming rule**
|
|
177
|
+
|
|
178
|
+
`{{ vendor_os }}_{{ command_with_underscores }}.txt` - lower case only
|
|
179
|
+
|
|
180
|
+
**YANG collection templates files naming rule**
|
|
181
|
+
|
|
182
|
+
`{{ YANG module name }}_{{ platform_name }}.txt` - lower case only
|
|
183
|
+
|
|
184
|
+
**Misc collection templates files naming rule**
|
|
185
|
+
|
|
186
|
+
`{{ usecase folder }}/{{ template name }}.txt` - upper or lower case
|
|
187
|
+
|
|
188
|
+
# API reference
|
|
189
|
+
|
|
190
|
+
`ttp_templates.parse_output`: Function to load template text and parse data provided
|
|
191
|
+
|
|
192
|
+
**Attributes**
|
|
193
|
+
|
|
194
|
+
* data (str) - data to parse
|
|
195
|
+
* path (str) - OS path to template to load
|
|
196
|
+
* platform (str) - name of the platform to load template for
|
|
197
|
+
* command (str) - command to load template for
|
|
198
|
+
* yang (str) - name of YANG module to load template for
|
|
199
|
+
* misc (str) - OS path to template within repository misc folder
|
|
200
|
+
* structure (str) - results structure list, dictionary or flat_list
|
|
201
|
+
* template_vars (dict) - variables to load in template object
|
|
202
|
+
|
|
203
|
+
**Valid combinations of template location**
|
|
204
|
+
|
|
205
|
+
``path`` attribute is always more preferred
|
|
206
|
+
|
|
207
|
+
* ``path="./misc/foo/bar.txt"``
|
|
208
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
209
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
210
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
`ttp_templates.get_template`: Function to locate template file and return it's content
|
|
214
|
+
|
|
215
|
+
**Attributes**
|
|
216
|
+
|
|
217
|
+
* path (str) - OS path to template to load
|
|
218
|
+
* platform (str) - name of the platform to load template for
|
|
219
|
+
* command (str) - command to load template for
|
|
220
|
+
* yang (str) - name of YANG module to load template for
|
|
221
|
+
* misc (str) - OS path to template within repository misc folder
|
|
222
|
+
|
|
223
|
+
**Valid combinations of template location**
|
|
224
|
+
|
|
225
|
+
``path`` attribute is always more preferred
|
|
226
|
+
|
|
227
|
+
* ``path="./misc/foo/bar.txt"``
|
|
228
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
229
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
230
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# Contributions
|
|
234
|
+
Feel free to submit an issue, report a bug or ask a question, feature requests are welcomed.
|
|
235
|
+
|
|
236
|
+
It is always good idea to document as much as you can and give context on the problem you was
|
|
237
|
+
trying to solve. TTP templates have ``<doc>`` tag exactly for that.
|
|
238
|
+
Platform: UNKNOWN
|
|
239
|
+
Classifier: Topic :: Utilities
|
|
240
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
241
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
242
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
243
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
244
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
245
|
+
Classifier: Operating System :: OS Independent
|
|
246
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Template Text Parser Templates
|
|
2
|
+
|
|
3
|
+
This repository contains a collection of [TTP](https://github.com/dmulyalin/ttp) templates.
|
|
4
|
+
|
|
5
|
+
If you solved a problem using TTP and feel that your work can be
|
|
6
|
+
useful to other people, feel free to raise an issue or submit pull request to
|
|
7
|
+
include your template(s) in this repository.
|
|
8
|
+
|
|
9
|
+
## Sample usage
|
|
10
|
+
|
|
11
|
+
This example demonstrates how to parse `Test Platform` output for `show run | sec interface` command using `platform/test_platform_show_run_pipe_sec_interface.txt` template.
|
|
12
|
+
<details><summary>Code</summary>
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from ttp_templates import parse_output
|
|
16
|
+
import pprint
|
|
17
|
+
|
|
18
|
+
data = """
|
|
19
|
+
interface GigabitEthernet1/3.251
|
|
20
|
+
description Customer #32148
|
|
21
|
+
encapsulation dot1q 251
|
|
22
|
+
ip address 172.16.33.10 255.255.255.128
|
|
23
|
+
shutdown
|
|
24
|
+
!
|
|
25
|
+
interface GigabitEthernet1/3.251
|
|
26
|
+
description Customer #32148
|
|
27
|
+
encapsulation dot1q 251
|
|
28
|
+
ip address 172.16.33.10 255.255.255.128
|
|
29
|
+
shutdown
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
result = parse_output(
|
|
33
|
+
data=data,
|
|
34
|
+
platform="Test Platform",
|
|
35
|
+
command="show run | sec interface"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
pprint.pprint(result)
|
|
39
|
+
|
|
40
|
+
# prints:
|
|
41
|
+
# [[[{'description': 'Customer #32148',
|
|
42
|
+
# 'disabled': True,
|
|
43
|
+
# 'dot1q': '251',
|
|
44
|
+
# 'interface': 'GigabitEthernet1/3.251',
|
|
45
|
+
# 'ip': '172.16.33.10',
|
|
46
|
+
# 'mask': '255.255.255.128'},
|
|
47
|
+
# {'description': 'Customer #32148',
|
|
48
|
+
# 'disabled': True,
|
|
49
|
+
# 'dot1q': '251',
|
|
50
|
+
# 'interface': 'GigabitEthernet1/3.251',
|
|
51
|
+
# 'ip': '172.16.33.10',
|
|
52
|
+
# 'mask': '255.255.255.128'}]]]
|
|
53
|
+
```
|
|
54
|
+
</details>
|
|
55
|
+
|
|
56
|
+
Sample code to parse `Cisco IOS` output in a structure compatible with `ietf-interfaces` YANG module.
|
|
57
|
+
<details><summary>Code</summary>
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from ttp_templates import get_template
|
|
61
|
+
from ttp import ttp
|
|
62
|
+
import pprint
|
|
63
|
+
|
|
64
|
+
data1 = """
|
|
65
|
+
interface GigabitEthernet1/3.251
|
|
66
|
+
description Customer #32148
|
|
67
|
+
encapsulation dot1q 251
|
|
68
|
+
ip address 172.16.33.10 255.255.255.128
|
|
69
|
+
shutdown
|
|
70
|
+
!
|
|
71
|
+
interface GigabitEthernet1/4
|
|
72
|
+
description vCPEs access control
|
|
73
|
+
ip address 172.16.33.10 255.255.255.128
|
|
74
|
+
!
|
|
75
|
+
"""
|
|
76
|
+
data2 = """
|
|
77
|
+
interface GigabitEthernet1/5
|
|
78
|
+
description Works data
|
|
79
|
+
ip mtu 9000
|
|
80
|
+
!
|
|
81
|
+
interface GigabitEthernet1/7
|
|
82
|
+
description Works data v6
|
|
83
|
+
ipv6 address 2001::1/64
|
|
84
|
+
ipv6 address 2001:1::1/64
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
template = get_template(yang="ietf-interfaces", platform="cisco_ios")
|
|
88
|
+
parser = ttp(template=template)
|
|
89
|
+
|
|
90
|
+
parser.add_input(data1)
|
|
91
|
+
parser.add_input(data2)
|
|
92
|
+
|
|
93
|
+
parser.parse()
|
|
94
|
+
res = parser.result()
|
|
95
|
+
pprint.pprint(res)
|
|
96
|
+
|
|
97
|
+
# prints:
|
|
98
|
+
# [{'comment': '',
|
|
99
|
+
# 'exception': {},
|
|
100
|
+
# 'result': [{'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'down',
|
|
101
|
+
# 'description': 'Customer '
|
|
102
|
+
# '#32148',
|
|
103
|
+
# 'enabled': False,
|
|
104
|
+
# 'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
105
|
+
# 'netmask': '255.255.255.128',
|
|
106
|
+
# 'origin': 'static'}]},
|
|
107
|
+
# 'if-index': 1,
|
|
108
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
109
|
+
# 'name': 'GigabitEthernet1/3.251',
|
|
110
|
+
# 'oper-status': 'unknown',
|
|
111
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
112
|
+
# 'type': 'iana-if-type:ethernetCsmacd'},
|
|
113
|
+
# {'admin-status': 'up',
|
|
114
|
+
# 'description': 'vCPEs '
|
|
115
|
+
# 'access '
|
|
116
|
+
# 'control',
|
|
117
|
+
# 'enabled': True,
|
|
118
|
+
# 'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
119
|
+
# 'netmask': '255.255.255.128',
|
|
120
|
+
# 'origin': 'static'}]},
|
|
121
|
+
# 'if-index': 1,
|
|
122
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
123
|
+
# 'name': 'GigabitEthernet1/4',
|
|
124
|
+
# 'oper-status': 'unknown',
|
|
125
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
126
|
+
# 'type': 'iana-if-type:ethernetCsmacd'}]}},
|
|
127
|
+
# {'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'up',
|
|
128
|
+
# 'description': 'Works '
|
|
129
|
+
# 'data',
|
|
130
|
+
# 'enabled': True,
|
|
131
|
+
# 'ietf-ip:ipv4': {'mtu': 9000},
|
|
132
|
+
# 'if-index': 1,
|
|
133
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
134
|
+
# 'name': 'GigabitEthernet1/5',
|
|
135
|
+
# 'oper-status': 'unknown',
|
|
136
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
137
|
+
# 'type': 'iana-if-type:ethernetCsmacd'},
|
|
138
|
+
# {'admin-status': 'up',
|
|
139
|
+
# 'description': 'Works '
|
|
140
|
+
# 'data '
|
|
141
|
+
# 'v6',
|
|
142
|
+
# 'enabled': True,
|
|
143
|
+
# 'ietf-ip:ipv6': {'address': [{'ip': '2001::1',
|
|
144
|
+
# 'origin': 'static',
|
|
145
|
+
# 'prefix-length': 64},
|
|
146
|
+
# {'ip': '2001:1::1',
|
|
147
|
+
# 'origin': 'static',
|
|
148
|
+
# 'prefix-length': 64}]},
|
|
149
|
+
# 'if-index': 1,
|
|
150
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
151
|
+
# 'name': 'GigabitEthernet1/7',
|
|
152
|
+
# 'oper-status': 'unknown',
|
|
153
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
154
|
+
# 'type': 'iana-if-type:ethernetCsmacd'}]}}],
|
|
155
|
+
# 'valid': {0: True, 1: True}}]
|
|
156
|
+
```
|
|
157
|
+
</details>
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# How templates collections structured
|
|
161
|
+
|
|
162
|
+
This repository contains three collections of templates corresponding to folder names:
|
|
163
|
+
|
|
164
|
+
* `platform` collection - mimics [ntc-templates](https://github.com/networktocode/ntc-templates) API and follows same naming rule
|
|
165
|
+
* `yang` collection - contains templates capable of producing YANG compatible structures out of text data
|
|
166
|
+
* `misc` collection - miscellaneous templates for various use cases organized in folders
|
|
167
|
+
|
|
168
|
+
**Platform collection templates files naming rule**
|
|
169
|
+
|
|
170
|
+
`{{ vendor_os }}_{{ command_with_underscores }}.txt` - lower case only
|
|
171
|
+
|
|
172
|
+
**YANG collection templates files naming rule**
|
|
173
|
+
|
|
174
|
+
`{{ YANG module name }}_{{ platform_name }}.txt` - lower case only
|
|
175
|
+
|
|
176
|
+
**Misc collection templates files naming rule**
|
|
177
|
+
|
|
178
|
+
`{{ usecase folder }}/{{ template name }}.txt` - upper or lower case
|
|
179
|
+
|
|
180
|
+
# API reference
|
|
181
|
+
|
|
182
|
+
`ttp_templates.parse_output`: Function to load template text and parse data provided
|
|
183
|
+
|
|
184
|
+
**Attributes**
|
|
185
|
+
|
|
186
|
+
* data (str) - data to parse
|
|
187
|
+
* path (str) - OS path to template to load
|
|
188
|
+
* platform (str) - name of the platform to load template for
|
|
189
|
+
* command (str) - command to load template for
|
|
190
|
+
* yang (str) - name of YANG module to load template for
|
|
191
|
+
* misc (str) - OS path to template within repository misc folder
|
|
192
|
+
* structure (str) - results structure list, dictionary or flat_list
|
|
193
|
+
* template_vars (dict) - variables to load in template object
|
|
194
|
+
|
|
195
|
+
**Valid combinations of template location**
|
|
196
|
+
|
|
197
|
+
``path`` attribute is always more preferred
|
|
198
|
+
|
|
199
|
+
* ``path="./misc/foo/bar.txt"``
|
|
200
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
201
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
202
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
`ttp_templates.get_template`: Function to locate template file and return it's content
|
|
206
|
+
|
|
207
|
+
**Attributes**
|
|
208
|
+
|
|
209
|
+
* path (str) - OS path to template to load
|
|
210
|
+
* platform (str) - name of the platform to load template for
|
|
211
|
+
* command (str) - command to load template for
|
|
212
|
+
* yang (str) - name of YANG module to load template for
|
|
213
|
+
* misc (str) - OS path to template within repository misc folder
|
|
214
|
+
|
|
215
|
+
**Valid combinations of template location**
|
|
216
|
+
|
|
217
|
+
``path`` attribute is always more preferred
|
|
218
|
+
|
|
219
|
+
* ``path="./misc/foo/bar.txt"``
|
|
220
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
221
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
222
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# Contributions
|
|
226
|
+
Feel free to submit an issue, report a bug or ask a question, feature requests are welcomed.
|
|
227
|
+
|
|
228
|
+
It is always good idea to document as much as you can and give context on the problem you was
|
|
229
|
+
trying to solve. TTP templates have ``<doc>`` tag exactly for that.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r") as f:
|
|
4
|
+
long_description = f.read()
|
|
5
|
+
|
|
6
|
+
__author__ = "Denis Mulyalin <d.mulyalin@gmail.com>"
|
|
7
|
+
|
|
8
|
+
setup(
|
|
9
|
+
name="ttp_templates",
|
|
10
|
+
version="0.1.0",
|
|
11
|
+
author="Denis Mulyalin",
|
|
12
|
+
author_email="d.mulyalin@gmail.com",
|
|
13
|
+
description="Template Text Parser Templates collections",
|
|
14
|
+
long_description=long_description,
|
|
15
|
+
long_description_content_type="text/markdown",
|
|
16
|
+
url="https://github.com/dmulyalin/ttp_templates",
|
|
17
|
+
packages=find_packages(),
|
|
18
|
+
extras_require={},
|
|
19
|
+
include_package_data=True,
|
|
20
|
+
package_data={
|
|
21
|
+
"ttp_templates": [
|
|
22
|
+
"platform/*.txt",
|
|
23
|
+
"yang/*.txt",
|
|
24
|
+
"misc/*/*.txt"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
data_files=[('', ['LICENSE'])],
|
|
28
|
+
classifiers=[
|
|
29
|
+
"Topic :: Utilities",
|
|
30
|
+
"Programming Language :: Python :: 2.7",
|
|
31
|
+
"Programming Language :: Python :: 3.5",
|
|
32
|
+
"Programming Language :: Python :: 3.6",
|
|
33
|
+
"Programming Language :: Python :: 3.7",
|
|
34
|
+
"License :: OSI Approved :: MIT License",
|
|
35
|
+
"Operating System :: OS Independent",
|
|
36
|
+
]
|
|
37
|
+
)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import pprint
|
|
3
|
+
sys.path.insert(0,'..')
|
|
4
|
+
|
|
5
|
+
from ttp_templates import get_template
|
|
6
|
+
from ttp_templates import parse_output
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_get_template():
|
|
10
|
+
template = get_template(path="yang/ietf-interfaces_cisco_ios.txt")
|
|
11
|
+
# print(template)
|
|
12
|
+
assert isinstance(template, str)
|
|
13
|
+
|
|
14
|
+
# test_get_template()
|
|
15
|
+
|
|
16
|
+
def test_parse_output_platform():
|
|
17
|
+
data = """
|
|
18
|
+
interface GigabitEthernet1/3.251
|
|
19
|
+
description Customer #32148
|
|
20
|
+
encapsulation dot1q 251
|
|
21
|
+
ip address 172.16.33.10 255.255.255.128
|
|
22
|
+
shutdown
|
|
23
|
+
!
|
|
24
|
+
interface GigabitEthernet1/3.251
|
|
25
|
+
description Customer #32148
|
|
26
|
+
encapsulation dot1q 251
|
|
27
|
+
ip address 172.16.33.10 255.255.255.128
|
|
28
|
+
shutdown
|
|
29
|
+
"""
|
|
30
|
+
result = parse_output(
|
|
31
|
+
data=data,
|
|
32
|
+
platform="Test Platform",
|
|
33
|
+
command="show run | sec interface"
|
|
34
|
+
)
|
|
35
|
+
# pprint.pprint(result)
|
|
36
|
+
assert result == [[[{'description': 'Customer #32148',
|
|
37
|
+
'disabled': True,
|
|
38
|
+
'dot1q': '251',
|
|
39
|
+
'interface': 'GigabitEthernet1/3.251',
|
|
40
|
+
'ip': '172.16.33.10',
|
|
41
|
+
'mask': '255.255.255.128'},
|
|
42
|
+
{'description': 'Customer #32148',
|
|
43
|
+
'disabled': True,
|
|
44
|
+
'dot1q': '251',
|
|
45
|
+
'interface': 'GigabitEthernet1/3.251',
|
|
46
|
+
'ip': '172.16.33.10',
|
|
47
|
+
'mask': '255.255.255.128'}]]]
|
|
48
|
+
|
|
49
|
+
# test_parse_output()
|
|
50
|
+
|
|
51
|
+
def test_parse_output_misc():
|
|
52
|
+
data = """
|
|
53
|
+
r1# show run | sec interfaces
|
|
54
|
+
interface GigabitEthernet1
|
|
55
|
+
vrf forwarding MGMT
|
|
56
|
+
ip address 10.223.89.55 255.255.255.0
|
|
57
|
+
negotiation auto
|
|
58
|
+
no mop enabled
|
|
59
|
+
interface GigabitEthernet1
|
|
60
|
+
vrf forwarding MGMT
|
|
61
|
+
ip address 10.223.89.56 255.255.255.0
|
|
62
|
+
negotiation auto
|
|
63
|
+
no mop enabled
|
|
64
|
+
no mop sysid
|
|
65
|
+
"""
|
|
66
|
+
result = parse_output(
|
|
67
|
+
data=data,
|
|
68
|
+
misc="ttp_templates_tests/cisco_ios_interfaces_cfg_per_ip.txt"
|
|
69
|
+
)
|
|
70
|
+
# pprint.pprint(result)
|
|
71
|
+
assert result == [[{'description': 'description',
|
|
72
|
+
'hostname': 'r1',
|
|
73
|
+
'interface': 'GigabitEthernet1',
|
|
74
|
+
'ip': '10.223.89.55',
|
|
75
|
+
'mask': '255.255.255.0',
|
|
76
|
+
'vrf': 'MGMT'},
|
|
77
|
+
{'description': 'description',
|
|
78
|
+
'hostname': 'r1',
|
|
79
|
+
'interface': 'GigabitEthernet1',
|
|
80
|
+
'ip': '10.223.89.56',
|
|
81
|
+
'mask': '255.255.255.0',
|
|
82
|
+
'vrf': 'MGMT'}]]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# test_parse_output_misc()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import pprint
|
|
3
|
+
sys.path.insert(0,'..')
|
|
4
|
+
|
|
5
|
+
from ttp_templates import get_template
|
|
6
|
+
from ttp import ttp
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_cisco_ios():
|
|
10
|
+
data1 = """
|
|
11
|
+
interface GigabitEthernet1/3.251
|
|
12
|
+
description Customer #32148
|
|
13
|
+
encapsulation dot1q 251
|
|
14
|
+
ip address 172.16.33.10 255.255.255.128
|
|
15
|
+
shutdown
|
|
16
|
+
!
|
|
17
|
+
interface GigabitEthernet1/4
|
|
18
|
+
description vCPEs access control
|
|
19
|
+
ip address 172.16.33.10 255.255.255.128
|
|
20
|
+
!
|
|
21
|
+
"""
|
|
22
|
+
data2 = """
|
|
23
|
+
interface GigabitEthernet1/5
|
|
24
|
+
description Works data
|
|
25
|
+
ip mtu 9000
|
|
26
|
+
!
|
|
27
|
+
interface GigabitEthernet1/7
|
|
28
|
+
description Works data v6
|
|
29
|
+
ipv6 address 2001::1/64
|
|
30
|
+
ipv6 address 2001:1::1/64
|
|
31
|
+
"""
|
|
32
|
+
template = get_template(yang="ietf-interfaces", platform="cisco_ios")
|
|
33
|
+
# print(template)
|
|
34
|
+
parser = ttp(template=template)
|
|
35
|
+
parser.add_input(data1)
|
|
36
|
+
parser.add_input(data2)
|
|
37
|
+
parser.parse()
|
|
38
|
+
res = parser.result()
|
|
39
|
+
# pprint.pprint(res)
|
|
40
|
+
assert res == [{'comment': '',
|
|
41
|
+
'exception': {},
|
|
42
|
+
'result': [{'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'down',
|
|
43
|
+
'description': 'Customer '
|
|
44
|
+
'#32148',
|
|
45
|
+
'enabled': False,
|
|
46
|
+
'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
47
|
+
'netmask': '255.255.255.128',
|
|
48
|
+
'origin': 'static'}]},
|
|
49
|
+
'if-index': 1,
|
|
50
|
+
'link-up-down-trap-enable': 'enabled',
|
|
51
|
+
'name': 'GigabitEthernet1/3.251',
|
|
52
|
+
'oper-status': 'unknown',
|
|
53
|
+
'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
54
|
+
'type': 'iana-if-type:ethernetCsmacd'},
|
|
55
|
+
{'admin-status': 'up',
|
|
56
|
+
'description': 'vCPEs '
|
|
57
|
+
'access '
|
|
58
|
+
'control',
|
|
59
|
+
'enabled': True,
|
|
60
|
+
'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
61
|
+
'netmask': '255.255.255.128',
|
|
62
|
+
'origin': 'static'}]},
|
|
63
|
+
'if-index': 1,
|
|
64
|
+
'link-up-down-trap-enable': 'enabled',
|
|
65
|
+
'name': 'GigabitEthernet1/4',
|
|
66
|
+
'oper-status': 'unknown',
|
|
67
|
+
'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
68
|
+
'type': 'iana-if-type:ethernetCsmacd'}]}},
|
|
69
|
+
{'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'up',
|
|
70
|
+
'description': 'Works '
|
|
71
|
+
'data',
|
|
72
|
+
'enabled': True,
|
|
73
|
+
'ietf-ip:ipv4': {'mtu': 9000},
|
|
74
|
+
'if-index': 1,
|
|
75
|
+
'link-up-down-trap-enable': 'enabled',
|
|
76
|
+
'name': 'GigabitEthernet1/5',
|
|
77
|
+
'oper-status': 'unknown',
|
|
78
|
+
'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
79
|
+
'type': 'iana-if-type:ethernetCsmacd'},
|
|
80
|
+
{'admin-status': 'up',
|
|
81
|
+
'description': 'Works '
|
|
82
|
+
'data '
|
|
83
|
+
'v6',
|
|
84
|
+
'enabled': True,
|
|
85
|
+
'ietf-ip:ipv6': {'address': [{'ip': '2001::1',
|
|
86
|
+
'origin': 'static',
|
|
87
|
+
'prefix-length': 64},
|
|
88
|
+
{'ip': '2001:1::1',
|
|
89
|
+
'origin': 'static',
|
|
90
|
+
'prefix-length': 64}]},
|
|
91
|
+
'if-index': 1,
|
|
92
|
+
'link-up-down-trap-enable': 'enabled',
|
|
93
|
+
'name': 'GigabitEthernet1/7',
|
|
94
|
+
'oper-status': 'unknown',
|
|
95
|
+
'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
96
|
+
'type': 'iana-if-type:ethernetCsmacd'}]}}],
|
|
97
|
+
'valid': {0: True, 1: True}}]
|
|
98
|
+
|
|
99
|
+
# test_cisco_ios()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from ttp import ttp
|
|
3
|
+
from typing import Optional, List, Dict
|
|
4
|
+
|
|
5
|
+
def get_template(
|
|
6
|
+
platform: Optional[str] = None,
|
|
7
|
+
command: Optional[str] = None,
|
|
8
|
+
yang: Optional[str] = None,
|
|
9
|
+
misc: Optional[str] = None,
|
|
10
|
+
path: Optional[str] = None
|
|
11
|
+
):
|
|
12
|
+
"""
|
|
13
|
+
Function to locate template file and return it's content
|
|
14
|
+
|
|
15
|
+
**Attributes**
|
|
16
|
+
|
|
17
|
+
* path (str) - OS path to template to load
|
|
18
|
+
* platform (str) - name of the platform to load template for
|
|
19
|
+
* command (str) - command to load template for
|
|
20
|
+
* yang (str) - name of YANG module to load template for
|
|
21
|
+
* misc (str) - OS path to template within repository misc folder
|
|
22
|
+
|
|
23
|
+
**Valid combinations of template location**
|
|
24
|
+
|
|
25
|
+
``path`` attribute is always more preferred
|
|
26
|
+
|
|
27
|
+
* ``path="./misc/foo/bar.txt"``
|
|
28
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
29
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
30
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
31
|
+
"""
|
|
32
|
+
# form path to template file
|
|
33
|
+
if path:
|
|
34
|
+
pass
|
|
35
|
+
elif platform and command:
|
|
36
|
+
platform = platform.lower()
|
|
37
|
+
command = command.lower()
|
|
38
|
+
command = command.replace("|", "pipe")
|
|
39
|
+
for symbol in [" "]:
|
|
40
|
+
platform = platform.replace(symbol, "_")
|
|
41
|
+
command = command.replace(symbol, "_")
|
|
42
|
+
path = "platform/{}_{}.txt".format(platform, command)
|
|
43
|
+
elif platform and yang:
|
|
44
|
+
platform = platform.lower()
|
|
45
|
+
yang = yang.lower()
|
|
46
|
+
for symbol in [" "]:
|
|
47
|
+
platform = platform.replace(symbol, "_")
|
|
48
|
+
yang = yang.replace(symbol, "_")
|
|
49
|
+
path = "yang/{}_{}.txt".format(yang, platform)
|
|
50
|
+
elif misc:
|
|
51
|
+
path = "misc/{}".format(misc)
|
|
52
|
+
else:
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
template_filename = os.path.join(os.path.dirname(__file__), path)
|
|
56
|
+
|
|
57
|
+
# open template file and return content
|
|
58
|
+
with open(template_filename, "r") as f:
|
|
59
|
+
return f.read()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def parse_output(
|
|
63
|
+
data: str,
|
|
64
|
+
platform: Optional[str] = None,
|
|
65
|
+
command: Optional[str] = None,
|
|
66
|
+
path: Optional[str] = None,
|
|
67
|
+
yang: Optional[str] = None,
|
|
68
|
+
misc: Optional[str] = None,
|
|
69
|
+
structure: Optional[str] = "list",
|
|
70
|
+
template_vars: Optional[Dict] = {}
|
|
71
|
+
):
|
|
72
|
+
"""
|
|
73
|
+
Function to load template text and parse data provided
|
|
74
|
+
|
|
75
|
+
**Attributes**
|
|
76
|
+
|
|
77
|
+
* data (str) - data to parse
|
|
78
|
+
* path (str) - OS path to template to load
|
|
79
|
+
* platform (str) - name of the platform to load template for
|
|
80
|
+
* command (str) - command to load template for
|
|
81
|
+
* yang (str) - name of YANG module to load template for
|
|
82
|
+
* misc (str) - OS path to template within repository misc folder
|
|
83
|
+
* structure (str) - results structure list, dictionary or flat_list
|
|
84
|
+
* template_vars (dict) - variables to load in template object
|
|
85
|
+
|
|
86
|
+
**Valid combinations of template location**
|
|
87
|
+
|
|
88
|
+
``path`` attribute is always more preferred
|
|
89
|
+
|
|
90
|
+
* ``path="./misc/foo/bar.txt"``
|
|
91
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
92
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
93
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
94
|
+
"""
|
|
95
|
+
# get template text
|
|
96
|
+
template = get_template(
|
|
97
|
+
platform=platform,
|
|
98
|
+
command=command,
|
|
99
|
+
path=path,
|
|
100
|
+
yang=yang,
|
|
101
|
+
misc=misc
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# create parser object
|
|
105
|
+
parser = ttp(data=data, template=template, vars=template_vars)
|
|
106
|
+
|
|
107
|
+
# parse and return results
|
|
108
|
+
parser.parse(one=True)
|
|
109
|
+
return parser.result(structure=structure)
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ttp-templates
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Template Text Parser Templates collections
|
|
5
|
+
Home-page: https://github.com/dmulyalin/ttp_templates
|
|
6
|
+
Author: Denis Mulyalin
|
|
7
|
+
Author-email: d.mulyalin@gmail.com
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description: # Template Text Parser Templates
|
|
10
|
+
|
|
11
|
+
This repository contains a collection of [TTP](https://github.com/dmulyalin/ttp) templates.
|
|
12
|
+
|
|
13
|
+
If you solved a problem using TTP and feel that your work can be
|
|
14
|
+
useful to other people, feel free to raise an issue or submit pull request to
|
|
15
|
+
include your template(s) in this repository.
|
|
16
|
+
|
|
17
|
+
## Sample usage
|
|
18
|
+
|
|
19
|
+
This example demonstrates how to parse `Test Platform` output for `show run | sec interface` command using `platform/test_platform_show_run_pipe_sec_interface.txt` template.
|
|
20
|
+
<details><summary>Code</summary>
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from ttp_templates import parse_output
|
|
24
|
+
import pprint
|
|
25
|
+
|
|
26
|
+
data = """
|
|
27
|
+
interface GigabitEthernet1/3.251
|
|
28
|
+
description Customer #32148
|
|
29
|
+
encapsulation dot1q 251
|
|
30
|
+
ip address 172.16.33.10 255.255.255.128
|
|
31
|
+
shutdown
|
|
32
|
+
!
|
|
33
|
+
interface GigabitEthernet1/3.251
|
|
34
|
+
description Customer #32148
|
|
35
|
+
encapsulation dot1q 251
|
|
36
|
+
ip address 172.16.33.10 255.255.255.128
|
|
37
|
+
shutdown
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
result = parse_output(
|
|
41
|
+
data=data,
|
|
42
|
+
platform="Test Platform",
|
|
43
|
+
command="show run | sec interface"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
pprint.pprint(result)
|
|
47
|
+
|
|
48
|
+
# prints:
|
|
49
|
+
# [[[{'description': 'Customer #32148',
|
|
50
|
+
# 'disabled': True,
|
|
51
|
+
# 'dot1q': '251',
|
|
52
|
+
# 'interface': 'GigabitEthernet1/3.251',
|
|
53
|
+
# 'ip': '172.16.33.10',
|
|
54
|
+
# 'mask': '255.255.255.128'},
|
|
55
|
+
# {'description': 'Customer #32148',
|
|
56
|
+
# 'disabled': True,
|
|
57
|
+
# 'dot1q': '251',
|
|
58
|
+
# 'interface': 'GigabitEthernet1/3.251',
|
|
59
|
+
# 'ip': '172.16.33.10',
|
|
60
|
+
# 'mask': '255.255.255.128'}]]]
|
|
61
|
+
```
|
|
62
|
+
</details>
|
|
63
|
+
|
|
64
|
+
Sample code to parse `Cisco IOS` output in a structure compatible with `ietf-interfaces` YANG module.
|
|
65
|
+
<details><summary>Code</summary>
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from ttp_templates import get_template
|
|
69
|
+
from ttp import ttp
|
|
70
|
+
import pprint
|
|
71
|
+
|
|
72
|
+
data1 = """
|
|
73
|
+
interface GigabitEthernet1/3.251
|
|
74
|
+
description Customer #32148
|
|
75
|
+
encapsulation dot1q 251
|
|
76
|
+
ip address 172.16.33.10 255.255.255.128
|
|
77
|
+
shutdown
|
|
78
|
+
!
|
|
79
|
+
interface GigabitEthernet1/4
|
|
80
|
+
description vCPEs access control
|
|
81
|
+
ip address 172.16.33.10 255.255.255.128
|
|
82
|
+
!
|
|
83
|
+
"""
|
|
84
|
+
data2 = """
|
|
85
|
+
interface GigabitEthernet1/5
|
|
86
|
+
description Works data
|
|
87
|
+
ip mtu 9000
|
|
88
|
+
!
|
|
89
|
+
interface GigabitEthernet1/7
|
|
90
|
+
description Works data v6
|
|
91
|
+
ipv6 address 2001::1/64
|
|
92
|
+
ipv6 address 2001:1::1/64
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
template = get_template(yang="ietf-interfaces", platform="cisco_ios")
|
|
96
|
+
parser = ttp(template=template)
|
|
97
|
+
|
|
98
|
+
parser.add_input(data1)
|
|
99
|
+
parser.add_input(data2)
|
|
100
|
+
|
|
101
|
+
parser.parse()
|
|
102
|
+
res = parser.result()
|
|
103
|
+
pprint.pprint(res)
|
|
104
|
+
|
|
105
|
+
# prints:
|
|
106
|
+
# [{'comment': '',
|
|
107
|
+
# 'exception': {},
|
|
108
|
+
# 'result': [{'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'down',
|
|
109
|
+
# 'description': 'Customer '
|
|
110
|
+
# '#32148',
|
|
111
|
+
# 'enabled': False,
|
|
112
|
+
# 'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
113
|
+
# 'netmask': '255.255.255.128',
|
|
114
|
+
# 'origin': 'static'}]},
|
|
115
|
+
# 'if-index': 1,
|
|
116
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
117
|
+
# 'name': 'GigabitEthernet1/3.251',
|
|
118
|
+
# 'oper-status': 'unknown',
|
|
119
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
120
|
+
# 'type': 'iana-if-type:ethernetCsmacd'},
|
|
121
|
+
# {'admin-status': 'up',
|
|
122
|
+
# 'description': 'vCPEs '
|
|
123
|
+
# 'access '
|
|
124
|
+
# 'control',
|
|
125
|
+
# 'enabled': True,
|
|
126
|
+
# 'ietf-ip:ipv4': {'address': [{'ip': '172.16.33.10',
|
|
127
|
+
# 'netmask': '255.255.255.128',
|
|
128
|
+
# 'origin': 'static'}]},
|
|
129
|
+
# 'if-index': 1,
|
|
130
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
131
|
+
# 'name': 'GigabitEthernet1/4',
|
|
132
|
+
# 'oper-status': 'unknown',
|
|
133
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
134
|
+
# 'type': 'iana-if-type:ethernetCsmacd'}]}},
|
|
135
|
+
# {'ietf-interfaces:interfaces': {'interface': [{'admin-status': 'up',
|
|
136
|
+
# 'description': 'Works '
|
|
137
|
+
# 'data',
|
|
138
|
+
# 'enabled': True,
|
|
139
|
+
# 'ietf-ip:ipv4': {'mtu': 9000},
|
|
140
|
+
# 'if-index': 1,
|
|
141
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
142
|
+
# 'name': 'GigabitEthernet1/5',
|
|
143
|
+
# 'oper-status': 'unknown',
|
|
144
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
145
|
+
# 'type': 'iana-if-type:ethernetCsmacd'},
|
|
146
|
+
# {'admin-status': 'up',
|
|
147
|
+
# 'description': 'Works '
|
|
148
|
+
# 'data '
|
|
149
|
+
# 'v6',
|
|
150
|
+
# 'enabled': True,
|
|
151
|
+
# 'ietf-ip:ipv6': {'address': [{'ip': '2001::1',
|
|
152
|
+
# 'origin': 'static',
|
|
153
|
+
# 'prefix-length': 64},
|
|
154
|
+
# {'ip': '2001:1::1',
|
|
155
|
+
# 'origin': 'static',
|
|
156
|
+
# 'prefix-length': 64}]},
|
|
157
|
+
# 'if-index': 1,
|
|
158
|
+
# 'link-up-down-trap-enable': 'enabled',
|
|
159
|
+
# 'name': 'GigabitEthernet1/7',
|
|
160
|
+
# 'oper-status': 'unknown',
|
|
161
|
+
# 'statistics': {'discontinuity-time': '1970-01-01T00:00:00+00:00'},
|
|
162
|
+
# 'type': 'iana-if-type:ethernetCsmacd'}]}}],
|
|
163
|
+
# 'valid': {0: True, 1: True}}]
|
|
164
|
+
```
|
|
165
|
+
</details>
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# How templates collections structured
|
|
169
|
+
|
|
170
|
+
This repository contains three collections of templates corresponding to folder names:
|
|
171
|
+
|
|
172
|
+
* `platform` collection - mimics [ntc-templates](https://github.com/networktocode/ntc-templates) API and follows same naming rule
|
|
173
|
+
* `yang` collection - contains templates capable of producing YANG compatible structures out of text data
|
|
174
|
+
* `misc` collection - miscellaneous templates for various use cases organized in folders
|
|
175
|
+
|
|
176
|
+
**Platform collection templates files naming rule**
|
|
177
|
+
|
|
178
|
+
`{{ vendor_os }}_{{ command_with_underscores }}.txt` - lower case only
|
|
179
|
+
|
|
180
|
+
**YANG collection templates files naming rule**
|
|
181
|
+
|
|
182
|
+
`{{ YANG module name }}_{{ platform_name }}.txt` - lower case only
|
|
183
|
+
|
|
184
|
+
**Misc collection templates files naming rule**
|
|
185
|
+
|
|
186
|
+
`{{ usecase folder }}/{{ template name }}.txt` - upper or lower case
|
|
187
|
+
|
|
188
|
+
# API reference
|
|
189
|
+
|
|
190
|
+
`ttp_templates.parse_output`: Function to load template text and parse data provided
|
|
191
|
+
|
|
192
|
+
**Attributes**
|
|
193
|
+
|
|
194
|
+
* data (str) - data to parse
|
|
195
|
+
* path (str) - OS path to template to load
|
|
196
|
+
* platform (str) - name of the platform to load template for
|
|
197
|
+
* command (str) - command to load template for
|
|
198
|
+
* yang (str) - name of YANG module to load template for
|
|
199
|
+
* misc (str) - OS path to template within repository misc folder
|
|
200
|
+
* structure (str) - results structure list, dictionary or flat_list
|
|
201
|
+
* template_vars (dict) - variables to load in template object
|
|
202
|
+
|
|
203
|
+
**Valid combinations of template location**
|
|
204
|
+
|
|
205
|
+
``path`` attribute is always more preferred
|
|
206
|
+
|
|
207
|
+
* ``path="./misc/foo/bar.txt"``
|
|
208
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
209
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
210
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
`ttp_templates.get_template`: Function to locate template file and return it's content
|
|
214
|
+
|
|
215
|
+
**Attributes**
|
|
216
|
+
|
|
217
|
+
* path (str) - OS path to template to load
|
|
218
|
+
* platform (str) - name of the platform to load template for
|
|
219
|
+
* command (str) - command to load template for
|
|
220
|
+
* yang (str) - name of YANG module to load template for
|
|
221
|
+
* misc (str) - OS path to template within repository misc folder
|
|
222
|
+
|
|
223
|
+
**Valid combinations of template location**
|
|
224
|
+
|
|
225
|
+
``path`` attribute is always more preferred
|
|
226
|
+
|
|
227
|
+
* ``path="./misc/foo/bar.txt"``
|
|
228
|
+
* ``platfrom="cisco_ios", command="show version"``
|
|
229
|
+
* ``yang="ietf-interfaces", platform="cisco_ios"``
|
|
230
|
+
* ``misc="foo_folder/bar_template.txt"``
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# Contributions
|
|
234
|
+
Feel free to submit an issue, report a bug or ask a question, feature requests are welcomed.
|
|
235
|
+
|
|
236
|
+
It is always good idea to document as much as you can and give context on the problem you was
|
|
237
|
+
trying to solve. TTP templates have ``<doc>`` tag exactly for that.
|
|
238
|
+
Platform: UNKNOWN
|
|
239
|
+
Classifier: Topic :: Utilities
|
|
240
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
241
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
242
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
243
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
244
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
245
|
+
Classifier: Operating System :: OS Independent
|
|
246
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.cfg
|
|
4
|
+
setup.py
|
|
5
|
+
test/test_ttp_templates_methods.py
|
|
6
|
+
test/test_yang_ietf_interfaces.py
|
|
7
|
+
ttp_templates/__init__.py
|
|
8
|
+
ttp_templates/ttp_templates.py
|
|
9
|
+
ttp_templates.egg-info/PKG-INFO
|
|
10
|
+
ttp_templates.egg-info/SOURCES.txt
|
|
11
|
+
ttp_templates.egg-info/dependency_links.txt
|
|
12
|
+
ttp_templates.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ttp_templates
|