├── .gitignore
├── .project
├── .pydevproject
├── .travis.yml
├── LICENSE
├── README.md
├── coding102-REST-python-dcloud
├── build-topology.py
├── create-ticket.py
├── get-network-devices.py
├── get-network-hosts.py
├── manage-users.py
├── readme.txt
├── report-topology.py
└── spark.py
├── coding102-REST-python-ga
├── build-topology-webserver.py
├── build-topology.py
├── create-ticket.py
├── get-network-devices.py
├── get-network-hosts.py
├── manage-users.py
└── templates
│ └── topology.html
├── coding103-python-json
├── Examples
│ ├── example1.py
│ ├── example2.py
│ └── example3.py
└── reqirements.txt
├── coding201-parsing-xml
├── get-ap-xml-1.py
├── get-ap-xml-2.py
├── get-ap-xml-3.py
├── get-ap-xml-4.py
├── get-tenants-xml-1.py
├── get-tenants-xml-2.py
├── get-tenants-xml-3.py
└── get-tenants-xml-4.py
├── coding202-parsing-json
├── activity-debug-1.py
├── activity-parse-1.py
├── activity-parse-2.py
├── activity-parse-3.py
├── activity-parse-4.py
├── call-functions.py
├── data-type-values.py
├── get-ap-json-1.py
├── get-ap-json-2.py
├── get-ap-json-3.py
├── get-cmx-json.py
├── get-tenant-json-1.py
├── get-tenant-json-2.py
├── get-tenant-json-3.py
├── hello.py
├── helloworld.py
├── json_parse-1.py
├── json_parse-2.py
└── parse.py
├── coding203-getting-input
└── get-input.py
├── coding204-reading-a-file
├── my-file.txt
├── my-json.json
├── read-file-loop.py
├── read-file-one-line.py
├── read-file-with.py
├── read-file.py
└── read-json-from-file.py
├── coding205-writing-file-ga
├── list-of-devices.txt
├── write-file-append.py
├── write-file-using-with.py
├── write-file.py
└── write-json-to-file.py
├── coding206-logging
├── logging-step3.py
├── logging-step4.py
├── mylog.log
└── super-simple-logging.py
├── coding207-putting-it-together-ga
├── crap.txt
└── create-device-list.py
├── coding210-parsing-json-c++
├── CMakeLists.txt
├── README.md
├── activity-1.cmake
├── activity-2.cmake
├── activity-3.cmake
├── activity-4.cmake
├── activity-5.cmake
├── hello.cpp
├── hello.cs
├── main-annotated.cpp
├── main-http.cpp
├── main-json-lib.cpp
├── main-json.cpp
└── main.cpp
├── content-serve
├── content-server.py
└── data
│ ├── complex-array.json
│ ├── complex.json
│ └── index.html
└── contributing.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 |
8 | # Distribution / packaging
9 | .Python
10 | env/
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | *.egg-info/
23 | .installed.cfg
24 | *.egg
25 |
26 | # PyInstaller
27 | # Usually these files are written by a python script from a template
28 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
29 | *.manifest
30 | *.spec
31 |
32 | # Installer logs
33 | pip-log.txt
34 | pip-delete-this-directory.txt
35 |
36 | # Unit test / coverage reports
37 | htmlcov/
38 | .tox/
39 | .coverage
40 | .coverage.*
41 | .cache
42 | nosetests.xml
43 | coverage.xml
44 | *,cover
45 |
46 | # Translations
47 | *.mo
48 | *.pot
49 |
50 | # Django stuff:
51 | *.log
52 |
53 | # Sphinx documentation
54 | docs/_build/
55 |
56 | # PyBuilder
57 | target/
58 |
59 | # Jetbrains IDE files
60 | .idea
61 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | coding-skills-sample-code
4 |
5 |
6 |
7 |
8 |
9 | org.python.pydev.PyDevBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.python.pydev.pythonNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /${PROJECT_DIR_NAME}
5 |
6 | python 3.0
7 | Default
8 |
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7"
4 | branches:
5 | only:
6 | - clus-updates
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Cisco DevNet Learning Labs Sample Code for Coding Skills
2 |
3 | These code examples provide Python scripts to perform coding tasks.
4 |
5 | The step-by-step tutorials that work with this code are Learning Labs, displayed within the [Cisco DevNet Learning Labs system](https://developer.cisco.com/learning).
6 |
7 | Contributions are welcome, and we are glad to review changes through pull requests. See [contributing.md](contributing.md) for details.
8 |
9 | The goal of these learning labs is to ensure a 'hands-on' learning approach rather than just theory or instructions.
10 |
11 | ## Contributing
12 |
13 | These samples are for public consumption, so you must ensure that you have the rights to any code that you contribute.
14 |
15 | ## Getting Involved
16 |
17 | * If you'd like to contribute examples for an existing lab, refer to [contributing.md](contributing.md).
18 | * If you're interested in creating a new Cisco DevNet Learning Lab or code example, please contact a DevNet administrator for guidance.
19 |
20 |
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/build-topology.py:
--------------------------------------------------------------------------------
1 | # Example of building topology via REST API calls from Python
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 |
23 | # import requests library
24 | import requests
25 |
26 | #import json library
27 | import json
28 |
29 | # Disable warnings
30 | requests.packages.urllib3.disable_warnings()
31 |
32 | controller='198.18.129.100'
33 |
34 |
35 | def getTicket():
36 | # put the ip address or dns of your apic-em controller in this url
37 | url = "https://" + controller + "/api/v1/ticket"
38 |
39 | #the username and password to access the APIC-EM Controller
40 | payload = {"username":"admin","password":"C1sco12345"}
41 |
42 | #Content type must be included in the header
43 | header = {"content-type": "application/json"}
44 |
45 | #Performs a POST on the specified url to get the service ticket
46 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
47 |
48 | print (response)
49 |
50 | #convert response to json format
51 | r_json=response.json()
52 |
53 | #parse the json to get the service ticket
54 | ticket = r_json["response"]["serviceTicket"]
55 |
56 | return ticket
57 |
58 |
59 |
60 | def getTopology(ticket):
61 | # URL for topology REST API call to get list of existing devices on the network, and build topology
62 | url = "https://" + controller + "/api/v1/topology/physical-topology"
63 |
64 | #Content type as well as the ticket must be included in the header
65 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
66 |
67 | # this statement performs a GET on the specified network device url
68 | response = requests.get(url, headers=header, verify=False)
69 |
70 | # json.dumps serializes the json into a string and allows us to
71 | # print the response in a 'pretty' format with indentation etc.
72 | print ("Topology = ")
73 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
74 |
75 | #convert data to json format.
76 | r_json=response.json()
77 |
78 | #Iterate through network device data and list the nodes, their interfaces, status and to what they connect
79 | for n in r_json["response"]["nodes"]:
80 | if "platformId" in n:
81 | print()
82 | print()
83 | print('{:30}'.format("Node") + '{:25}'.format("Family") + '{:20}'.format("Label")+ "Management IP")
84 | print('{:30}'.format(n["platformId"]) + '{:25}'.format(n["family"]) + '{:20}'.format(n["label"]) + n["ip"])
85 | found=0 #print header flag
86 | printed=0 #formatting flag
87 | for i in r_json["response"]["links"]:
88 | if "startPortName" in i:
89 | #check that the source device id for the interface matches the node id. Means interface originated from this device.
90 | if i["source"] == n["id"]:
91 | if found==0:
92 | print('{:>20}'.format("Source Interface") + '{:>15}'.format("Target") +'{:>28}'.format("Target Interface") + '{:>15}'.format("Status") )
93 | found=1
94 | printed=1
95 | for n1 in r_json["response"]["nodes"]:
96 | #find name of node to which this one connects
97 | if i["target"] == n1["id"]:
98 | print(" " + '{:<25}'.format(i["startPortName"]) + '{:<18}'.format(n1["platformId"]) + '{:<25}'.format(i["endPortName"]) + '{:<9}'.format(i["linkStatus"]) )
99 | break;
100 | found=0
101 |
102 | for i in r_json["response"]["links"]:
103 | if "startPortName" in i:
104 | #Find interfaces that link to this one which means this node is the target.
105 | if i["target"] == n["id"]:
106 | if found==0:
107 | if printed==1:
108 | print()
109 | print('{:>10}'.format("Source") + '{:>30}'.format("Source Interface") + '{:>25}'.format("Target Interface") + '{:>13}'.format("Status"))
110 | found=1
111 | for n1 in r_json["response"]["nodes"]:
112 | #find name of node to that connects to this one
113 | if i["source"] == n1["id"]:
114 | print(" " + '{:<20}'.format(n1["platformId"]) + '{:<25}'.format(i["startPortName"]) + '{:<23}'.format(i["endPortName"]) + '{:<8}'.format(i["linkStatus"]))
115 | break;
116 |
117 | theTicket=getTicket()
118 | getTopology(theTicket)
119 |
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/create-ticket.py:
--------------------------------------------------------------------------------
1 | # import requests library
2 | import requests
3 |
4 | #import json library
5 | import json
6 |
7 | # put the ip address or dns of your apic-em controller in this url
8 | url = 'https://198.18.129.100/api/v1/ticket'
9 |
10 |
11 |
12 | #the username and password to access the APIC-EM Controller
13 | payload = {"username":"admin","password":"C1sco12345"}
14 |
15 |
16 | #Content type must be included in the header
17 | header = {"content-type": "application/json"}
18 |
19 | #Performs a POST on the specified url.
20 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
21 |
22 | # print the json that is returned
23 | print(response.text)
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/get-network-devices.py:
--------------------------------------------------------------------------------
1 | # Example of getting network-devices via REST API calls from Python
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 |
23 | # import requests library
24 | import requests
25 |
26 | #import json library
27 | import json
28 |
29 | controller='198.18.129.100'
30 |
31 | def getTicket():
32 | # put the ip address or dns of your apic-em controller in this url
33 | url = "https://" + controller + "/api/v1/ticket"
34 |
35 | #the username and password to access the APIC-EM Controller
36 | payload = {"username":"admin","password":"C1sco12345"}
37 |
38 | #Content type must be included in the header
39 | header = {"content-type": "application/json"}
40 |
41 | #Performs a POST on the specified url to get the service ticket
42 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
43 |
44 | print (response)
45 |
46 | #convert response to json format
47 | r_json=response.json()
48 |
49 | #parse the json to get the service ticket
50 | ticket = r_json["response"]["serviceTicket"]
51 |
52 | return ticket
53 |
54 |
55 | def getNetworkDevices(ticket):
56 | # URL for network-device REST API call to get list of exisiting devices on the network.
57 | url = "https://" + controller + "/api/v1/network-device"
58 |
59 | #Content type as well as the ticket must be included in the header
60 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
61 |
62 | # this statement performs a GET on the specified network device url
63 | response = requests.get(url, headers=header, verify=False)
64 |
65 | # json.dumps serializes the json into a string and allows us to
66 | # print the response in a 'pretty' format with indentation etc.
67 | print ("Network Devices = ")
68 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
69 |
70 | #convert data to json format.
71 | r_json=response.json()
72 |
73 | #Iterate through network device data and print the id and series name of each device
74 | for i in r_json["response"]:
75 | print(i["id"] + " " + '{:53}'.format(i["series"]) + " " + i["reachabilityStatus"])
76 |
77 |
78 |
79 | theTicket=getTicket()
80 | getNetworkDevices(theTicket)
81 |
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/get-network-hosts.py:
--------------------------------------------------------------------------------
1 | # Simple Example of calling REST API from Python
2 | # This is all that is required to call a REST API from python
3 |
4 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
5 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
6 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
7 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
8 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
9 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
10 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
11 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
12 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
13 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
14 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
15 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
16 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
17 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
18 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
19 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
20 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
21 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
22 |
23 |
24 | # import requests library
25 | import requests
26 |
27 | #import json library
28 | import json
29 |
30 | controller='198.18.129.100'
31 |
32 |
33 | # put the ip address or dns of your apic-em controller in this url
34 | url = "https://" + controller + "/api/v1/ticket"
35 |
36 | #the username and password to access the APIC-EM Controller
37 | payload = {"username":"admin","password":"C1sco12345"}
38 |
39 | #Content type must be included in the header
40 | header = {"content-type": "application/json"}
41 |
42 | #Performs a POST on the specified url to get the service ticket
43 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
44 |
45 | #convert response to json format
46 | r_json=response.json()
47 |
48 | print(r_json)
49 | #parse the json to get the service ticket
50 | ticket = r_json["response"]["serviceTicket"]
51 |
52 | # URL for Host REST API call to get list of exisitng hosts on the network.
53 | url = "https://" + controller + "/api/v1/host?limit=1&offset=1"
54 |
55 | #Content type must be included in the header as well as the ticket
56 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
57 |
58 | # this statement performs a GET on the specified host url
59 | response = requests.get(url, headers=header, verify=False)
60 |
61 | # json.dumps serializes the json into a string and allows us to
62 | # print the response in a 'pretty' format with indentation etc.
63 | print ("Hosts = ")
64 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/manage-users.py:
--------------------------------------------------------------------------------
1 | # Example of calling REST API from Python to manage APIC-EM users/roles using APIC-EM APIs.
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 |
23 | # import requests library
24 | import requests
25 |
26 | #import json library
27 | import json
28 |
29 |
30 | # Disable warnings
31 | requests.packages.urllib3.disable_warnings()
32 |
33 | controller='198.18.129.100'
34 |
35 |
36 | #creates and returns a service ticket.
37 | def getTicket():
38 | print("\nCreating ticket")
39 | # put the ip address or dns of your apic-em controller in this url
40 | url = "https://" + controller + "/api/v1/ticket"
41 |
42 | #the username and password to access the APIC-EM Controller
43 | payload = {"username":"admin","password":"C1sco12345"}
44 |
45 | #Content type must be included in the header
46 | header = {"content-type": "application/json"}
47 |
48 | #Performs a POST on the specified url to get the service ticket
49 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
50 |
51 | print(response.text)
52 |
53 | #convert response to json format
54 | r_json=response.json()
55 |
56 | #parse the json to get the service ticket
57 | ticket = r_json["response"]["serviceTicket"]
58 |
59 | return ticket
60 |
61 | #Get and display the APIC-EM Users
62 | def getUsers(ticket):
63 | print("\nGetting list of existing users")
64 | # URL for user REST API call to get list of APIC-EM users.
65 | url = "https://" + controller + "/api/v1/user"
66 |
67 | #Content type as well as the ticket must be included in the header
68 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
69 |
70 | # this statement performs a GET on the specified host url
71 | response = requests.get(url, headers=header, verify=False)
72 |
73 | # json.dumps serializes the json into a string and allows us to
74 | # print the response in a 'pretty' format with indentation etc.
75 | print ("Users = ")
76 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
77 |
78 |
79 | #Adds a APIC-EM User
80 | def addUser(ticket):
81 | print("\nAdding new user")
82 | # URL for user REST API call to get list of existing users in the network.
83 | url = "https://" + controller + "/api/v1/user"
84 |
85 | #Content type as well as the ticket must be included in the header
86 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
87 |
88 | username="brett"
89 | #Data for new user
90 | payload={"password":"Brett123!","username":username,"authorization":[{"scope":"ALL","role":"ROLE_OBSERVER"}]}
91 |
92 | # this statement performs a Post on the specified user url
93 | response = requests.post(url, data=json.dumps(payload), headers=header, verify=False)
94 | print ("Response after post: " + response.text)
95 |
96 | return (username)
97 |
98 |
99 | #Delete the user that corresponds to the passed in username parameter
100 | def deleteUser(username, ticket):
101 | print("\nRemoving user: " + username)
102 | # URL for a specified user REST API call.
103 | url = "https://" + controller + "/api/v1/user/" + username
104 |
105 | #Content type as well as the ticket must be included in the header
106 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
107 |
108 | # this statement performs a Delete on the specified user url
109 | response = requests.delete(url, headers=header, verify=False)
110 | print (response.text)
111 |
112 |
113 | #Show the User that corresponds to the passed in username parameter
114 | def showUser(username, ticket):
115 | print("\nDisplaying user: " + username)
116 | # URL for user REST API call to get APIC-EM user with corresponding name.
117 | url = "https://" + controller + "/api/v1/user/" + username
118 |
119 | #Content type as well as the ticket must be included in the header
120 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
121 |
122 | # this statement performs a GET on the specified user url
123 | response = requests.get(url, headers=header, verify=False)
124 |
125 | # json.dumps serializes the json into a string and allows us to
126 | # print the response in a 'pretty' format with indentation etc.
127 | print ("User found = ")
128 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
129 |
130 |
131 |
132 | theTicket=getTicket()
133 | getUsers(theTicket)
134 | name=addUser(theTicket)
135 | showUser(name,theTicket)
136 | getUsers(theTicket)
137 | deleteUser(name,theTicket)
138 | getUsers(theTicket)
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/readme.txt:
--------------------------------------------------------------------------------
1 | Before you begin
2 |
3 | These code samples are intended to be used with the Cisco DevNet Learning Labs. The Learning Labs will
4 | walk you through the code step by step.
5 |
6 | You can find the learning labs here:
7 | https://developer.cisco.com/learning/lab/coding-101-rest-basics-ga/step/1
8 | https://developer.cisco.com/learning/lab/coding-102-rest-python-ga/step/1
9 |
10 | You will need to download and setup a few items before you can begin coding along with us.
11 |
12 | Download the Coding 101 sample code and slides
13 | Your favorite text editor (text wrangler, notepad ++, sublime text etc.)
14 | Postman Rest Client for Chrome
15 | Python
16 | Python is normally pre-installed on Mac OS and most Linux distributions.
17 | You can also install Python on Windows.
18 | First, check see if you have Python installed on your system.
19 | Go to your command prompt and type “python”.
20 | If you get an error, follow the installations to install python for your system type from this page - http://learnpythonthehardway.org/book/ex0.html
21 | You will also need to install the Requests Library for Python.
22 | This is a library that makes it very easy to call REST APIs.
23 | Follow the instructions to install it here - http://docs.python-requests.org/en/latest/user/install/#install
24 |
25 |
26 | This download contains the following python examples:
27 |
28 | * create-ticket.py – First REST call to create a service ticket which is later used for authentication and role management
29 | * get-network-hosts.py – First application to parse the service ticket response and show list of hosts by doing a pretty print of the JSON data
30 | * get-network-devices.py – Retrieves network device list and parses JSON to display networkDeviceId values
31 | * manage-users.py – Shows how to manage controller access by retrieving, adding and deleting users
32 |
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/report-topology.py:
--------------------------------------------------------------------------------
1 | # Example of building and reporting topology via REST API calls from Python
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 | from spark import *
23 |
24 | # import requests library
25 | import requests
26 |
27 | #import json library
28 | import json
29 |
30 | # Disable warnings
31 | requests.packages.urllib3.disable_warnings()
32 |
33 | controller='198.18.129.100'
34 |
35 | def getTicket():
36 | # put the ip address or dns of your apic-em controller in this url
37 | url = "https://" + controller + "/api/v1/ticket"
38 |
39 | #the username and password to access the APIC-EM Controller
40 | #payload = {"username":"devnetuser","password":"Cisco123!"}
41 | payload = {"username":"admin","password":"C1sco12345"}
42 |
43 | #Content type must be included in the header
44 | header = {"content-type": "application/json"}
45 |
46 | #Performs a POST on the specified url to get the service ticket
47 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
48 |
49 | print (response)
50 |
51 | #convert response to json format
52 | r_json=response.json()
53 |
54 | #parse the json to get the service ticket
55 | ticket = r_json["response"]["serviceTicket"]
56 |
57 | return ticket
58 |
59 |
60 |
61 | def getTopology(ticket):
62 | # URL for topology REST API call to get list of existing devices on the network, and build topology
63 | url = "https://" + controller + "/api/v1/topology/physical-topology"
64 |
65 | #Content type as well as the ticket must be included in the header
66 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
67 |
68 | # this statement performs a GET on the specified network device url
69 | response = requests.get(url, headers=header, verify=False)
70 |
71 | # json.dumps serializes the json into a string and allows us to
72 | # print the response in a 'pretty' format with indentation etc.
73 | print ("Topology = ")
74 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
75 |
76 | #convert data to json format.
77 | r_json=response.json()
78 |
79 | net_nodes=[]
80 | #Iterate through network device data and list the nodes, their interfaces, status and to what they connect
81 | for n in r_json["response"]["nodes"]:
82 | if "platformId" in n:
83 | print()
84 | print()
85 | print('{:30}'.format("Node") + '{:25}'.format("Family") + '{:20}'.format("Label")+ "Management IP")
86 | print('{:30}'.format(n["platformId"]) + '{:25}'.format(n["family"]) + '{:20}'.format(n["label"]) + n["ip"])
87 | net_nodes.append(n["label"])
88 |
89 | found=0 #print header flag
90 | for i in r_json["response"]["links"]:
91 | if "startPortName" in i:
92 | #check that the source device id for the interface matches the node id. Means interface originated from this device.
93 | if i["source"] == n["id"]:
94 | if found==0:
95 | print('{:>20}'.format("Source Interface") + '{:>15}'.format("Target") +'{:>28}'.format("Target Interface") + '{:>15}'.format("Status") )
96 | found=1
97 | for n1 in r_json["response"]["nodes"]:
98 | #find name of node to which this one connects
99 | if i["target"] == n1["id"]:
100 | print(" " + '{:<25}'.format(i["startPortName"]) + '{:<18}'.format(n1["platformId"]) + '{:<25}'.format(i["endPortName"]) + '{:<9}'.format(i["linkStatus"]) )
101 | break
102 |
103 | return net_nodes
104 |
105 |
106 | theTicket=getTicket()
107 | theNodes=getTopology(theTicket)
108 | nodestr=""
109 | for node in theNodes:
110 | nodestr=nodestr + node + " "
111 | setHeaders()
112 | room_id=createRoom("Brett's Room")
113 | addMembers(room_id) # Passing roomId to members function here to Post Message.
114 | postMsg(room_id,"Network nodes are " + nodestr) # Passing roomId to message function here to Post Message.
115 |
--------------------------------------------------------------------------------
/coding102-REST-python-dcloud/spark.py:
--------------------------------------------------------------------------------
1 | import json
2 | import requests
3 |
4 | accessToken = "" #set your access token here
5 |
6 |
7 | def setHeaders():
8 | global spark_header
9 | accessToken_hdr = 'Bearer ' + accessToken
10 | spark_header = {'Authorization': accessToken_hdr, 'Content-Type': 'application/json; charset=utf-8'}
11 |
12 |
13 | def createRoom(room_name):
14 | roomInfo = '{"title" :"' + room_name + '"}'
15 | uri = 'https://api.ciscospark.com/v1/rooms'
16 | resp = requests.post(uri, data=roomInfo, headers=spark_header)
17 | print("SparkAPI: ",resp)
18 | print(resp.json())
19 | print("Newly Created RoomId: ", resp.json()['id']) # You will need this roomId to post Messages to it
20 | return resp.json()['id']
21 |
22 |
23 | def addMembers(roomId):
24 | message = '{"roomId":"' + roomId + '","personEmail": "test@test.com", "isModerator": false}'
25 | uri = 'https://api.ciscospark.com/v1/memberships'
26 | resp = requests.post(uri, data=message, headers=spark_header)
27 | print("SparkAPI: ", resp.json())
28 |
29 |
30 | def postMsg(roomId,message):
31 | message = '{"roomId":"' + roomId + '","text":"'+message+'"}'
32 | uri = 'https://api.ciscospark.com/v1/messages'
33 | resp = requests.post(uri, data=message, headers=spark_header)
34 | print("SparkAPI: ", resp.json())
35 |
36 |
37 | if __name__ == '__main__':
38 | setHeaders()
39 | room_id=createRoom("Brett's Room")
40 | addMembers(room_id) # Passing roomId to members function here to Post Message.
41 | postMsg(room_id,"What's up World?") # Passing roomId to message function here to Post Message.
42 |
43 |
--------------------------------------------------------------------------------
/coding102-REST-python-ga/build-topology-webserver.py:
--------------------------------------------------------------------------------
1 | # Example of render a topology via a web server. This include :
2 | # - building a web server via Flask (http://flask.pocoo.org/)
3 | # - render topology graphic via NeXt UI toolkit (https://wiki.opendaylight.org/view/NeXt:Main)
4 | # - get topology data from APIC-EM via REST API calls from Python
5 |
6 | # Before start please install flask by `pip install flask`
7 | # Then use python run this script via: python build-topology-webserver.py
8 | # Use Chrome or Safari browser. In the url field enter this link: `http://127.0.0.1:5000/`
9 |
10 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
11 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
12 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
13 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
14 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
15 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
16 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
17 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
18 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
19 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
20 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
21 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
22 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
23 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
24 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
25 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
26 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
27 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
28 |
29 |
30 | # import requests library
31 | import requests
32 |
33 | # import json library
34 | import json
35 |
36 | # import flask web framewoork
37 | from flask import Flask
38 |
39 | # from flask import render_template function
40 | from flask import render_template, jsonify
41 |
42 | # controller='sandboxapic.cisco.com'
43 | controller = 'devnetapi.cisco.com/sandbox/apic_em'
44 |
45 |
46 | def getTicket():
47 | # put the ip address or dns of your apic-em controller in this url
48 | url = "https://" + controller + "/api/v1/ticket"
49 |
50 | # the username and password to access the APIC-EM Controller
51 | payload = {"username": "devnetuser", "password": "Cisco123!"}
52 |
53 | # Content type must be included in the header
54 | header = {"content-type": "application/json"}
55 |
56 | # Performs a POST on the specified url to get the service ticket
57 | response = requests.post(url, data=json.dumps(payload), headers=header, verify=False)
58 |
59 | print(response)
60 |
61 | # convert response to json format
62 | r_json = response.json()
63 |
64 | # parse the json to get the service ticket
65 | ticket = r_json["response"]["serviceTicket"]
66 |
67 | return ticket
68 |
69 |
70 | def getTopology(ticket):
71 | # URL for network-device REST API call to get list of exisiting devices on the network.
72 | url = "https://" + controller + "/api/v1/topology/physical-topology"
73 |
74 | # Content type as well as the ticket must be included in the header
75 | header = {"content-type": "application/json", "X-Auth-Token": ticket}
76 |
77 | # this statement performs a GET on the specified network device url
78 | response = requests.get(url, headers=header, verify=False)
79 |
80 | # convert data to json format.
81 | r_json = response.json()
82 |
83 | # return json object
84 | return r_json["response"]
85 |
86 |
87 | # intialize a web app
88 | app = Flask(__name__)
89 |
90 | # define index route to return topology.html
91 | @app.route("/")
92 | def index():
93 | # when called '/' which is the default index page, render the template 'topology.html'
94 | return render_template("topology.html")
95 |
96 |
97 | # define an reset api to get topology data
98 | @app.route("/api/topology")
99 | def topology():
100 | # get ticket
101 | theTicket = getTicket()
102 |
103 | # get topology data and return `jsonify` string to request
104 | return jsonify(getTopology(theTicket))
105 |
106 |
107 |
108 | if __name__ == "__main__":
109 | app.run()
110 |
--------------------------------------------------------------------------------
/coding102-REST-python-ga/build-topology.py:
--------------------------------------------------------------------------------
1 | # Example of building topology via REST API calls from Python
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 |
23 | # import requests library
24 | import requests
25 |
26 | #import json library
27 | import json
28 |
29 | # Disable warnings
30 | requests.packages.urllib3.disable_warnings()
31 |
32 | #controller='sandboxapic.cisco.com'
33 | controller='devnetapi.cisco.com/sandbox/apic_em'
34 |
35 |
36 | def getTicket():
37 | # put the ip address or dns of your apic-em controller in this url
38 | url = "https://" + controller + "/api/v1/ticket"
39 |
40 | #the username and password to access the APIC-EM Controller
41 | payload = {"username":"devnetuser","password":"Cisco123!"}
42 |
43 | #Content type must be included in the header
44 | header = {"content-type": "application/json"}
45 |
46 | #Performs a POST on the specified url to get the service ticket
47 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
48 |
49 | print (response)
50 |
51 | #convert response to json format
52 | r_json=response.json()
53 |
54 | #parse the json to get the service ticket
55 | ticket = r_json["response"]["serviceTicket"]
56 |
57 | return ticket
58 |
59 |
60 |
61 | def getTopology(ticket):
62 | # URL for topology REST API call to get list of existing devices on the network, and build topology
63 | url = "https://" + controller + "/api/v1/topology/physical-topology"
64 |
65 | #Content type as well as the ticket must be included in the header
66 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
67 |
68 | # this statement performs a GET on the specified network device url
69 | response = requests.get(url, headers=header, verify=False)
70 |
71 | # json.dumps serializes the json into a string and allows us to
72 | # print the response in a 'pretty' format with indentation etc.
73 | print ("Topology = ")
74 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
75 |
76 | #convert data to json format.
77 | r_json=response.json()
78 |
79 | #Iterate through network device data and list the nodes, their interfaces, status and to what they connect
80 | for n in r_json["response"]["nodes"]:
81 | print()
82 | print()
83 | print('{:30}'.format("Node") + '{:25}'.format("Family") + '{:20}'.format("Label")+ "Management IP")
84 | if "platformId" in n:
85 | print('{:30}'.format(n["platformId"]) + '{:25}'.format(n["family"]) + '{:20.14}'.format(n["label"]) + n["ip"])
86 | else:
87 | print('{:30}'.format(n["role"]) + '{:25}'.format(n["family"]) + '{:20.14}'.format(n["label"]) + n["ip"])
88 | found=0 #print header flag
89 | printed=0 #formatting flag
90 | for i in r_json["response"]["links"]:
91 | #check that the source device id for the interface matches the node id. Means interface originated from this device.
92 | if i["source"] == n["id"]:
93 | if found==0:
94 | print('{:>20}'.format("Source Interface") + '{:>15}'.format("Target") +'{:>28}'.format("Target Interface") + '{:>15}'.format("Status") )
95 | found=1
96 | printed=1
97 | for n1 in r_json["response"]["nodes"]:
98 | #find name of node to which this one connects
99 | if i["target"] == n1["id"]:
100 | if "startPortName" in i:
101 | print(" " + '{:<25}'.format(i["startPortName"]) + '{:<18.14}'.format(n1["label"]) + '{:<25}'.format(i["endPortName"]) + '{:<9}'.format(i["linkStatus"]) )
102 | else:
103 | print(" " + '{:<25}'.format("unknown") + '{:<18.14}'.format(n1["label"]) + '{:<25}'.format("unknown") + '{:<9}'.format(i["linkStatus"]) )
104 | break;
105 | found=0
106 | for i in r_json["response"]["links"]:
107 | #Find interfaces that link to this one which means this node is the target.
108 | if i["target"] == n["id"]:
109 | if found==0:
110 | if printed==1:
111 | print()
112 | print('{:>10}'.format("Source") + '{:>30}'.format("Source Interface") + '{:>25}'.format("Target Interface") + '{:>13}'.format("Status"))
113 | found=1
114 | for n1 in r_json["response"]["nodes"]:
115 | #find name of node to that connects to this one
116 | if i["source"] == n1["id"]:
117 | if "startPortName" in i:
118 | print(" " + '{:<20}'.format(n1["label"]) + '{:<25}'.format(i["startPortName"]) + '{:<23}'.format(i["endPortName"]) + '{:<8}'.format(i["linkStatus"]))
119 | else:
120 | print(" " + '{:<20}'.format(n1["label"]) + '{:<25}'.format("unknown") + '{:<23}'.format("unknown") + '{:<8}'.format(i["linkStatus"]))
121 | break;
122 |
123 | theTicket=getTicket()
124 | getTopology(theTicket)
125 |
--------------------------------------------------------------------------------
/coding102-REST-python-ga/create-ticket.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3.5
2 |
3 | # import requests library
4 | import requests
5 |
6 | #import json library
7 | import json
8 |
9 | # put the ip address or dns of your apic-em controller in this url
10 | #url = 'https://sandboxapic.cisco.com/api/v1/ticket'
11 | url='https://devnetapi.cisco.com/sandbox/apic_em/api/v1/ticket'
12 |
13 |
14 |
15 | #the username and password to access the APIC-EM Controller
16 | payload = {"username":"devnetuser","password":"Cisco123!"}
17 |
18 |
19 | #Content type must be included in the header
20 | header = {"content-type": "application/json"}
21 |
22 | #Performs a POST on the specified url.
23 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
24 |
25 | # print the json that is returned
26 | print(response.text)
27 |
--------------------------------------------------------------------------------
/coding102-REST-python-ga/get-network-devices.py:
--------------------------------------------------------------------------------
1 | # Example of getting network-devices via REST API calls from Python
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 |
23 | # import requests library
24 | import requests
25 |
26 | #import json library
27 | import json
28 |
29 | #controller='sandboxapic.cisco.com'
30 | controller='devnetapi.cisco.com/sandbox/apic_em'
31 |
32 | def getTicket():
33 | # put the ip address or dns of your apic-em controller in this url
34 | url = "https://" + controller + "/api/v1/ticket"
35 |
36 | #the username and password to access the APIC-EM Controller
37 | payload = {"username":"devnetuser","password":"Cisco123!"}
38 |
39 | #Content type must be included in the header
40 | header = {"content-type": "application/json"}
41 |
42 | #Performs a POST on the specified url to get the service ticket
43 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
44 |
45 | print (response)
46 |
47 | #convert response to json format
48 | r_json=response.json()
49 |
50 | #parse the json to get the service ticket
51 | ticket = r_json["response"]["serviceTicket"]
52 |
53 | return ticket
54 |
55 |
56 | def getNetworkDevices(ticket):
57 | # URL for network-device REST API call to get list of exisiting devices on the network.
58 | url = "https://" + controller + "/api/v1/network-device"
59 |
60 | #Content type as well as the ticket must be included in the header
61 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
62 |
63 | # this statement performs a GET on the specified network device url
64 | response = requests.get(url, headers=header, verify=False)
65 |
66 | # json.dumps serializes the json into a string and allows us to
67 | # print the response in a 'pretty' format with indentation etc.
68 | print ("Network Devices = ")
69 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
70 |
71 | #convert data to json format.
72 | r_json=response.json()
73 |
74 | #Iterate through network device data and print the id and series name of each device
75 | for i in r_json["response"]:
76 | print(i["id"] + " " + '{:53}'.format(i["series"]) + " " + i["reachabilityStatus"])
77 |
78 |
79 |
80 | theTicket=getTicket()
81 | getNetworkDevices(theTicket)
82 |
--------------------------------------------------------------------------------
/coding102-REST-python-ga/get-network-hosts.py:
--------------------------------------------------------------------------------
1 | # Simple Example of calling REST API from Python
2 | # This is all that is required to call a REST API from python
3 |
4 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
5 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
6 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
7 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
8 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
9 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
10 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
11 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
12 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
13 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
14 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
15 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
16 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
17 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
18 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
19 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
20 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
21 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
22 |
23 |
24 | # import requests library
25 | import requests
26 |
27 | #import json library
28 | import json
29 |
30 | #controller='sandboxapic.cisco.com'
31 | controller='devnetapi.cisco.com/sandbox/apic_em'
32 |
33 |
34 | # put the ip address or dns of your apic-em controller in this url
35 | url = "https://" + controller + "/api/v1/ticket"
36 |
37 | #the username and password to access the APIC-EM Controller
38 | payload = {"username":"devnetuser","password":"Cisco123!"}
39 |
40 | #Content type must be included in the header
41 | header = {"content-type": "application/json"}
42 |
43 | #Performs a POST on the specified url to get the service ticket
44 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
45 |
46 | #convert response to json format
47 | r_json=response.json()
48 |
49 | print(r_json)
50 | #parse the json to get the service ticket
51 | ticket = r_json["response"]["serviceTicket"]
52 |
53 | # URL for Host REST API call to get list of exisitng hosts on the network.
54 | url = "https://" + controller + "/api/v1/host?limit=1&offset=1"
55 |
56 | #Content type must be included in the header as well as the ticket
57 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
58 |
59 | # this statement performs a GET on the specified host url
60 | response = requests.get(url, headers=header, verify=False)
61 |
62 | # json.dumps serializes the json into a string and allows us to
63 | # print the response in a 'pretty' format with indentation etc.
64 | print ("Hosts = ")
65 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
66 |
67 | r_resp=response.json()
68 |
69 | print(r_resp["response"][0]["hostIp"])
--------------------------------------------------------------------------------
/coding102-REST-python-ga/manage-users.py:
--------------------------------------------------------------------------------
1 | # Example of calling REST API from Python to manage APIC-EM users/roles using APIC-EM APIs.
2 |
3 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
4 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
6 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
7 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
8 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
9 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
10 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
11 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
12 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
13 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
14 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
15 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
16 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
17 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
18 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
19 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
20 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
21 |
22 |
23 | # import requests library
24 | import requests
25 |
26 | #import json library
27 | import json
28 |
29 |
30 | # Disable warnings
31 | requests.packages.urllib3.disable_warnings()
32 |
33 |
34 | #controller='sandboxapic.cisco.com'
35 | controller='devnetapi.cisco.com/sandbox/apic_em'
36 |
37 |
38 | #creates and returns a service ticket.
39 | def getTicket():
40 | print("\nCreating ticket")
41 | # put the ip address or dns of your apic-em controller in this url
42 | url = "https://" + controller + "/api/v1/ticket"
43 |
44 | #the username and password to access the APIC-EM Controller
45 | payload = {"username":"devnetuser","password":"Cisco123!"}
46 |
47 | #Content type must be included in the header
48 | header = {"content-type": "application/json"}
49 |
50 | #Performs a POST on the specified url to get the service ticket
51 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
52 |
53 | print(response.text)
54 |
55 | #convert response to json format
56 | r_json=response.json()
57 |
58 | #parse the json to get the service ticket
59 | ticket = r_json["response"]["serviceTicket"]
60 |
61 | return ticket
62 |
63 | #Get and display the APIC-EM Users
64 | def getUsers(ticket):
65 | print("\nGetting list of existing users")
66 | # URL for user REST API call to get list of APIC-EM users.
67 | url = "https://" + controller + "/api/v1/user"
68 |
69 | #Content type as well as the ticket must be included in the header
70 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
71 |
72 | # this statement performs a GET on the specified host url
73 | response = requests.get(url, headers=header, verify=False)
74 |
75 | # json.dumps serializes the json into a string and allows us to
76 | # print the response in a 'pretty' format with indentation etc.
77 | print ("Users = ")
78 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
79 |
80 |
81 | #Adds a APIC-EM User
82 | def addUser(ticket):
83 | print("\nAdding new user")
84 | # URL for user REST API call to get list of existing users in the network.
85 | url = "https://" + controller + "/api/v1/user"
86 |
87 | #Content type as well as the ticket must be included in the header
88 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
89 |
90 | username="brett"
91 | #Data for new user
92 | payload={"password":"Brett123!","username":username,"authorization":[{"scope":"ALL","role":"ROLE_OBSERVER"}]}
93 |
94 | # this statement performs a Post on the specified user url
95 | response = requests.post(url, data=json.dumps(payload), headers=header, verify=False)
96 | print ("Response after post: " + response.text)
97 |
98 | return (username)
99 |
100 |
101 | #Delete the user that corresponds to the passed in username parameter
102 | def deleteUser(username, ticket):
103 | print("\nRemoving user: " + username)
104 | # URL for a specified user REST API call.
105 | url = "https://" + controller + "/api/v1/user/" + username
106 |
107 | #Content type as well as the ticket must be included in the header
108 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
109 |
110 | # this statement performs a Delete on the specified user url
111 | response = requests.delete(url, headers=header, verify=False)
112 | print (response.text)
113 |
114 |
115 | #Show the User that corresponds to the passed in username parameter
116 | def showUser(username, ticket):
117 | print("\nDisplaying user: " + username)
118 | # URL for user REST API call to get APIC-EM user with corresponding name.
119 | url = "https://" + controller + "/api/v1/user/" + username
120 |
121 | #Content type as well as the ticket must be included in the header
122 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
123 |
124 | # this statement performs a GET on the specified user url
125 | response = requests.get(url, headers=header, verify=False)
126 |
127 | # json.dumps serializes the json into a string and allows us to
128 | # print the response in a 'pretty' format with indentation etc.
129 | print ("User found = ")
130 | print (json.dumps(response.json(), indent=4, separators=(',', ': ')))
131 |
132 |
133 |
134 | theTicket=getTicket()
135 | getUsers(theTicket)
136 | name=addUser(theTicket)
137 | showUser(name,theTicket)
138 | getUsers(theTicket)
139 | deleteUser(name,theTicket)
140 | getUsers(theTicket)
--------------------------------------------------------------------------------
/coding102-REST-python-ga/templates/topology.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | APIC-EM Topology
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/coding103-python-json/Examples/example1.py:
--------------------------------------------------------------------------------
1 | # Import Statements
2 | import json
3 |
4 | #This is our JSON sample
5 | string = """
6 | {
7 | "first_name": "Jacob",
8 | "last_name": "Adams"
9 | }
10 |
11 | """
12 |
13 | # Print out the JSON sample
14 | print("This is just a string \n " + string)
15 |
16 | # Load the data into a JSON object
17 | json_data = json.loads(string)
18 |
19 | # Extract first name from the object and assign it to a variable
20 | name = json_data["first_name"]
21 |
22 | # Print the extracted data to the terminal, to show us it worked.
23 | print("My first name is: " + name)
--------------------------------------------------------------------------------
/coding103-python-json/Examples/example2.py:
--------------------------------------------------------------------------------
1 | # Import Statements
2 | import json
3 |
4 | # Sample json as a string
5 | string = """
6 | {
7 | "prop_1001": {
8 | "type": "apartment",
9 | "residents": [{
10 | "resident": "Jacob",
11 | "phone": "555-1234"
12 | },
13 | {
14 | "resident": "Emily",
15 | "phone": "555-1235"
16 | }
17 | ]
18 | },
19 |
20 | "prop_1002": {
21 | "type": "condo",
22 | "residents": [{
23 | "resident": "Jock",
24 | "phone": "555-1236"
25 | },
26 | {
27 | "resident": "Kelley",
28 | "phone": "555-1237"
29 | }
30 | ]
31 | }
32 | }
33 |
34 | """
35 |
36 | json_string = json.loads(string)
37 |
38 | # print out type for 1001
39 | rental_type = str(json_string['prop_1001']['type'])
40 |
41 | print("the rental type is: " + rental_type)
42 |
43 | # print out the residents on prop_1002
44 | #count = 0
45 | #for i in json_string['prop_1002']["residents"]:
46 | # print("Resident number %s is %s!" % (str(count), str(i["resident"])))
47 | # count += 1
48 | """
49 | for i, data in enumerate(json_string['prop_1002']["residents"]):
50 | print("Resident number %s is %s!" % (str(i), str(data["resident"])))
51 | """
52 |
53 |
--------------------------------------------------------------------------------
/coding103-python-json/Examples/example3.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 |
4 |
5 | # Request the x-auth-token
6 | url = "https://sandboxapic.cisco.com/api/v1/ticket"
7 | # Request Body
8 | payload = """{
9 | "username":"devnetuser",
10 | "password":"Cisco123!"
11 | }"""
12 |
13 | # HTTP Headers
14 | headers = {
15 | 'content-type': "application/json"
16 | }
17 |
18 | # Execute request
19 | response = requests.request("POST", url, data=payload, headers=headers, verify=False)
20 |
21 | # Print request
22 | print(response.text)
23 |
24 | # Load the response into a JSON object
25 | json_response = json.loads(response.text)
26 |
27 | # Parse the service ticket out of the JSON
28 | service_ticket = json_response['response']['serviceTicket']
29 |
30 | # Print the service ticket
31 | print(service_ticket)
32 |
33 | # Request the x-auth-token
34 | url = "https://sandboxapic.cisco.com/api/v1/host"
35 |
36 | # HTTP Headers
37 | headers = {
38 | 'content-type': "application/json",
39 | 'x-auth-token': service_ticket
40 | }
41 |
42 | # Execute request to get hosts, set equal to host_response
43 | host_response = requests.request("GET", url, data=payload, headers=headers, verify=False)
44 |
45 | #Print the reponse data
46 | print(host_response.text)
47 |
48 | #Load the response into a json object
49 | host_response = json.loads(host_response.text)
50 |
51 | # loop through the response, return the host IP and connection type
52 | for i, body in enumerate(host_response["response"]):
53 | host = body['hostIp']
54 | connection = body['hostType']
55 | message = "Host %i's ip is %s and uses a %s connection!\n" % (i + 1, host, connection)
56 | print(message)
--------------------------------------------------------------------------------
/coding103-python-json/reqirements.txt:
--------------------------------------------------------------------------------
1 | requests
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-ap-xml-1.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | req = Request('https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
3 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc==')
4 | response = urlopen(req)
5 | responseString = response.read().decode("utf-8")
6 | print(responseString)
7 | response.close()
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-ap-xml-2.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import xml.dom.minidom
3 | req = Request('https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
4 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc==')
5 | response = urlopen(req)
6 | responseString = response.read().decode("utf-8")
7 | dom = xml.dom.minidom.parseString(responseString)
8 | xml = dom.toprettyxml()
9 | print(xml)
10 | response.close()
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-ap-xml-3.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import xml.dom.minidom
3 | req = Request('https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
4 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc==')
5 | response = urlopen(req)
6 | responseString = response.read().decode("utf-8")
7 | dom = xml.dom.minidom.parseString(responseString)
8 | xml = dom.toprettyxml()
9 | print(xml)
10 | floor_element = dom.firstChild
11 | if floor_element.hasChildNodes :
12 | child = floor_element.firstChild
13 | while child is not None:
14 | if child.tagName == 'AccessPoint' :
15 | output = child.tagName + ": " + child.getAttribute('name') + '\t eth: ' + child.getAttribute('ethMacAddress')
16 | print(output)
17 | child = child.nextSibling
18 | response.close()
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-ap-xml-4.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import xml.dom.minidom
3 | req = Request('https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
4 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc==')
5 | response = urlopen(req)
6 | responseString = response.read().decode("utf-8")
7 | dom = xml.dom.minidom.parseString(responseString)
8 | xml = dom.toprettyxml()
9 | print(xml)
10 | access_points = dom.getElementsByTagName('AccessPoint')
11 | for access_point in access_points:
12 | ap_name = access_point.getAttribute('name')
13 | ap_eth_addr = access_point.getAttribute('ethMacAddress')
14 | ap_ip_addr = access_point.getAttribute('ipAddress')
15 | print(access_point.tagName + ": " + ap_name + '\t eth: ' + ap_eth_addr + '\t ip: ' + ap_ip_addr)
16 | response.close()
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-tenants-xml-1.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import xml.dom.minidom
3 | # We need to import the JSON library just to handle our request to the APIC for login
4 | import json
5 |
6 |
7 | # We need to log in to the APIC and gather a token, before we can access any data
8 | # Let's construct a request with a body
9 |
10 | # We'll need to disable certificate warnings
11 | requests.packages.urllib3.disable_warnings()
12 |
13 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
14 | encoded_body = json.dumps({
15 | "aaaUser": {
16 | "attributes": {
17 | "name": "admin",
18 | "pwd": "ciscopsdt"
19 | }
20 | }
21 | })
22 |
23 | # Now lets make the request and store the data
24 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
25 |
26 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
27 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
28 |
29 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
30 | # We leverage the .xml ending to receive the data back as XML
31 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False)
32 |
33 | # Requests stores the text of the response in the .text attribute. Lets print it to see raw XML
34 | print(tenants.text)
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-tenants-xml-2.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import xml.dom.minidom
3 | # We need to import the JSON library just to handle our request to the APIC for login
4 | import json
5 |
6 |
7 | # We need to log in to the APIC and gather a token, before we can access any data
8 | # Let's construct a request with a body
9 |
10 | # We'll need to disable certificate warnings
11 | requests.packages.urllib3.disable_warnings()
12 |
13 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
14 | encoded_body = json.dumps({
15 | "aaaUser": {
16 | "attributes": {
17 | "name": "admin",
18 | "pwd": "ciscopsdt"
19 | }
20 | }
21 | })
22 |
23 | # Now lets make the request and store the data
24 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
25 |
26 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
27 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
28 |
29 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
30 | # We leverage the .xml ending to receive the data back as XML
31 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False)
32 |
33 | # Now lets use DOM to clean up the XML from its completely raw format
34 | dom = xml.dom.minidom.parseString(tenants.text)
35 | xml = dom.toprettyxml()
36 | print(xml)
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-tenants-xml-3.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import xml.dom.minidom
3 | # We need to import the JSON library just to handle our request to the APIC for login
4 | import json
5 |
6 |
7 | # We need to log in to the APIC and gather a token, before we can access any data
8 | # Let's construct a request with a body
9 |
10 | # We'll need to disable certificate warnings
11 | requests.packages.urllib3.disable_warnings()
12 |
13 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
14 | encoded_body = json.dumps({
15 | "aaaUser": {
16 | "attributes": {
17 | "name": "admin",
18 | "pwd": "ciscopsdt"
19 | }
20 | }
21 | })
22 |
23 | # Now lets make the request and store the data
24 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
25 |
26 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
27 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
28 |
29 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
30 | # We leverage the .xml ending to receive the data back as XML
31 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False)
32 |
33 | # Now lets use DOM to clean up the XML from its completely raw format
34 | dom = xml.dom.minidom.parseString(tenants.text)
35 | xml = dom.toprettyxml()
36 | print(xml)
37 |
38 | # Now we want to parse the resulting XML and print only the tenant name and its current health score. We'll do this through iteration over the elements in the XML
39 | tenant_objects = dom.firstChild
40 | if tenant_objects.hasChildNodes:
41 | tenant_element = tenant_objects.firstChild
42 | while tenant_element is not None:
43 | if tenant_element.tagName == 'fvTenant':
44 | health_element = tenant_element.firstChild
45 | output = "Tenant: " + tenant_element.getAttribute('name') + '\t Health Score: ' + health_element.getAttribute('cur')
46 | print(output.expandtabs(40))
47 | tenant_element = tenant_element.nextSibling
--------------------------------------------------------------------------------
/coding201-parsing-xml/get-tenants-xml-4.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import xml.dom.minidom
3 | # We need to import the JSON library just to handle our request to the APIC for login
4 | import json
5 |
6 |
7 | # We need to log in to the APIC and gather a token, before we can access any data
8 | # Let's construct a request with a body
9 |
10 | # We'll need to disable certificate warnings
11 | requests.packages.urllib3.disable_warnings()
12 |
13 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
14 | encoded_body = json.dumps({
15 | "aaaUser": {
16 | "attributes": {
17 | "name": "admin",
18 | "pwd": "ciscopsdt"
19 | }
20 | }
21 | })
22 |
23 | # Now lets make the request and store the data
24 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
25 |
26 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
27 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
28 |
29 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
30 | # We leverage the .xml ending to receive the data back as XML
31 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.xml?rsp-subtree-include=health,faults", headers=header, verify=False)
32 |
33 | # Now lets use DOM to clean up the XML from its completely raw format
34 | dom = xml.dom.minidom.parseString(tenants.text)
35 | xml = dom.toprettyxml()
36 | print(xml)
37 |
38 | # Now we'll do something similar, but done using a direct access method of the data, rather than interation and loops
39 | tenant_list = dom.getElementsByTagName('fvTenant')
40 | for tenants in tenant_list:
41 | tenant_name = tenants.getAttribute('name')
42 | tenant_dn = tenants.getAttribute('dn')
43 | health_score = tenants.firstChild.getAttribute('cur')
44 | output = "Tenant: " + tenant_name + "\t Health Score: " + health_score + "\n DN: " + tenant_dn
45 | print(output.expandtabs(40))
--------------------------------------------------------------------------------
/coding202-parsing-json/activity-debug-1.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | uri = 'https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus'
5 |
6 |
7 | def get_content(uri):
8 | req = Request(uri)
9 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
10 | req.add_header('Accept', 'application/json')
11 | response = urlopen(req)
12 | response_string = response.read().decode("utf-8")
13 | response.close()
14 | return response_string
15 |
16 |
17 | json_object = json.loads(get_content(uri))
18 |
19 | building_names = []
20 |
21 | buildings = json_object["buildingList"]
22 | for building in buildings:
23 | building_names.append(building["name"])
24 |
25 | # Print out the building names found - this is a Python list
26 | print(building_names)
27 |
28 | # Get the content for each of the buildings found by iterating through the building list
29 | for building_name in building_names:
30 | building_uri = uri + "/" + building_name
31 | print(building_uri)
32 | print(get_content(building_uri))
33 |
--------------------------------------------------------------------------------
/coding202-parsing-json/activity-parse-1.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | req = Request('http://jsonplaceholder.typicode.com/users', headers={'User-Agent': 'Mozilla/5.0'})
5 | # req = Request('http://127.0.0.1:8000/object')
6 | # req = Request('http://127.0.0.1:8000/array')
7 | # req = Request('http://127.0.0.1:8000/random')
8 | # req = Request('http://127.0.0.1:8000/random/array')
9 | # req = Request('http://127.0.0.1:8000/complex')
10 | # req = Request('http://127.0.0.1:8000/complex/array')
11 |
12 | response = urlopen(req)
13 | response_string = response.read().decode("utf-8")
14 |
15 | json_object = json.loads(response_string)
16 |
17 | print(json_object)
18 | #print(json.dumps(json_object, sort_keys=True, indent=4))
19 | #print(json_object[4])
20 | #print(json.dumps(json_object[4], sort_keys=True, indent=4))
21 | #print(json_object[4]["name"])
22 | #print(json_object[4]["address"]["geo"])
23 | #print(json_object[4]["address"]["geo"]["lat"])
24 | #print(json_object[4]["address"]["geo"]["lng"])
25 |
26 | response.close()
27 |
--------------------------------------------------------------------------------
/coding202-parsing-json/activity-parse-2.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps')
5 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
6 | response = urlopen(req)
7 | response_string = response.read().decode('utf-8')
8 |
9 | json_object = json.loads(response_string)
10 |
11 | print(json_object['campuses'])
12 |
13 | # campuses = json_object['campuses']
14 | # for campus in campuses:
15 | # print(campus['name'])
16 | # # for building in campus['buildingList']:
17 | # # print('\t' + building['name'])
18 |
19 | response.close()
20 |
--------------------------------------------------------------------------------
/coding202-parsing-json/activity-parse-3.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus/DevNetBuilding')
5 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
6 | response = urlopen(req)
7 | response_string = response.read().decode('utf-8')
8 |
9 | json_object = json.loads(response_string)
10 |
11 | print(json_object['floorList'])
12 |
13 | # Parse out the floors from the result set
14 | # floors = json_object["floorList"]
15 | # for floor in floors:
16 | # print(floor['name'] + ' Floor Number: ' + str(floor['floorNumber']))
17 | # # Parse out the access points from the returned floors
18 | # # aps = floor["accessPoints"]
19 | # # for ap in aps:
20 | # # print('\t' + ap['name'] + '/' + ap['radioMacAddress'])
21 |
22 | response.close()
--------------------------------------------------------------------------------
/coding202-parsing-json/activity-parse-4.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | uri_cmx = 'https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/CiscoCampus'
5 |
6 |
7 | # Let's wrap our common get functionality in a function definition
8 | def get_content(uri):
9 | req = Request(uri)
10 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
11 | # req.add_header('Accept', 'application/json')
12 | response = urlopen(req)
13 | response_string = response.read().decode("utf-8")
14 | response.close()
15 | return response_string
16 |
17 |
18 | json_object = json.loads(get_content(uri_cmx))
19 |
20 | building_names = []
21 |
22 | buildings = json_object["buildingList"]
23 | for building in buildings:
24 | building_names.append(building["name"])
25 |
26 | print(building_names)
27 | print(type(building_names))
28 |
29 | # for building_name in building_names:
30 | # building_uri = uri_cmx + "/" + building_name
31 | # print(building_uri)
32 | # print(get_content(building_uri))
33 |
--------------------------------------------------------------------------------
/coding202-parsing-json/call-functions.py:
--------------------------------------------------------------------------------
1 | print ("I'm not a function")
2 |
3 | def my_function():
4 | print("Hey I'm a function!")
5 |
6 |
7 | def brett(val):
8 | for i in range(val):
9 | print("I'm a function with args!")
10 |
11 |
12 |
13 | my_function()
14 | brett(5)
--------------------------------------------------------------------------------
/coding202-parsing-json/data-type-values.py:
--------------------------------------------------------------------------------
1 | my_list=[5,'joe']
2 | print (my_list[1])
3 |
4 | my_tuple=('brett','Cisco',9)
5 | print (my_tuple[1])
6 |
7 |
8 | my_dict={"red":1,"green":2}
9 | print(my_dict["green"])
--------------------------------------------------------------------------------
/coding202-parsing-json/get-ap-json-1.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 |
3 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
4 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
5 | response = urlopen(req)
6 | response_string = response.read().decode('utf-8')
7 | print(response_string)
8 | response.close()
9 |
--------------------------------------------------------------------------------
/coding202-parsing-json/get-ap-json-2.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
5 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
6 | req.add_header('Accept', 'application/json')
7 | response = urlopen(req)
8 | response_string = response.read().decode('utf-8')
9 | # print(response_string)
10 | json_object = json.loads(response_string)
11 | print(json.dumps(json_object, sort_keys=True, indent=4))
12 | response.close()
13 |
--------------------------------------------------------------------------------
/coding202-parsing-json/get-ap-json-3.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone')
5 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
6 | req.add_header('Accept', 'application/json')
7 | response = urlopen(req)
8 | response_string = response.read().decode("utf-8")
9 | # print(responseString)
10 | json_object = json.loads(response_string)
11 | print(json_object)
12 | print(json.dumps(json_object, sort_keys=True, indent=4))
13 | access_points = json_object['accessPoints']
14 | for ap in access_points:
15 | print('Access Point: ' + ap['name'] + '\t mac: ' + ap['radioMacAddress'])
16 |
17 | response.close()
18 |
--------------------------------------------------------------------------------
/coding202-parsing-json/get-cmx-json.py:
--------------------------------------------------------------------------------
1 | from urllib.request import Request, urlopen
2 | import json
3 |
4 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps')
5 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=')
6 | req.add_header('Accept', 'application/json')
7 |
8 | response = urlopen(req)
9 | responseString = response.read().decode("utf-8")
10 |
11 | jsonObject = json.loads(responseString)
12 |
13 | print(json.dumps(jsonObject, sort_keys=True, indent=4))
14 |
15 | response.close()
16 |
--------------------------------------------------------------------------------
/coding202-parsing-json/get-tenant-json-1.py:
--------------------------------------------------------------------------------
1 | import requests
2 | # We need to import the JSON library just to handle our request to the APIC for login
3 | import json
4 |
5 |
6 | # We need to log in to the APIC and gather a token, before we can access any data
7 | # Let's construct a request with a body
8 |
9 | # We'll need to disable certificate warnings
10 | requests.packages.urllib3.disable_warnings()
11 |
12 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
13 | encoded_body = json.dumps({
14 | "aaaUser": {
15 | "attributes": {
16 | "name": "admin",
17 | "pwd": "ciscopsdt"
18 | }
19 | }
20 | })
21 |
22 | # Now lets make the request and store the data
23 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
24 |
25 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
26 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
27 |
28 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
29 | # We leverage the .xml ending to receive the data back as XML. We're adding health and faults to the printout to ensure that we get levels of data back from the APIC
30 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.json?rsp-subtree-include=health,faults", headers=header, verify=False)
31 |
32 | # Requests stores the text of the response in the .text attribute. Lets print it to see raw JSON
33 | print(tenants.text)
--------------------------------------------------------------------------------
/coding202-parsing-json/get-tenant-json-2.py:
--------------------------------------------------------------------------------
1 | import requests
2 | # We need to import the JSON library just to handle our request to the APIC for login
3 | import json
4 |
5 |
6 | # We need to log in to the APIC and gather a token, before we can access any data
7 | # Let's construct a request with a body
8 |
9 | # We'll need to disable certificate warnings
10 | requests.packages.urllib3.disable_warnings()
11 |
12 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
13 | encoded_body = json.dumps({
14 | "aaaUser": {
15 | "attributes": {
16 | "name": "admin",
17 | "pwd": "ciscopsdt"
18 | }
19 | }
20 | })
21 |
22 | # Now lets make the request and store the data
23 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
24 |
25 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
26 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
27 |
28 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
29 | # We leverage the .xml ending to receive the data back as XML. We're adding health and faults to the printout to ensure that we get levels of data back from the APIC
30 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.json?rsp-subtree-include=health,faults", headers=header, verify=False)
31 |
32 | # Requests stores the text of the response in the .text attribute. Lets print it to see raw JSON
33 | #print(tenants.text)
34 |
35 | # Lets make this response a bit prettier, by converting it to a JSON object and using the dumps method to provide indentation
36 | json_response = json.loads(tenants.text)
37 | print(json.dumps(json_response, sort_keys=True, indent=4))
--------------------------------------------------------------------------------
/coding202-parsing-json/get-tenant-json-3.py:
--------------------------------------------------------------------------------
1 | import requests
2 | # We need to import the JSON library just to handle our request to the APIC for login
3 | import json
4 |
5 |
6 | # We need to log in to the APIC and gather a token, before we can access any data
7 | # Let's construct a request with a body
8 |
9 | # We'll need to disable certificate warnings
10 | requests.packages.urllib3.disable_warnings()
11 |
12 | # We need to have a body of data consisting of a username and password to gather a cookie from APIC
13 | encoded_body = json.dumps({
14 | "aaaUser": {
15 | "attributes": {
16 | "name": "admin",
17 | "pwd": "ciscopsdt"
18 | }
19 | }
20 | })
21 |
22 | # Now lets make the request and store the data
23 | resp = requests.post("https://sandboxapicdc.cisco.com/api/aaaLogin.json", data=encoded_body, verify=False)
24 |
25 | # This stores the received APIC-cookie from the login as a value to be used in subsequent REST calls
26 | header = {"Cookie": "APIC-cookie=" + resp.cookies["APIC-cookie"]}
27 |
28 | # Now we make a call towards the tenant class on the ACI fabric with the proper header value set.
29 | # We leverage the .xml ending to receive the data back as XML. We're adding health and faults to the printout to ensure that we get levels of data back from the APIC
30 | tenants = requests.get("https://sandboxapicdc.cisco.com/api/node/class/fvTenant.json?rsp-subtree-include=health,faults", headers=header, verify=False)
31 |
32 | # Requests stores the text of the response in the .text attribute. Lets print it to see raw XML
33 | #print(tenants.text)
34 |
35 | # Lets make this response a bit prettier, by converting it to a JSON object and using the dumps method to provide indentation
36 | json_response = json.loads(tenants.text)
37 | #print(json.dumps(json_response, sort_keys=True, indent=4))
38 |
39 |
40 | # We've commented out the pretty-print, but now lets return only the values we want.
41 | # Everything within the returned JSON is containted within the `imdata` dictionary, so lets strip that away
42 | json_tenants = json_response['imdata']
43 |
44 | # Now we have to loop through the resulting list (using the `for` loop) and drill into the subsequent dictionaries by name
45 | # When we get to `tenant health`, we move from `attributes` dictionary to `children` dictionary.
46 | # Inside of the `children` dictionary is a list, which will need an index value to move further.
47 | # Since there is only one child object within the `children` list, we can safely set this value to `0`
48 | # This is the result of how the original query was structured, so don't assume you can always set that value to `0`
49 | for tenant in json_tenants:
50 | tenant_name = tenant['fvTenant']['attributes']['name']
51 | tenant_dn = tenant['fvTenant']['attributes']['dn']
52 | tenant_health = tenant['fvTenant']['children'][0]['healthInst']['attributes']['cur']
53 | output = "Tenant: " + tenant_name + "\t Health Score: " + tenant_health + "\n DN: " + tenant_dn
54 | print(output.expandtabs(40))
--------------------------------------------------------------------------------
/coding202-parsing-json/hello.py:
--------------------------------------------------------------------------------
1 |
2 | print ("Hello World!")
3 |
4 | print ("How are you?")
--------------------------------------------------------------------------------
/coding202-parsing-json/helloworld.py:
--------------------------------------------------------------------------------
1 | print ("Helloworld!")
2 |
3 | num = 1
4 |
5 | if num < 1:
6 | print ("I'm less than 1!")
7 | print ("Goodbye Cruel World!")
8 |
--------------------------------------------------------------------------------
/coding202-parsing-json/json_parse-1.py:
--------------------------------------------------------------------------------
1 | food={"vegetables":["carrots","kale","cucumber","tomato"]}
2 |
3 | cars={"sports":{"Porsche":"Volkswagen","Viper":"Dodge","Corvette":"Chevy"}}
4 |
5 |
6 |
7 | #Assignment
8 | dessert={"iceCream":["Rocky-Road","strawberry","Pistachio-Cashew","Pecan-Praline"]}
9 |
10 |
11 | superhero={"Super":("Batman","Green-Hornet", "Wonder-Woman","Superman")}
12 |
13 |
14 | soup={"soup":{"tomato":"healthy","onion":"bleh!","vegetable":"goodForYou"}}
15 |
16 |
17 | network={"Network":{"router":{"ipaddress":"192.168.1.21","mac_address":"08:56:27:6f:2b:9c"}}}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/coding202-parsing-json/json_parse-2.py:
--------------------------------------------------------------------------------
1 | network1={"Network":{"routers":[{"ipaddress":"192.168.1.21","mac_address":"08:56:27:6f:2b:9c"},{"ipaddress":"192.168.32.15","mac_address":"3a:24:37:4f:5b:1d"}],"switches":[{"ipaddress":"192.168.32.1","mac_address":"3a:24:37:4f:5b:1d"}]}}
2 |
3 | def read_network(network1):
4 | #get the device type name
5 | for device in network1["Network"]:
6 | print("Device is: " + device)
7 | #get the attributes for each device. Returns a dictionary for each
8 | for attrib in network1["Network"][device]:
9 | print("Device attributes are: " + str(attrib))
10 | #parse the attributes for each device
11 | for val in attrib:
12 | print ("Device attribute values are: " + val + " " + attrib[val])
13 | print() #add extra line for separation
14 |
15 |
16 | read_network(network1)
17 |
18 |
19 | #Assignment:
20 | network2={"Network":{"routers":[{"ipaddress":"192.168.1.21","mac_address":"08:56:27:6f:2b:9c"}],"switches":[{"ipaddress":"192.168.32.1","mac_address":"3a:24:37:4f:5b:1d"}],"hosts":[{"ipaddress":"192.168.32.5","mac_address":"3b:25:31:4a:5c:3f"},{"ipaddress":"192.168.32.8","mac_address":"4b:15:32:43:51:3c"}]}}
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/coding202-parsing-json/parse.py:
--------------------------------------------------------------------------------
1 | # 0 Type anything (Temp)
2 |
3 | # 1 Import our required libraries: Request, urlopen, json
4 |
5 | # 2 Specify our URI
6 |
7 | # 3 Setup a connection Request
8 |
9 | # 4 Add the appropriate headers to our HTTP request
10 |
11 | # 5 Do the actual request and collect the response with urlopen (Also do # 15)
12 |
13 | # 6 Store the Response string
14 |
15 | # 7 Load the JSON Object
16 |
17 | # 8 Print the JSON Object (Temp)
18 |
19 | # 9 Extract the floors from Building\Floor
20 |
21 | # 10 Loop through the Floors
22 |
23 | # 11 Print the Floor (Temp)
24 |
25 | # 12 Get the APs from the Floor
26 |
27 | # 13 Print the APs
28 |
29 | # 14 Loop through the APs printing them out
30 |
31 | # 15 Close the response
32 |
--------------------------------------------------------------------------------
/coding203-getting-input/get-input.py:
--------------------------------------------------------------------------------
1 | # Simple example of how to get input from a user
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | favorite_veg = input("What's your favorite vegetable? ")
29 | print("I like " + favorite_veg + " too!")
30 |
31 | favorite_sauce = input("What is your favorite sauce? ")
32 | print("I like " + favorite_veg + " with " + favorite_sauce + " on it!")
33 |
--------------------------------------------------------------------------------
/coding204-reading-a-file/my-file.txt:
--------------------------------------------------------------------------------
1 | This is the first line. Absolutely, the first line.
2 | This is the second line. Yep, this is the second line.
--------------------------------------------------------------------------------
/coding204-reading-a-file/my-json.json:
--------------------------------------------------------------------------------
1 | {
2 | "response": [
3 | {
4 | "id": "d4b33d28-04dd-4733-a6de-8877ec26c196",
5 | "tag": "campus",
6 | "networkDeviceId": "e5f93514-3ae5-4109-8b52-b9fa876e1eae",
7 | "attributeInfo": {}
8 | },
9 | {
10 | "id": "d4b33d28-04dd-4733-a6de-8877ec26c196",
11 | "tag": "campus",
12 | "networkDeviceId": "da733ffb-e34b-4733-bd85-b615fb7e61f3",
13 | "attributeInfo": {}
14 | },
15 | {
16 | "id": "d4b33d28-04dd-4733-a6de-8877ec26c196",
17 | "tag": "campus",
18 | "networkDeviceId": "f8c3fc68-cd26-4576-bcec-51f9b578f71e",
19 | "attributeInfo": {}
20 | }
21 | ],
22 | "version": "0.0"
23 | }
--------------------------------------------------------------------------------
/coding204-reading-a-file/read-file-loop.py:
--------------------------------------------------------------------------------
1 | # Read from a file one line at a time using a loop
2 | # amwhaley@cisco.com
3 | # twitter: @mandywhaley
4 | # http://developer.cisco.com
5 | # http://developer.cisco.com/learning
6 | # Jan 15, 2015
7 |
8 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
9 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
10 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
11 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
12 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
13 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
14 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
15 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
16 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
17 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
18 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
19 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
20 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
21 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
22 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
23 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
24 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
25 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
26 |
27 | # You can also loop through the lines and read each line in a loop.
28 | print ("Loop through and read each line")
29 | my_file_object = open("my-file.txt", "r")
30 | x=1
31 | for line in my_file_object:
32 | print ("Line " + str(x) + ": " + line)
33 | x += 1
34 |
35 | my_file_object.close()
--------------------------------------------------------------------------------
/coding204-reading-a-file/read-file-one-line.py:
--------------------------------------------------------------------------------
1 | # Read from a file one line at a time.
2 | # amwhaley@cisco.com
3 | # twitter: @mandywhaley
4 | # http://developer.cisco.com
5 | # http://developer.cisco.com/learning
6 | # Jan 15, 2015
7 |
8 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
9 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
10 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
11 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
12 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
13 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
14 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
15 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
16 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
17 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
18 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
19 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
20 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
21 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
22 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
23 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
24 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
25 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
26 |
27 | #.readline() reads in only 1 line of the file at a time.
28 | print ("Read only the first line of the file:")
29 | my_file_object = open("my-file.txt", "r")
30 | print (my_file_object.readline())
31 | print ("\n")
32 | my_file_object.close()
--------------------------------------------------------------------------------
/coding204-reading-a-file/read-file-with.py:
--------------------------------------------------------------------------------
1 | # Read from a file using the with statement
2 | # amwhaley@cisco.com
3 | # twitter: @mandywhaley
4 | # http://developer.cisco.com
5 | # http://developer.cisco.com/learning
6 | # Jan 15, 2015
7 |
8 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
9 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
10 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
11 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
12 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
13 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
14 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
15 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
16 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
17 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
18 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
19 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
20 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
21 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
22 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
23 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
24 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
25 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
26 |
27 | print ("Loop through and read each line using with to open the file")
28 | x=1
29 |
30 | # you can open the file using 'with'.
31 | # 'with' gives you better exception handling and when you use 'with' the file automatically be closed
32 | with open("my-file.txt") as file:
33 | for line in file:
34 | print ("Line " + str(x) + ": " + line)
35 | x += 1
--------------------------------------------------------------------------------
/coding204-reading-a-file/read-file.py:
--------------------------------------------------------------------------------
1 | # Most basic example of reading from a file
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 |
29 | # Use the open method to open a file
30 | # Pass in the name of the file to open and mode. 'r' for read only 'w' if you want to write to the file
31 | my_file_object = open("my-file.txt", "r")
32 |
33 | print ("Read the whole file at once:")
34 |
35 | # read() reads in the entire file. In this line of code, we read in the contents of the file and print it to the screen.
36 | print (my_file_object.read())
37 | print ("\n")
38 |
39 | # .close closes the file object
40 | my_file_object.close()
--------------------------------------------------------------------------------
/coding204-reading-a-file/read-json-from-file.py:
--------------------------------------------------------------------------------
1 | # How to read json from a file
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | # import the json library. This library provides many handy features for formatting, displaying
29 | # and manipulating json.
30 | import json
31 |
32 | # use 'with" to open the file containing json
33 | with open('my-json.json') as file:
34 | # read the whole file
35 | data = json.loads(file.read())
36 |
37 | # access values from the json and loop through devices and display the network device id
38 | i = 0
39 | for item in data["response"]:
40 | print ("Network Device ID: " + data["response"][i]["networkDeviceId"])
41 | i += 1
42 |
43 |
--------------------------------------------------------------------------------
/coding205-writing-file-ga/list-of-devices.txt:
--------------------------------------------------------------------------------
1 | id = 2dc30cac-072e-4d67-9720-cc302d02695a type = Cisco Catalyst 2960C-8PC-L Switch
2 | id = 17184480-2617-42c3-b267-4fade5f794a9 type = Cisco 3500I Unified Access Point
3 | id = 3ab14801-5c88-477d-bbb5-0aca5e5ba840 type = Cisco Catalyst 29xx Stack-able Ethernet Switch
4 |
--------------------------------------------------------------------------------
/coding205-writing-file-ga/write-file-append.py:
--------------------------------------------------------------------------------
1 | # Simple Examples of How to write to a File using with
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | print ("Writing to file..")
29 |
30 | # you can open the file using 'with'.
31 | # 'with' gives you better exception handling and when you use 'with' the file automatically be closed
32 | with open("my-new-file2.txt", "w") as file:
33 | file.write("Cisco Developers are 1337!\n")
34 | file.write("DevNet Developers rock!\n")
35 |
36 | print ("Do some stuff outside of the with block")
37 |
38 | # open the file again and append some additional text
39 | with open("my-new-file2.txt", "w") as file:
40 | file.write("Level up!\n")
41 | file.write("Go to developer.cisco.com and do more learning labs!")
--------------------------------------------------------------------------------
/coding205-writing-file-ga/write-file-using-with.py:
--------------------------------------------------------------------------------
1 | # Simple Examples of How to write to a File using with
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | print ("Writing to file..")
29 |
30 | # you can open the file using 'with'.
31 | # 'with' gives you better exception handling and when you use 'with' the file automatically be closed
32 | with open("my-new-file2.txt", "w") as file:
33 | file.write("Cisco Developers are 1337!\n")
34 | file.write("DevNet Developers rock!")
--------------------------------------------------------------------------------
/coding205-writing-file-ga/write-file.py:
--------------------------------------------------------------------------------
1 | # Most basic example of writing to a file
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | # Use the open method to open a file
29 | # Pass in the name of the file to open and mode. 'r' for read only 'w' if you want to write to the file
30 | # To write to this file we will use "w"
31 | # If the file does not exist, it will be created.
32 | my_file_object = open("my-new-file.txt", "w")
33 |
34 | my_file_object.write("The grey penguin flies at noon.")
35 |
36 | my_file_object.close()
--------------------------------------------------------------------------------
/coding205-writing-file-ga/write-json-to-file.py:
--------------------------------------------------------------------------------
1 | # Coding 205 Example
2 | # This example retrieves a list of network devices using the APIC-EM APIs
3 | # Then we write the network device ID and type for each device out to a file.
4 |
5 |
6 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
7 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
8 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
9 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
10 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
11 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
12 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
13 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
14 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
15 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
16 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
17 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
18 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
19 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
20 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
21 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
22 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
23 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
24 |
25 | # import the requests library so we can use it to make REST calls (http://docs.python-requests.org/en/latest/index.html)
26 | import requests
27 |
28 | # import the json library. This library gives us many handy features for formatting, displaying
29 | # and manipulating json.
30 | import json
31 |
32 | # All of our REST calls will use the url for the APIC EM Controller as the base URL
33 | # So lets define a variable for the controller IP or DNS so we don't have to keep typing it
34 | #controller_url = "https://sandboxapic.cisco.com"
35 | controller_url='https://devnetapi.cisco.com/sandbox/apic_em'
36 |
37 |
38 | #the username and password to access the APIC-EM Controller
39 | payload = {"username":"devnetuser","password":"Cisco123!"}
40 |
41 | ticket_url = controller_url + "/api/v1/ticket"
42 |
43 | #Content type must be included in the header
44 | header = {"content-type": "application/json"}
45 |
46 | #Performs a POST on the specified url to get the service ticket
47 | response= requests.post(ticket_url,data=json.dumps(payload), headers=header, verify=False)
48 |
49 | #convert response to json format
50 | r_json=response.json()
51 |
52 | #parse the json to get the service ticket
53 | ticket = r_json["response"]["serviceTicket"]
54 |
55 | # Get Devices
56 | # This function allows you to view a list of 3 of the devices in the network(routers and switches).
57 | get_devices_url = controller_url + '/api/v1/network-device/1/3'
58 |
59 | #Content type as well as the ticket must be included in the header
60 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
61 |
62 | #Perform GET on get_devices_url
63 | get_devices_response = requests.get(get_devices_url, headers=header, verify=False)
64 |
65 | # The json method of the response object returned by requests.get returns the request body in json format
66 | get_devices_json = get_devices_response.json()
67 |
68 | #Now let's read and display some specific information from the json
69 |
70 | # set our parent as the top level response object
71 | parent = get_devices_json["response"]
72 |
73 | print ("Devices = ")
74 | # you can open the file using 'with'.
75 | # 'with' gives you better exception handling and when you use 'with' the file automatically be closed
76 | with open("list-of-devices.txt", "w") as file:
77 | # for each device returned, write the networkDeviceId and type value to the file
78 | for item in parent:
79 | device="id = " + item["id"] + " type = " + item["type"]
80 | file.write (device + "\n")
81 | print(device)
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/coding206-logging/logging-step3.py:
--------------------------------------------------------------------------------
1 | # Simple example of how to log to a file
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | # import logging module
29 | import logging
30 |
31 | # specify that we want to log to a file named mylog.log and that we want to track messages at the DEBUG level
32 | logging.basicConfig(filename='mylog.log',level=logging.DEBUG)
33 |
34 | logging.debug('This is a debug message. We should see this in the file.')
35 | logging.info('This is an info message. We should see this in the file.')
36 | logging.warning('This is a warning message. We should see this in the file.')
--------------------------------------------------------------------------------
/coding206-logging/logging-step4.py:
--------------------------------------------------------------------------------
1 | # Formatting the messages in the logging output
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | #import the logging module
29 | import logging
30 |
31 | # specify to log to a file, specify the format for the message and the date format and the logging level
32 | logging.basicConfig(filename='mylog.log',format='%(asctime)s %(levelname)s: %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.DEBUG)
33 |
34 | # log some messages
35 | logging.debug('This is a debug message. We should see this in the file.')
36 | logging.info('This is an info message. We should see this in the file.')
37 | logging.warning('This is a warning message. We should see this in the file.')
--------------------------------------------------------------------------------
/coding206-logging/mylog.log:
--------------------------------------------------------------------------------
1 | 08/29/2016 05:53:15 PM DEBUG: This is a debug message. We should see this in the file.
2 | 08/29/2016 05:53:15 PM INFO: This is an info message. We should see this in the file.
3 | 08/29/2016 05:53:15 PM WARNING: This is a warning message. We should see this in the file.
4 |
--------------------------------------------------------------------------------
/coding206-logging/super-simple-logging.py:
--------------------------------------------------------------------------------
1 | # Simple example of how to do logging in python
2 |
3 | # amwhaley@cisco.com
4 | # twitter: @mandywhaley
5 | # http://developer.cisco.com
6 | # http://developer.cisco.com/learning
7 | # Jan 15, 2015
8 |
9 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
10 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
11 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
12 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
13 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
14 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
15 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
16 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
17 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
18 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
19 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
20 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
21 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
22 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
23 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
24 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
25 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
26 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
27 |
28 | # import the logging module
29 | import logging
30 |
31 | # uncomment the following line and you will see both messages in the console
32 | logging.basicConfig(level=logging.INFO)
33 |
34 | logging.warning('This is a warning!') # this line will print a message to the console
35 | logging.info('This is information') # this will not print anything because the default logging level is warning.
--------------------------------------------------------------------------------
/coding207-putting-it-together-ga/crap.txt:
--------------------------------------------------------------------------------
1 | The list of devices of type: switch
2 | id = 7f794dae-b5fc-4cc4-8140-c088d46c7d51 type = Cisco Catalyst 3850-48U-E Switch
3 | id = 4418bd65-ce35-454c-a862-6db074f99030 type = Cisco Catalyst 6503 Switch
4 | id = 9222791a-95cf-4ae3-b498-6ac72d0074f4 type = Cisco Catalyst 6503 Switch
5 | id = 0c3aa565-233a-4843-9f5e-8a70f77e1853 type = Cisco Catalyst 4507R plus E Switch
6 | id = 19a333ba-52ee-49eb-90c2-4dc9ab05b47f type = Cisco Catalyst 4507R plus E Switch
7 |
--------------------------------------------------------------------------------
/coding207-putting-it-together-ga/create-device-list.py:
--------------------------------------------------------------------------------
1 | # Coding 207 - Putting it all together example
2 | # Asks the user to choose router or switch
3 | # Retrieves list of devices using APIC-EM
4 | # Writes list of devices of selected type to a file
5 |
6 |
7 | # * THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
8 | # * OF ANY KIND BY CISCO, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
9 | # * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR
10 | # * PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE OF
11 | # * DEALING, LAW, USAGE, OR TRADE PRACTICE. CISCO TAKES NO RESPONSIBILITY
12 | # * REGARDING ITS USAGE IN AN APPLICATION, AND IT IS PRESENTED ONLY AS AN
13 | # * EXAMPLE. THE SAMPLE CODE HAS NOT BEEN THOROUGHLY TESTED AND IS PROVIDED AS AN
14 | # * EXAMPLE ONLY, THEREFORE CISCO DOES NOT GUARANTEE OR MAKE ANY REPRESENTATIONS
15 | # * REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION. IN NO EVENT DOES
16 | # * CISCO WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE
17 | # * TO OPERATE THE SOFTWARE WITHOUT PROBLEMS OR INTERRUPTIONS. NOR DOES CISCO
18 | # * WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE SOFTWARE IS USED WILL
19 | # * BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK. THIS SAMPLE APPLICATION IS
20 | # * NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY
21 | # * ARISING FROM THE USE OF THE APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO
22 | # * OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR CONSEQUENTIAL DAMAGES, LOST
23 | # * PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
24 | # * SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.-->
25 |
26 | # import requests library
27 | import requests
28 |
29 | #import json library
30 | import json
31 |
32 | #import logging library
33 | import logging
34 |
35 | # Disable warnings
36 | requests.packages.urllib3.disable_warnings()
37 |
38 |
39 | # All of our REST calls will use the url for the APIC EM Controller as the base URL
40 | #controller_url = "https://sandboxapic.cisco.com"
41 | controller_url='https://devnetapi.cisco.com/sandbox/apic_em'
42 |
43 |
44 | def getUserInput():
45 | #turn on logging to the mylog.log file
46 | logging.basicConfig(filename='mylog.log',format='%(asctime)s %(levelname)s: %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.DEBUG)
47 |
48 | logging.info("Begin")
49 | logging.info("Asking user for device type")
50 |
51 | # Ask the user what kind of list they want to create
52 | device_type = input("Do you want to create a list of [r]outers or [s]witches?")
53 |
54 | # create a variable called type to hold which kind of device to save
55 | if device_type == 'r':
56 | type = "router"
57 | else:
58 | type = "switch"
59 |
60 | logging.info("Device type is " + type)
61 |
62 | # Ask user for name of the file
63 | file_name = input("Specify the file name to use for the list:")
64 |
65 | logging.info("Will save device list to " + file_name)
66 |
67 | return(type,file_name)
68 |
69 |
70 | #creates and returns a service ticket.
71 | def getTicket():
72 | logging.info("\nCreating ticket")
73 | # put the ip address or dns of your apic-em controller in this url
74 | url = controller_url + "/api/v1/ticket"
75 |
76 | #the username and password to access the APIC-EM Controller
77 | payload = {"username":"devnetuser","password":"Cisco123!"}
78 |
79 | #Content type must be included in the header
80 | header = {"content-type": "application/json"}
81 |
82 | #Performs a POST on the specified url to get the service ticket
83 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False)
84 |
85 | logging.info(response.text)
86 |
87 | #convert response to json format
88 | r_json=response.json()
89 |
90 | #parse the json to get the service ticket
91 | ticket = r_json["response"]["serviceTicket"]
92 |
93 | return ticket
94 |
95 |
96 | def getDeviceCount(ticket):
97 | # Specify URL for the devices count
98 | devices_count_url = controller_url + '/api/v1/network-device/count'
99 |
100 | logging.info("Calling APIC-EM API url:" + devices_count_url)
101 |
102 | #Content type as well as the ticket must be included in the header
103 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
104 |
105 | # Perform GET on devices_count_url
106 | devices_count_response = requests.get(devices_count_url, headers=header, verify=False)
107 | count = devices_count_response.json()["response"]
108 |
109 | logging.debug("API response: " + json.dumps(devices_count_response.json(), indent=4, separators=(',', ': ')))
110 |
111 | return count
112 |
113 |
114 | # Get Devices
115 | # This function allows you to view a list of all the devices in the network(routers and switches) with the maximum shown specified by the passed in count variable
116 | def getDevices(ticket,count,type,file_name):
117 | get_devices_url = controller_url + '/api/v1/network-device/1/' + str(count)
118 |
119 | logging.info("Calling APIC-EM API url:" + get_devices_url)
120 |
121 | #Content type as well as the ticket must be included in the header
122 | header = {"content-type": "application/json", "X-Auth-Token":ticket}
123 |
124 | #Perform GET on get_devices_url
125 | get_devices_response = requests.get(get_devices_url, headers=header, verify=False)
126 |
127 | # The json method of the response object returned by requests.get returns the request body in json format
128 | get_devices_json = get_devices_response.json()
129 |
130 | logging.debug("API response: " + json.dumps(get_devices_json, indent=4, separators=(',', ': ')))
131 |
132 | #Now let's parse the json and write the devices out to our file
133 | file= open(file_name, "w")
134 | logging.info("File opened:" + file_name)
135 | logging.info("Begin writing list:" + file_name)
136 | file.write ("The list of devices of type: " + type + "\n" )
137 |
138 | # set our parent as the top level response object
139 | parent = get_devices_json["response"]
140 |
141 | # for each device returned, write the networkDeviceId and type value to the file if the type corresponds to what we're seeking.
142 | for item in parent:
143 | lowerCaseType=item["type"].lower()
144 | if lowerCaseType.find(type)!=-1:
145 | file.write ("id = " + item["id"] + " type = " + item["type"] + "\n")
146 |
147 | print ("Finished writing list ...")
148 | logging.info("End writing list:" + file_name)
149 |
150 |
151 | (theType,theFilename)=getUserInput()
152 | theTicket=getTicket()
153 | theCount=getDeviceCount(theTicket)
154 | getDevices(theTicket,theCount,theType,theFilename)
155 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.2)
2 |
3 | project(AllProjects)
4 | include(activity-1.cmake)
5 | include(activity-2.cmake)
6 | include(activity-3.cmake)
7 | include(activity-4.cmake)
8 | include(activity-5.cmake)
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/README.md:
--------------------------------------------------------------------------------
1 | # coding210-parsing-json-c++
2 | This is sample code for the parsing JSON using C++.
3 |
4 | ## Requirements ##
5 |
6 | ### Windows ###
7 | #### Installing Cygwin ####
8 |
9 | Install Cygwin and make sure you select the following packages: gcc-g++, openssl-devel, libssh2-devel, libcurl-devel, libcurl4
10 |
11 | You may need to close and reopen your console window to pickup the changes to the Windows environment.
12 |
13 | ## Instructions ##
14 |
15 | ### Get libcurl URL library
16 | To get a local copy of the required libcurl headers, execute the following command:
17 |
18 | git clone https://github.com/bagder/curl.git
19 |
20 |
21 | ### Get RapidJSON parser/generator ###
22 | To get a local copy of the required RapidJSON headers, execute the following command:
23 |
24 | git clone https://github.com/miloyip/rapidjson.git
25 |
26 |
27 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/activity-1.cmake:
--------------------------------------------------------------------------------
1 |
2 | project(coding210_parsing_json_cpp_activity_1)
3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
4 |
5 |
6 |
7 | # hello
8 | set(SOURCE_FILES
9 | hello.cpp)
10 |
11 | add_executable(coding210_1_hello ${SOURCE_FILES})
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/activity-2.cmake:
--------------------------------------------------------------------------------
1 |
2 | project(coding210_parsing_json_cpp_activity_2)
3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
4 |
5 |
6 |
7 | # main-http
8 | set(SOURCE_FILES
9 | main-http.cpp)
10 |
11 | add_executable(coding210_2_main_http ${SOURCE_FILES})
12 | target_link_libraries(coding210_2_main_http curl)
13 |
14 |
15 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/activity-3.cmake:
--------------------------------------------------------------------------------
1 |
2 | project(coding210_parsing_json_cpp_activity_3)
3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
4 |
5 |
6 |
7 | # main-http
8 | set(SOURCE_FILES
9 | main-json.cpp)
10 |
11 | add_executable(coding210_3_main_json ${SOURCE_FILES})
12 | target_link_libraries(coding210_3_main_json curl)
13 |
14 |
15 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/activity-4.cmake:
--------------------------------------------------------------------------------
1 |
2 | project(coding210_parsing_json_cpp_activity_4)
3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
4 |
5 | include_directories("rapidjson/include")
6 |
7 | # main-http
8 | set(SOURCE_FILES
9 | main-json-lib.cpp)
10 |
11 | add_executable(coding210_4_main_json_lib ${SOURCE_FILES})
12 | target_link_libraries(coding210_4_main_json_lib curl)
13 |
14 |
15 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/activity-5.cmake:
--------------------------------------------------------------------------------
1 |
2 | project(coding210_parsing_json_cpp_activity_5)
3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
4 |
5 | include_directories("rapidjson/include")
6 |
7 | # main
8 | set(SOURCE_FILES
9 | main.cpp)
10 |
11 | add_executable(coding210_5_main ${SOURCE_FILES})
12 | target_link_libraries(coding210_5_main curl)
13 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/hello.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main()
4 | {
5 | std::cout << "Hello World!\n";
6 | std::cout << "How are you?\n";
7 |
8 | return 0;
9 | }
10 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/hello.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | public class HelloWorld
4 | {
5 | static public void Main()
6 | {
7 | Console.WriteLine("Hello World!");
8 | Console.WriteLine("How are you?");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/main-annotated.cpp:
--------------------------------------------------------------------------------
1 | // Include the headers needed for the input/output, cURL, and RapidJSON functionality
2 | #include
3 | #include
4 | #include "curl/curl.h"
5 | #include "curl/easy.h"
6 | #include "rapidjson/document.h"
7 | #include "rapidjson/writer.h"
8 | #include "rapidjson/stringbuffer.h"
9 |
10 | // Declare the namespaces we intend to use
11 | using namespace std;
12 | using namespace rapidjson;
13 |
14 | // Define a structure to hold our file and string information for the callback data
15 | struct JSONDATA
16 | {
17 | fstream *file;
18 | string *str;
19 | };
20 |
21 | // The callback function used by cURL to write our file
22 | size_t write_data(void *ptr, size_t size, size_t nmemb, JSONDATA *data) {
23 |
24 | size_t numBytes = size * nmemb;
25 |
26 | if (data->file)
27 | data->file->write((char*)ptr, numBytes);
28 |
29 | if (data->str)
30 | *(data->str) += std::string((char*)ptr, numBytes);
31 |
32 | return numBytes;
33 | }
34 |
35 | // The main function of the application
36 | int main() {
37 |
38 | CURL *curl;
39 | CURLcode res;
40 |
41 | // The URI we intend to access
42 | string uri = "https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone";
43 |
44 | // The Authorization header with learning:learning base64 encoded for the user:password
45 | string header_authorization = "Authorization: Basic bGVhcm5pbmc6bGVhcm5pbmc=";
46 |
47 | // The Accept header specifying we would like JSON data returned to us from the server
48 | string header_accept = "Accept: application/json";
49 |
50 | // Add the headers to a list for cURL to use
51 | struct curl_slist *headers = NULL;
52 | headers = curl_slist_append(headers, header_authorization.c_str());
53 | headers = curl_slist_append(headers, header_accept.c_str());
54 |
55 | // Initialize cURL
56 | curl = curl_easy_init();
57 |
58 | // Declare a file called content.json
59 | fstream file("content.json", ios_base::out | ios_base::ate);
60 |
61 | // A string to store our json output
62 | string json;
63 |
64 | // An instance of our JSONDATA structure
65 | JSONDATA data;
66 | data.file = &file;
67 | data.str = &json;
68 |
69 | // If we have a valid cURL instance we can proceed
70 | if (curl) {
71 |
72 | // Set the cURL options for the URI, headers, the callback function, and callback data
73 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
74 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
75 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
76 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
77 |
78 | // Actually have cURL perform the request
79 | res = curl_easy_perform(curl);
80 |
81 | // Check to see if we received an OK from cURL
82 | if(res != CURLE_OK)
83 | cerr << "ERROR: " << curl_easy_strerror(res) << endl;
84 | else {
85 |
86 | // Create a RapidJSON document and parse the received JSON into it
87 | Document document;
88 | document.Parse(json.c_str());
89 |
90 | // Get the Floor\AccessPoint value from the JSON
91 | Value& accessPoint = document["Floor"]["AccessPoint"];
92 |
93 | // Check to verify we got an array of access point values in the JSON
94 | assert(accessPoint.IsArray());
95 |
96 | // Iterate through the Access Points, printing their name
97 | for (SizeType i = 0; i < accessPoint.Size(); i++)
98 | printf("accessPoint: %s\n", accessPoint[i]["name"].GetString());
99 | }
100 |
101 | // Cleanup the cURL instance
102 | curl_easy_cleanup(curl);
103 | }
104 |
105 | // Return a success value from our application
106 | return 0;
107 | }
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/main-http.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "curl/curl.h"
3 | #include "curl/easy.h"
4 |
5 | using namespace std;
6 |
7 | int main() {
8 |
9 | string uri = "http://www.cisco.com";
10 |
11 | CURLcode res;
12 | CURL *curl = curl_easy_init();
13 | if(curl) {
14 |
15 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
16 | res = curl_easy_perform(curl);
17 |
18 | if(res != CURLE_OK)
19 | cerr << "ERROR: " << curl_easy_strerror(res) << endl;
20 | else {
21 | // We should have received data from the URI
22 | }
23 |
24 | curl_easy_cleanup(curl);
25 | }
26 |
27 | return 0;
28 | }
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/main-json-lib.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "curl/curl.h"
4 | #include "curl/easy.h"
5 | #include "rapidjson/document.h"
6 | #include "rapidjson/prettywriter.h"
7 | #include "rapidjson/stringbuffer.h"
8 |
9 | using namespace std;
10 | using namespace rapidjson;
11 |
12 | struct JSONDATA
13 | {
14 | fstream *file;
15 | string *str;
16 | };
17 |
18 | size_t write_data(void *ptr, size_t size, size_t nmemb, JSONDATA *data) {
19 |
20 | size_t numBytes = size * nmemb;
21 |
22 | if (data->file)
23 | data->file->write((char*)ptr, numBytes);
24 |
25 | if (data->str)
26 | *(data->str) += std::string((char*)ptr, numBytes);
27 |
28 | return numBytes;
29 | }
30 |
31 | int main() {
32 |
33 | CURL *curl;
34 | CURLcode res;
35 |
36 | string uri = "https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone";
37 | string header_authorization = "Authorization: Basic bGVhcm5pbmc6bGVhcm5pbmc=";
38 | string header_accept = "Accept: application/json";
39 |
40 | struct curl_slist *headers = NULL;
41 | headers = curl_slist_append(headers, header_authorization.c_str());
42 | headers = curl_slist_append(headers, header_accept.c_str());
43 |
44 | curl = curl_easy_init();
45 |
46 | fstream file("content.json", ios_base::out | ios_base::ate);
47 | string json;
48 |
49 | JSONDATA data;
50 | data.file = &file;
51 | data.str = &json;
52 |
53 | if(curl) {
54 |
55 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
56 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
57 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
58 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
59 |
60 | res = curl_easy_perform(curl);
61 |
62 | if(res != CURLE_OK)
63 | cerr << "ERROR: " << curl_easy_strerror(res) << endl;
64 | else {
65 |
66 | Document document;
67 | document.Parse(json.c_str());
68 |
69 | StringBuffer buffer;
70 | PrettyWriter writer(buffer);
71 | document.Accept(writer);
72 |
73 | cout << buffer.GetString() << endl;
74 | }
75 |
76 | curl_easy_cleanup(curl);
77 | }
78 |
79 | return 0;
80 | }
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/main-json.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "curl/curl.h"
3 | #include "curl/easy.h"
4 |
5 | using namespace std;
6 |
7 | int main() {
8 |
9 | string uri = "https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone";
10 | string header_authorization = "Authorization: Basic bGVhcm5pbmc6bGVhcm5pbmc=";
11 | string header_accept = "Accept: application/json";
12 |
13 | struct curl_slist *headers = NULL;
14 | headers = curl_slist_append(headers, header_authorization.c_str());
15 | headers = curl_slist_append(headers, header_accept.c_str());
16 |
17 | CURLcode res;
18 | CURL *curl = curl_easy_init();
19 | if(curl) {
20 |
21 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
22 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
23 | res = curl_easy_perform(curl);
24 |
25 | if(res != CURLE_OK)
26 | cerr << "ERROR: " << curl_easy_strerror(res) << endl;
27 | else {
28 | // We should have received data from the URI
29 | }
30 |
31 | curl_easy_cleanup(curl);
32 | }
33 |
34 | return 0;
35 | }
--------------------------------------------------------------------------------
/coding210-parsing-json-c++/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "curl/curl.h"
4 | #include "curl/easy.h"
5 | #include "rapidjson/document.h"
6 | #include "rapidjson/writer.h"
7 | #include "rapidjson/stringbuffer.h"
8 |
9 | using namespace std;
10 | using namespace rapidjson;
11 |
12 | struct JSONDATA
13 | {
14 | fstream *file;
15 | string *str;
16 | };
17 |
18 | size_t write_data(void *ptr, size_t size, size_t nmemb, JSONDATA *data) {
19 |
20 | size_t numBytes = size * nmemb;
21 |
22 | if (data->file)
23 | data->file->write((char*)ptr, numBytes);
24 |
25 | if (data->str)
26 | *(data->str) += std::string((char*)ptr, numBytes);
27 |
28 | return numBytes;
29 | }
30 |
31 | int main() {
32 |
33 | CURL *curl;
34 | CURLcode res;
35 |
36 | string uri = "https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone";
37 | string header_authorization = "Authorization: Basic bGVhcm5pbmc6bGVhcm5pbmc=";
38 | string header_accept = "Accept: application/json";
39 |
40 | struct curl_slist *headers = NULL;
41 | headers = curl_slist_append(headers, header_authorization.c_str());
42 | headers = curl_slist_append(headers, header_accept.c_str());
43 |
44 | curl = curl_easy_init();
45 |
46 | fstream file("content.json", ios_base::out | ios_base::ate);
47 | string json;
48 |
49 | JSONDATA data;
50 | data.file = &file;
51 | data.str = &json;
52 |
53 | if(curl) {
54 |
55 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
56 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
57 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
58 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
59 |
60 | res = curl_easy_perform(curl);
61 |
62 | if(res != CURLE_OK)
63 | cerr << "ERROR: " << curl_easy_strerror(res) << endl;
64 | else {
65 |
66 | Document document;
67 | document.Parse(json.c_str());
68 |
69 | Value& accessPoint = document["Floor"]["AccessPoint"];
70 | assert(accessPoint.IsArray());
71 |
72 | // Iterate through the Access Points
73 | for (SizeType i = 0; i < accessPoint.Size(); i++)
74 | printf("accessPoint: %s\n", accessPoint[i]["name"].GetString());
75 | }
76 |
77 | curl_easy_cleanup(curl);
78 | }
79 |
80 | return 0;
81 | }
--------------------------------------------------------------------------------
/content-serve/content-server.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python
2 |
3 | import http.server
4 | import random
5 |
6 | server_ip = "127.0.0.1"
7 | server_port = 8000
8 |
9 |
10 | class CustomRequestHandler(http.server.BaseHTTPRequestHandler):
11 | def do_GET(self):
12 |
13 | route_path = self.path.rstrip("/")
14 |
15 | # print(route_path)
16 | if route_path == '/object':
17 | self.send_response(200)
18 | self.write_object()
19 | elif route_path == '/array':
20 | self.send_response(200)
21 | self.write_array()
22 | elif route_path == '/random':
23 | self.send_response(200)
24 | self.write_random()
25 | elif route_path == '/random/array':
26 | self.send_response(200)
27 | self.write_random_array()
28 | elif route_path == '/complex':
29 | self.send_response(200)
30 | self.write_complex()
31 | elif route_path == '/complex/array':
32 | self.send_response(200)
33 | self.write_complex_array()
34 | else:
35 | # Otherwise send a default response
36 | self.send_response(200)
37 | self.send_header('Content-type', 'text/html')
38 | self.end_headers()
39 | self.wfile.write(open("./data/index.html", "rb").read())
40 |
41 | return
42 |
43 | def write_object(self):
44 | self.send_header('Content-type', 'application/json')
45 | self.end_headers()
46 | self.wfile.write(b'{ "first_name": "Mike", "last_name": "Maas" }')
47 |
48 | def write_array(self):
49 | self.send_header('Content-type', 'application/json')
50 | self.end_headers()
51 | self.wfile.write(b'[{ "first_name": "Mike", "last_name": "Maas" }, { "first_name": "Matt", "last_name": "Denapoli" }]')
52 |
53 | def write_complex(self):
54 | self.send_header('Content-type', 'application/json')
55 | self.end_headers()
56 | self.wfile.write(open("./data/complex.json", "rb").read())
57 |
58 | def write_complex_array(self):
59 | self.send_header('Content-type', 'application/json')
60 | self.end_headers()
61 | self.wfile.write(open("./data/complex-array.json", "rb").read())
62 |
63 | def write_random(self):
64 | self.send_header('Content-type', 'application/json')
65 | self.end_headers()
66 | result = '{"value":' + str(random.randrange(0, 100, 1)) + '}'
67 | self.wfile.write(bytes(result, "utf-8"))
68 |
69 | def write_random_array(self):
70 | self.send_header('Content-type', 'application/json')
71 | self.end_headers()
72 |
73 | # Construct a JSON array with random entries
74 | values = []
75 | value_count = random.randint(0, 15)
76 | for element in range(0, value_count):
77 | value = '{{ "{}" : {}, "value" : {} }}'.format("id", element, str(random.randrange(0, 100, 1)))
78 | values.append(value)
79 |
80 | result = '[' + ', '.join(values) + ']'
81 | self.wfile.write(bytes(result, "utf-8"))
82 |
83 |
84 | def run():
85 | # Set the server settings
86 | server_address = (server_ip, server_port)
87 | httpd = http.server.HTTPServer(server_address, CustomRequestHandler)
88 | print("Serving content at http://" + server_ip + ":" + str(server_port))
89 | httpd.serve_forever()
90 |
91 |
92 | if __name__ == '__main__':
93 | run()
94 |
--------------------------------------------------------------------------------
/content-serve/data/complex-array.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "order": {
4 | "placed": "2017-01-01T00:00:00+00:00",
5 | "priority" : 1,
6 | "user": {
7 | "id": 1,
8 | "first_name": "Mike",
9 | "last_name": "Maas"
10 | },
11 | "product": {
12 | "sku": "TS007-XL-001",
13 | "location": {
14 | "container" : 9,
15 | "shelf": 4,
16 | "slot" : 6,
17 | "coordinates": [
18 | {
19 | "x": 11
20 | },
21 | {
22 | "y": 44
23 | },
24 | {
25 | "z": -4
26 | }
27 | ]
28 | },
29 | "price": 9.99,
30 | "tags": [
31 | "t-shirt",
32 | "black"
33 | ]
34 | }
35 | }
36 | },
37 | {
38 | "order": {
39 | "placed": "2016-01-01T00:00:00+00:00",
40 | "priority" : 3,
41 | "user": {
42 | "id": 2,
43 | "first_name": "Matt",
44 | "last_name": "Denapoli"
45 | },
46 | "product": {
47 | "sku": "TS009-XL-003",
48 | "location": {
49 | "container" : 9,
50 | "shelf": 4,
51 | "slot" : 5,
52 | "coordinates": [
53 | {
54 | "x": 11
55 | },
56 | {
57 | "y": 44
58 | },
59 | {
60 | "z": -4
61 | }
62 | ]
63 | },
64 | "price": 8.99,
65 | "tags": [
66 | "t-shirt",
67 | "blue"
68 | ]
69 | }
70 | }
71 | },
72 | {
73 | "order": {
74 | "placed": "2015-01-01T00:00:00+00:00",
75 | "priority" : 2,
76 | "user": {
77 | "id": 3,
78 | "first_name": "Ashley",
79 | "last_name": "Roach"
80 | },
81 | "product": {
82 | "sku": "TS003-L-001",
83 | "location": {
84 | "container" : 8,
85 | "shelf": 5,
86 | "slot" : 2,
87 | "coordinates": [
88 | {
89 | "x": 9
90 | },
91 | {
92 | "y": 34
93 | },
94 | {
95 | "z": -5
96 | }
97 | ]
98 | },
99 | "price": 12.99,
100 | "tags": [
101 | "t-shirt",
102 | "salmon"
103 | ]
104 | }
105 | }
106 | }
107 | ]
--------------------------------------------------------------------------------
/content-serve/data/complex.json:
--------------------------------------------------------------------------------
1 | {
2 | "order": {
3 | "placed" : "2017-01-01T00:00:00+00:00",
4 | "priority" : 1,
5 | "user": {
6 | "id": 1,
7 | "first_name": "Mike",
8 | "last_name": "Maas"
9 | },
10 | "product": {
11 | "sku": "TS007-XL-001",
12 | "location": {
13 | "container" : 9,
14 | "shelf" : 4,
15 | "slot" : 6,
16 | "coordinates": [
17 | {
18 | "x": 11
19 | },
20 | {
21 | "y": 44
22 | },
23 | {
24 | "z": -4
25 | }
26 | ]
27 | },
28 | "price": 9.99,
29 | "tags": [
30 | "t-shirt",
31 | "blue"
32 | ]
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/content-serve/data/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Content Server
6 |
7 |
8 |
9 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # How to contribute to a Learning Lab
2 |
3 | For Learning Labs, there are a few primary ways to help:
4 | - Testing the Learning Lab and then reporting issues in the repo or in the common issues tracking repo
5 | - Using the Issue tracker to report issues or comment that you will work on an issue
6 | - Updating the content in the Learning Lab repo
7 | - Requesting or creating a release
8 | - Contacting DevNet to publish new or updated Learning Labs
9 |
10 | ## Using the issue tracker
11 |
12 | For Learning Labs, there are two potential places to track issues, depending on
13 | whether the repo is a public or private repo.
14 |
15 | For public repo Learning Labs, use the issue tracker in the repo. All Learning Labs repos in the CiscoDevNet organization have a topic of `learning-labs`.
16 |
17 | For private Learning Labs, use the common Issue tracker in the [CiscoDevNet/learning-labs-issues](https://github.com/CiscoDevNet/learning-labs-issues) repo.
18 |
19 | For DevNet Express events, use these Issue tracker repos based on the content track:
20 | * https://github.com/CiscoDevNet/devnet-express-dna-issues
21 | * https://github.com/CiscoDevNet/devnet-express-cc-issues
22 | * https://github.com/CiscoDevNet/devnet-express-dci-issues
23 | * https://github.com/CiscoDevNet/devnet-express-security-issues
24 |
25 | Use the issue tracker to suggest additions, report bugs, and ask questions.
26 | This is also a great way to connect with the developers of the project as well
27 | as others who are interested in this solution.
28 |
29 | Also use the issue tracker to find ways to contribute. Test a lab, find a bug,
30 | log an issue, or offer an update, comment on the issue that you will take on
31 | that effort, then follow the _Changing the Learning Lab content_ guidance below.
32 |
33 | ## Changing the Learning Lab content
34 |
35 | Generally speaking, you should clone the Learning Lab repository, make changes locally, and then submit a pull request (PR). All new content should be tested
36 | to validate that documented tasks work correctly. Additionally, the content
37 | should follow the [Learning Lab Style Guide](https://github.com/CiscoDevNet/devnet-writing-guidelines/wiki/Lab-Style-Guide).
38 |
39 | The [DevNet Writing Guidelines Wiki](https://github.com/CiscoDevNet/devnet-writing-guidelines/wiki)
40 | describes the review and publishing process in detail. Please feel free to request reviews from DevNet contributors you see in the repository and we will review submissions.
41 |
--------------------------------------------------------------------------------