├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── contributing.md └── labs ├── coding-101-rest-basics-ga ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── 7.md ├── 8.md ├── assets │ └── images │ │ ├── Menu.png │ │ ├── RESTisGreat.jpg │ │ ├── Ref.png │ │ ├── apic-em-Gen-request.jpg │ │ ├── apic-em-main.png │ │ ├── apic-em-request.png │ │ ├── apic-em1.jpg │ │ ├── apic-emHostRequest.png │ │ ├── howitworks.jpg │ │ ├── login.png │ │ ├── postman1.png │ │ ├── postman2.png │ │ ├── postman3.png │ │ ├── postman4.png │ │ ├── postman5.png │ │ ├── postman6.png │ │ ├── postman7.png │ │ ├── refguide1.png │ │ ├── refguide4.png │ │ ├── refguide5.png │ │ ├── register.png │ │ ├── ssl1.png │ │ ├── ssl2.png │ │ └── ssl3.png ├── byod.html └── coding-101-rest-basics-ga.json ├── coding-102-rest-python-ga ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── assets │ └── images │ │ ├── Menu.png │ │ ├── Ref.png │ │ ├── build-topology.png │ │ ├── create-ticket.png │ │ ├── create_directory.png │ │ ├── get-devices.png │ │ ├── get-hosts.png │ │ ├── github-clone-listing.png │ │ ├── github-clone.png │ │ ├── login.png │ │ ├── register.png │ │ ├── topology-graph.png │ │ ├── web-flow.png │ │ └── webapp-start.png ├── byod.html └── coding-102-rest-python-ga.json ├── coding-201-parsing-xml ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── assets │ └── images │ │ ├── xml-output-new.png │ │ ├── xml-output-parse-001-new.png │ │ ├── xml-output-parse-001.png │ │ ├── xml-output-parse-002-new.png │ │ ├── xml-output-parse-002.png │ │ ├── xml-output-pretty-new.png │ │ ├── xml-output-pretty.png │ │ └── xml-output.png ├── byod.html ├── coding-201-parsing-xml.json ├── get-ap-xml.py └── get-tenants-xml.py ├── coding-202-parsing-json ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── assets │ └── images │ │ ├── json-output-new.png │ │ ├── json-output-parse-001-new.png │ │ ├── json-output-parse-001.png │ │ ├── json-output-pretty-new.png │ │ ├── json-output-pretty.png │ │ └── json-output.png ├── byod.html ├── coding-202-parsing-json.json └── get-ap-json.py ├── coding-203-getting-input ├── 1.md ├── 2.md ├── assets │ └── images │ │ └── step2-results.jpg ├── byod.html └── coding-203-getting-input.json ├── coding-204-reading-a-file ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── assets │ └── images │ │ ├── step2-results.jpg │ │ ├── step3-results.jpg │ │ ├── step4-results.jpg │ │ ├── step5-results.jpg │ │ └── step6-results.jpg ├── byod.html └── coding-204-reading-a-file.json ├── coding-205-writing-file-ga ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── assets │ └── images │ │ ├── github-clone-listing.png │ │ ├── github-clone.png │ │ ├── step2-results.jpg │ │ ├── step3-results.jpg │ │ ├── step4-results.jpg │ │ ├── step4a-results.jpg │ │ └── step5-results.jpg ├── byod.html └── coding-205-writing-file-ga.json ├── coding-206-logging ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── assets │ └── images │ │ ├── step1-results.jpg │ │ ├── step2-results.jpg │ │ ├── step2a-results.jpg │ │ ├── step2b-results.jpg │ │ ├── step3-results.jpg │ │ └── step4-results.jpg ├── byod.html └── coding-206-logging.json ├── coding-207-putting-it-together-ga ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── assets │ └── images │ │ ├── Menu.png │ │ ├── Ref.png │ │ ├── create-device-list-1.png │ │ ├── create-device-list-2.png │ │ ├── create-device-list-3.png │ │ ├── create-device-list-4.png │ │ ├── github-clone-listing.png │ │ ├── github-clone.png │ │ ├── login.png │ │ └── register.png ├── byod.html └── coding-207-putting-it-together-ga.json ├── coding-210-parsing-json-c++ ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── byod.html ├── coding-210-parsing-json-c++.json ├── command-compile.txt └── setup-cygwin-select-libcurl.png ├── parsing-json ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── assets │ └── images │ │ ├── json-output-new.png │ │ ├── json-output-parse-001-new.png │ │ ├── json-output-parse-001.png │ │ ├── json-output-pretty-new.png │ │ ├── json-output-pretty.png │ │ └── json-output.png ├── byod.html ├── get-ap-json.py └── parsing-json.json └── parsing-xml ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── assets └── images │ ├── xml-output-new.png │ ├── xml-output-parse-001-new.png │ ├── xml-output-parse-001.png │ ├── xml-output-parse-002-new.png │ ├── xml-output-parse-002.png │ ├── xml-output-pretty-new.png │ ├── xml-output-pretty.png │ └── xml-output.png ├── byod.html ├── get-ap-xml.py ├── get-tenants-xml.py └── parsing-xml.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | venv/ 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | preview: 2 | docker run -p "9000:9000" -p "35729:35729" \ 3 | -v $(CURDIR)/labs:/opt/labs \ 4 | containers.cisco.com/asroach/learning-labs-previewer:latest 5 | open http://localhost:9000 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Cisco DevNet Learning Labs: Coding Fundamentals 2 | 3 | These self-paced interactive tutorials provide an introduction to coding. 4 | 5 | Labs are written to be 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 | Once approved, Cisco DevNet reviewers then create a release that is published through our Learning Labs system. 10 | 11 | The goal of these Learning Labs is to ensure a 'hands-on' learning approach rather than just theory or instructions. 12 | 13 | ## About these Learning Labs 14 | 15 | These Learning Labs are for building your home networking lab for network programmability. 16 | 17 | If you need more help, reach out to DevNet through one of our [support options](https://developer.cisco.com/site/devnet/support/). 18 | 19 | ## Preview Learning Lab Markdown locally 20 | 21 | Refer to the instruction for your text editor for Markdown previewing. For example, [Markdown and Visual Studio Code](https://code.visualstudio.com/Docs/languages/markdown) describes how to configure Markdown extensions. 22 | 23 | ## Contributing 24 | 25 | These learning modules are for public consumption, so you must ensure that you have the rights to any content that you contribute. 26 | 27 | Write your content in Markdown. DevNet staff reviews content according to the [Cisco Style Guide](http://www-author.cisco.com/c/en/us/td/docs/general/style/guide/Latest/stylegd.html). (Link available on Cisco VPN only.) 28 | 29 | #### Publishing requirements 30 | 31 | To create and publish a new lab, take the following steps: 32 | - Add a new folder under `labs`. 33 | - Create a JSON file with the same name as the `labs/`_folder_ name. 34 | - Create markdown files named 1.md, 2.md, and so on; refer to those files in the `labs/`_folder_ JSON file. 35 | - Ensure that the JSON file contains appropriate page titles and file references. 36 | - Send a pull request to get the files committed and merged to the default branch by a DevNet reviewer. 37 | 38 | A DevNet reviewer then creates a release on the repository with the latest changes and publishes through the admin interface. 39 | 40 | #### Editors 41 | 42 | You can write Markdown in a plain text editor, but there are many desktop and Web-based options that allow you to write and preview your work at the same time. We recommend Visual Studio Code [Download](https://code.visualstudio.com/) for several reasons: 43 | - Lightweight environment for coding (or writing Markdown) 44 | - Available on Mac OS, Linux or Windows 45 | - Github Client integration 46 | - Great Markdown preview features native in the editor 47 | - Intuitive operation and structure 48 | 49 | You can validate a JSON file by using the [online formatter and validator](https://jsonformatter.curiousconcept.com). 50 | 51 | ## Getting involved 52 | 53 | * If you'd like to contribute to an existing lab, refer to [contributing.md](contributing.md). 54 | * If you're interested in creating a new Cisco DevNet Learning Lab, please contact a DevNet administrator for guidance. 55 | -------------------------------------------------------------------------------- /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 three 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 | 24 | Use the issue tracker to suggest additions, report bugs, and ask questions. 25 | This is also a great way to connect with the developers of the project as well 26 | as others who are interested in this solution. 27 | 28 | Also use the issue tracker to find ways to contribute. Test a lab, find a bug, 29 | log an issue, or offer an update, comment on the issue that you will take on 30 | that effort, then follow the _Changing the Learning Lab content_ guidance below. 31 | 32 | ## Changing the Learning Lab content 33 | 34 | Generally speaking, you should fork the Learning Lab repository, make changes in 35 | your fork, 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 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/1.md: -------------------------------------------------------------------------------- 1 | # Coding 101 - REST API Basics 2 | 3 | This Learning Lab explains the basics of using a REST API. It also shows how to use Postman to explore a REST API. 4 | 5 | ## Objectives 6 | 7 | * Understand REST APIs 8 | * Learn how to use the Postman application to make API calls 9 | 10 | ## Prerequisites 11 | 12 | - [Postman](https://www.getpostman.com) installed. 13 | If you are on a DevNet Zone station, Postman is already installed. 14 | 15 | - Access to DNA Center. To run the code samples, you need access to DNA Center. You can use the DNA Center DevNet Sandbox: 16 | * https://sandboxdnac.cisco.com 17 | * **username:** devnetuser 18 | * **password:** Cisco123! 19 | 20 | ## Step 1: Find the DNA Center API Reference documentation 21 | 22 | A good starting point to understand any API is to look at the documentation for the API. Now, find documentation for the DNA Center API. 23 | 24 | 1. In a browser, navigate to the [DevNet](https://developer.cisco.com/) home page. 25 | 1. Use the menu at the top to navigate to the DNA Center Platform page. 26 | * Click the **Technologies** link to see the submenu. 27 | * Click **Networking**. 28 | * From the list of technologies, click **DNA Center Platform**. 29 | ![](assets/images/Menu.png) 30 | 31 | 1. On the DNA Center Platform page, click the `Docs` link. 32 | 1. Click `API Reference`. 33 | 1. Select the latest API version. 34 | 1. Keep the DNA Center API Reference documentation open in a separate tab. This page provides a useful reference while you work on this lab. 35 | 36 | **Next step:** 37 | 38 | Proceed to Step 2: So what is a REST web service? 39 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: So what is a REST web service? 2 | 3 | ### What is a web service? 4 | 5 | A web service is a way for two systems to communicate through a defined interface. 6 | There are two major types of web services – **REST** and **SOAP**. 7 | 8 | ### What is a REST web service? 9 | 10 | REST is an architecture style for designing networked applications. 11 | A REST web service is as easy to call as making an HTTP request. 12 | RESTful interfaces usually offer the CRUD (Create, Read, Update, Delete) operations. 13 | To know more about REST in general, this is a great [REST definition](https://en.m.wikipedia.org/wiki/Representational_state_transfer). 14 | 15 | ### What are the benefits of REST? 16 | 17 | ***REST is easy to use on any platform.*** 18 | 19 | ![](assets/images/RESTisGreat.jpg) 20 | 21 | ### DNA Center API is a REST API 22 | 23 | For this lab, you are going to use the [DNA Center APIs](https://developer.cisco.com/site/dna-center-rest-api/). 24 | 25 | DNA Center APIs enable deploying and running application policies across your networking infrastructure. 26 | 27 | Using the DNA Center APIs, you can retrieve information about devices on your network including a list of hosts, network devices, or users. You are going to use these features as examples to learn how to make REST calls from Python. 28 | 29 | Look at the [DNA Center documentation](https://developer.cisco.com/site/dna-center-rest-api/) to see the details of the functions. 30 | 31 | ### How does this work? 32 | 33 | ![](assets/images/howitworks.jpg) 34 | 35 | REST is centered around the HTTP request and response model. Consuming an API is as simple as making an HTTP request. 36 | 37 | In this example, you request the list of hosts, and that information is returned to you in the response. The data returned in the response is usually formatted as JSON or XML. 38 | 39 | * [JSON](https://www.json.org/) - JSON, or JavaScript Object Notation, is a lightweight text-based open standard designed for human-readable data interchange. 40 | 41 | * [XML](https://www.w3schools.com/xml/xml_whatis.asp) - XML, or eXtensible Markup Language, a language designed to store and transport data. 42 | 43 | **Next step:** 44 | 45 | Proceed to Step 3: What do I need to know to make a request? 46 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Construct a REST call 2 | 3 | ### DNA Center example: Create a token 4 | 5 | Now, look at how to use the API to create a token for authentication. 6 | 7 | You need to know how to construct the request to retrieve the token. Use the API docs to determine the: 8 | 9 | * Method 10 | * URL 11 | * Headers 12 | * Authentication 13 | * Body 14 | 15 | Get the description of the token API call from the [DNA Center API Docs](https://developer.cisco.com/site/dna-center-rest-api/). Choose the proper API version. 16 | 17 | `POST /api/v1/token`: This method creates a new user token. 18 | 19 | The HTTP call to a create a token is easy. 20 | ``` 21 | 22 | POST https://{DNA-Center-Server}/api/system/v1/auth/token 23 | 24 | ``` 25 | 26 | To get the token your request will look like this: 27 | 28 | * **Method** - `POST` 29 | * **URL** - `https://{DNA-Center-Server}/api/system/v1/auth/token` 30 | * Substitute `{DNA-Center-Server}` with the IP address or hostname of the DNA Center you are using. For example, the Cisco DevNet Learning Labs DNA Center is `https://sandboxdnac.cisco.com/`. 31 | * **Headers** 32 | * Specify the 'Content-Type' as 'application/json'. It's typical to include this header with all HTTP methods (GET, POST, PUT, DELETE) calls. 33 | * **Authentication** 34 | * In this API call, the authentication data is passed in the body. 35 | * **Body** 36 | * Provide the username and password for logging into the DNA Center in JSON format. 37 | 38 | 39 | **Next step:** 40 | 41 | Proceed to Step 5: Make a REST API call. 42 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/5.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Make a REST API call 2 | 3 | There are HTTP clients you can use to quickly test web services. They provide a way to construct/send requests to REST APIs and view the responses: 4 | 5 | * Postman - [https://www.getpostman.com/](https://www.getpostman.com/) 6 | * Firefox RestClient - [https://addons.mozilla.org/en-US/firefox/addon/restclient/](https://addons.mozilla.org/en-US/firefox/addon/restclient/) 7 | * Command Line using curl - [https://curl.haxx.se/docs/httpscripting.html# POST](https://curl.haxx.se/docs/httpscripting.html# POST) 8 | * SOAPUI - [https://www.soapui.org/](https://www.soapui.org/) 9 | 10 | Many IDEs have also consoles for testing REST Services built in. 11 | 12 | In this lab, you use Postman as an example of a REST client. 13 | 14 | ### Accept the SSL certificate before you begin 15 | On OS X, to use Python 3.4, you may need to accept the SSL certificate before calling the APIs in Postman. If you see a certificate warning when visiting the sandbox, then follow these steps. Otherwise, skip these steps. 16 | 17 | 1. Open Chrome. 18 | 19 | 2. If you are using the DevNet DNA Center Platform Sandbox, go to [https://sandboxdnac.cisco.com](https://sandboxdnac.cisco.com). 20 | 21 | 3. If you receive a message specifying that there is a certificate issue, click the **Advanced** link. Otherwise, if you are taken to the login screen skip to the 'Using Postman to make REST API Calls' section. 22 | 23 | 4. Click the **Proceed to <your IP>** link. 24 | 25 | 5. You should then be taken the login screen. Now you are ready to start working in Postman. 26 | 27 | ### Use Postman to make REST API calls 28 | 29 | 1. Start Chrome and open Postman. If you are on a DevNet Zone station, Postman is already installed. 30 | 31 | 2. Set up your request to retrieve a token. In the Postman fields, enter the following information: 32 | 33 | ![](assets/images/postman1.png) 34 | 35 | * **Method** 36 | * ``A.`` Select **POST**. 37 | * **URL** 38 | * ``B.`` Enter `https://sandboxdnac.cisco.com/api/system/v1/auth/token` to use the DevNet Sandbox, or enter your own API endpoint. 39 | * **Body** 40 | * ``C.`` Enter the username and password in JSON format. Use these credentials to get a token for use in the DNA Center. If you are accessing the DNA Center Platform Sandbox, enter the username and password, as specified earlier. Otherwise, enter the required username and password for your DNA Center. 41 | * **Headers** 42 | * ``A.`` In the header, enter: `Content-Type` followed by `application/json`. 43 | 3. Click **Send**. 44 | 4. Postman sends the request to the server and displays the response. 45 | * The **Response Code**, `200`, appears in the **Status** field. 46 | * The **JSON** response contains a **token** attribute. Here is an example token value. The actual value will be different. 47 | 48 | ``` 49 | { 50 | "Token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YjE1MGMwMzY1MWY5MzAwOGFjZDEzZGIiLCJhdXRoU291cmNlIjoiaW50ZXJuYWwiLCJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbIjViMTNmY2ZhNjUxZjkzMDA4YWNkMDcwOSJdLCJ0ZW5hbnRJZCI6IjViMTNmY2Y5NjUxZjkzMDA4YWNkMDcwMiIsImV4cCI6MTUyODg0MTE1OCwidXNlcm5hbWUiOiJkZXZuZXR1c2VyIn0.rK54CBNlua7AjRT7rtWIV6jzpGTNK7OUTs10t8MDGoF" 51 | } 52 | ``` 53 | **Copy and paste this value into a text file to use for the next steps!** 54 | 55 | #### Congratulations! You made a first REST API call to DNA Center! 56 | 57 | **Next step:** 58 | 59 | Proceed to Step 6: Use a token to make REST API calls. 60 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/6.md: -------------------------------------------------------------------------------- 1 | ## Step 6: Use a token to make REST API calls 2 | 3 | ### DNA Center GET Example: Get hosts 4 | 5 | Now, look at the GET HOSTS API. A host is an end device attached to the network, such as a computer connected to a wireless device. Your goal is to find the hosts and display information about them. 6 | 7 | To construct a request that retrieves a list of hosts, refer to the [DNA Center API Docs](https://developer.cisco.com/site/dna-center-rest-api/). Click on Inventory under Services to find GET /host. These provide the following information: 8 | 9 | * Method 10 | * URL 11 | * Headers 12 | * Authentication 13 | * Body 14 | 15 | As specified earlier, you can see that the base URL for DNA Center is: 16 | 17 | ``` 18 | https://{DNA-Center-Server}/api/v1 19 | ``` 20 | 21 | The following call retrieves all of hosts on the specified server: 22 | 23 | ``` 24 | GET https://{DNA-Center-Server}/api/v1/host 25 | ``` 26 | 27 | Alternatively, you may want to retrieve some of the hosts to page through them. In that case, pass the 'limit' parameter to specify the maximum number of hosts to be returned. You can also pass the 'offset' parameter to specify where to start the list of hosts. The following call specifies to start from the first host, (offset=1), and to return a maximum of five hosts, (limit=5). 28 | ``` 29 | GET https://{DNA-Center-Server}/api/v1/host?limit=5&offset=1 30 | ``` 31 | 32 | To get the entire list of hosts, your request contains these items: 33 | 34 | * **Method** - `GET` 35 | * **URL** - `https://{DNA-Center-Server}/api/v1/host` 36 | * Insert the IP address or hostname of the DNA Center. 37 | * **Headers** 38 | * For authentication, add the token that was created earlier. On the left side of the header, add the text 'X-Auth-Token'. On the right side, add the token value. 39 | * When using GET, a content header is not required. However, it's a good practice to specify the content in the header anyway as: 'Content-Type' 'application/json'. 40 | * **Authentication** 41 | * Handled in the header. 42 | * **Body** 43 | * Not required for this request. 44 | 45 | ![](assets/images/HostRequest.png) 46 | 47 | **Next step:** 48 | 49 | Proceed to Step 7: Get the network hosts. 50 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/7.md: -------------------------------------------------------------------------------- 1 | ## Step 7: Get the network hosts 2 | 3 | 1. Set up the API call in Postman. 4 | * Now, use the token to authorize a request to GET the hosts from the controller. 5 | ![](assets/images/postman4.png) 6 | 7 | 2. Enter the following information: 8 | * **Method** 9 | * `A.` Select **GET** in the Method drop down. 10 | * **URL** 11 | * `B.` Enter **https://sandboxdnac.cisco.com/api/v1/host** 12 | * If you are not using your DNA Center, use the DNA Center Lab: https://sandboxdnac.cisco.com. 13 | * **Headers** 14 | * `C.` Enter the 'Content-Type' and value 'application/json'. 15 | * `C.` Enter the 'X-Auth-Token' and the token created earlier. The 'X-Auth-Token' is required for all DNA Center API calls. 16 | * **Authentication** 17 | * Handled in the header. 18 | * **Body** 19 | * Not required for this request. 20 | 3. Click **Send**. Postman sends the request to the server. 21 | 22 | 4. Review the response. 23 | * The **Response Code** in the **Status** field should be `200 OK`. 24 | * The **JSON** should display a list of hosts. 25 | 26 | ![](assets/images/postman5.png "Response") 27 | 28 | ## Things to try 29 | 1. In Postman, append '?limit=1&offset=1' to the URL https://sandboxdnac/api/v1/host so reads as 'https://sandboxdnac/api/v1/host?limit=1&offset=1'. Click the **Send** button. How does the return data differ? Check the API Reference Guide for more information about the Get Host API call. 30 |

31 | 32 | #### Congratulations! You made your first REST API call using the DNA Center Service Ticket! 33 | 34 | **Next step:** 35 | 36 | Proceed to Step 8: Get the network devices. 37 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/8.md: -------------------------------------------------------------------------------- 1 | ## Step 8: Get the network devices 2 | 3 | Now, look at the GET Network Devices API. A network device transports data to and from host devices or other network devices. A network device is typically a hub, switch, or router. It can be connected to the network by an Ethernet cable or wireless connection. Your goal is to find the network devices and display information about them. 4 | 5 | For details about the GET Network Devices API, consult the [DNA Center API Docs](https://developer.cisco.com/site/dna-center-rest-api/). 6 | 7 | 1. Set up the API Call in Postman. Use the token to authorize a request to GET the network devices from the controller. 8 | 9 | ![](assets/images/postman6.png)

10 | 11 | 2. To retrieve the list of network devices, enter the information in the appropriate Postman fields, as shown here: 12 | * **Method** 13 | * **A.** Select **GET**. 14 | * **URL** 15 | * **B.** Enter `https://sandboxdnac/api/v1/network-device` or, if you are not using your DNA Center, enter the DNA Center Lab controller`https://sandboxdnac.cisco.com`. 16 | * **Headers** 17 | * **C.** Enter the `Content-Type` and value `application/json`. 18 | * **C.** Enter `X-Auth-Token` and the value of the token created earlier. 19 | * **Authentication** 20 | * Is handled in the Headers. 21 | * **Body** 22 | * Not required for this request. 23 | 3. Click **Send**. 24 | 4. Postman sends the request to the server and displays the **Response Code**, `200 OK`, in **Status**. **JSON** contains the list of hosts that was returned. 25 | 26 | The output should look similar to the example in this screenshot. For display purposes, some records have been removed. 27 | 28 | ![](assets/images/postman7.png "Response") 29 | 30 | ### Things to try 31 | * In Postman, append `/1/2` so the call becomes `https://sandboxdnac/api/v1/network-device/1/2` and click **Send**. How does the output differ? 32 | * Compare the change you made in *Get Network Devices API* call with the change you made in the *Get Hosts* call in the previous exercise (Step 7). How are they different and why? Hint: Check the API Reference Guide for each of these API calls. 33 | * In Postman, change the API call `https://sandboxdnac/api/v1/network-device/1/2` to `https://sandboxdnac/api/v1/user` and click **Send**. How is the returned data different and what does it represent? Hint: Check the API Reference Guide 34 | 35 | ### Congratulations! You've completed lab Coding 101 - REST API Basics! 36 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/Menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/Menu.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/RESTisGreat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/RESTisGreat.jpg -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/Ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/Ref.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/apic-em-Gen-request.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/apic-em-Gen-request.jpg -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/apic-em-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/apic-em-main.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/apic-em-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/apic-em-request.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/apic-em1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/apic-em1.jpg -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/apic-emHostRequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/apic-emHostRequest.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/howitworks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/howitworks.jpg -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/login.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman1.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman2.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman3.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman4.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman5.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman6.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/postman7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/postman7.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/refguide1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/refguide1.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/refguide4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/refguide4.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/refguide5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/refguide5.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/register.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/ssl1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/ssl1.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/ssl2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/ssl2.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/assets/images/ssl3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-101-rest-basics-ga/assets/images/ssl3.png -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | This lab uses POSTMAN: a Google Chrome Browser application that makes REST API calls. 4 |

5 | You will also access an DNA Center. See the prerequisites section below. 6 |
7 | -------------------------------------------------------------------------------- /labs/coding-101-rest-basics-ga/coding-101-rest-basics-ga.json: -------------------------------------------------------------------------------- 1 | { 2 | "redirectTo": "what-are-rest-apis", 3 | "labId": "coding-101-rest-basics-ga", 4 | "title": "Coding 101 - REST API Basics", 5 | "slug": "Learn the basics of REST APIs. Use POSTMAN and the API for the DNA Center to learn how to make a REST API call.", 6 | "time": 20, 7 | "byod": true, 8 | "files": [ 9 | {"title": "Step 1: Find the DNA Center API Reference documentation", 10 | "file": "1.md"}, 11 | {"title": "Step 2: So what is a REST web service", 12 | "file": "2.md"}, 13 | {"title": "Step 3: What do I need to know to make a request?", 14 | "file": "3.md"}, 15 | {"title": "Step 4: Construct a REST call", 16 | "file": "4.md"}, 17 | {"title": "Step 5: Make a REST API call", 18 | "file": "5.md"}, 19 | {"title": "Step 6: Use a token to make REST API calls", 20 | "file": "6.md"}, 21 | {"title": "Step 7: Get the network hosts", 22 | "file": "7.md"}, 23 | {"title": "Step 8: Get the network devices", 24 | "file": "8.md"} 25 | ], 26 | "tags": [ 27 | {"title": "Coding"}, 28 | {"title": "REST"}, 29 | {"title": "Postman"}, 30 | {"title": "DNA Center"}, 31 | {"title": "JSON"}, 32 | {"title": "Sandbox"} 33 | ], 34 | "related": [ 35 | { 36 | "labId": "coding-102-rest-python-ga", 37 | "title": "Coding 102: Calling REST APIs from Python" 38 | }, 39 | { 40 | "labId": "coding-201-parsing-xml", 41 | "title": "Coding 201: Parsing XML with Python" 42 | }, 43 | { 44 | "labId": "coding-202-parsing-json", 45 | "title": "Coding 202: Parsing JSON with Python" 46 | }, 47 | { 48 | "labId": "coding-203-getting-input", 49 | "title": "Coding 203: Getting input from a user using Python" 50 | }, 51 | { 52 | "labId": "coding-204-reading-a-file", 53 | "title": "Coding 204: Reading from a file using Python" 54 | }, 55 | { 56 | "labId": "coding-205-writing-file-ga", 57 | "title": "Coding 205: Writing data to a file using Python" 58 | }, 59 | { 60 | "labId": "coding-206-logging", 61 | "title": "Coding 206: How to use the logging module in Python" 62 | }, 63 | { 64 | "labId": "coding-207-putting-it-together-ga", 65 | "title": "Coding 207:Python - Putting it all together" 66 | } 67 | ], 68 | "authors": [ 69 | {"name": "mcampos", "email": "marcocam@cisco.com"} 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/1.md: -------------------------------------------------------------------------------- 1 | # Coding 102: Calling REST APIs from Python 2 | 3 | In this Learning Lab, you learn the basics of how to call a REST API in Python. 4 | 5 | 6 | ## Objectives 7 | 8 | * Understand how to call a REST API from Python. 9 | * Explore ways to parse and use the JSON returned from the REST API. 10 | 11 | 12 | ## Prerequisites 13 | 14 | **Background** 15 | 16 | * Complete the [Coding Fundamentals](https://developer.cisco.com/learning/modules/programming-fundamentals) and [REST API Fundamentals](https://developer.cisco.com/learning/modules/rest-api-fundamentals) Learning Lab modules if you are unfamiliar with Python and retrieving results from a RESTful service and the [Parsing XML using Python Lab](lab/coding-201-parsing-xml/step/1 "Parsing XML using Python Lab") for a similar approach to retrieving data using XML. 17 | 18 | * You should also have a basic familiarity with JSON. Otherwise, consider visiting the [W3Schools JSON Tutorial](https://www.w3schools.com/js/js_json_intro.asp "W3Schools JSON Tutorial") to get a firm base to build upon. 19 | * Complete the [Coding 101 Rest Basics Learning Lab](/lab/coding-101-rest-basics-ga/step/1) before you start this lab. 20 | 21 | **Access to DNA Center** 22 | * To run these code samples, you need Access to DNA Center. 23 | * **If you are not using your DNA Center**, use the [DevNet Sandbox](https://sandboxdnac.cisco.com/) DNA Center Lab: https://sandboxdnac.cisco.com. 24 | 25 | **Python** 26 | * To run the code samples, you need to have Python 3 installed on your computer. 27 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, Python 3.x is already installed.. 28 | 29 | For more information, click the "How to Set Up Your Computer" link at the top of this lab. 30 | 31 | **Python Requests Library** 32 | * These code samples use the Python Requests Library to simplify making REST API calls. 33 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, the Requests Library is already installed. 34 | 35 | For more information, click the "How to Set Up Your Computer" link at the top of this lab. 36 | 37 | **Python Flask Library** 38 | * Step 6 uses use the Python Flask Library to interface with NeXt UI. 39 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, the Flask Library is already installed. 40 | 41 | For more information, click the "How to Set Up Your Computer" link at the top of this lab. 42 | 43 | **Clone Git Repo** 44 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, 45 | * Open the Git Command window by clicking the *Git CMD* icon on the Task Bar or click the Start button. Then, in the Run bar, enter: `git cmd`. 46 | * **If you are working from your computer**, on your computer open a command terminal. 47 | ![](assets/images/create_directory.png)

48 | * Clone the coding skills sample code from GitHub. Enter the following command. This will copy Cisco DevNet's coding samples directory down to your computer so you may work with it locally. 49 | ``` 50 | git clone https://github.com/CiscoDevNet/coding-skills-sample-code 51 | ``` 52 | ![](assets/images/github-clone.png)

53 | Inside the directory you created, , you should see a new directory, 'coding-skills-sample-code'.

54 | ![](assets/images/github-clone-listing.png)

55 | 56 | ## Step 1: Find the DNA Center API Reference documentation 57 | 58 | A good starting point to understand any API is to look at the documentation for the API. Now, find documentation for the DNA Center API. 59 | 60 | 1. In a browser, navigate to the [DevNet](https://developer.cisco.com/) home page. 61 | 1. Use the menu at the top to navigate to the DNA Center Platform page. 62 | * Click the **Technologies** link to see the submenu. 63 | * Click **Networking**. 64 | * From the list of technologies, click **DNA Center Platform**. 65 | ![](assets/images/Menu.png) 66 | 67 | 1. On the DNA Center Platform page, click the `Docs` link. 68 | 1. Click `API Reference`. 69 | 1. Select the latest API version. 70 | 1. Keep the DNA Center API Reference documentation open in a separate tab. This page provides a useful reference while you work on this lab. 71 | 72 | **Next step:** 73 | 74 | Proceed to Step 2: Make your first REST call from Python. 75 | -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/Menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/Menu.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/Ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/Ref.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/build-topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/build-topology.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/create-ticket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/create-ticket.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/create_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/create_directory.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/get-devices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/get-devices.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/get-hosts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/get-hosts.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/github-clone-listing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/github-clone-listing.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/github-clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/github-clone.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/login.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/register.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/topology-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/topology-graph.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/web-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/web-flow.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/assets/images/webapp-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-102-rest-python-ga/assets/images/webapp-start.png -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | To work on this lab on your own machine, you will need to install Python and the Requests library. 4 |

5 |

Install Python

6 | 10 | 11 |

Install the Requests Library

12 |
75 | -------------------------------------------------------------------------------- /labs/coding-102-rest-python-ga/coding-102-rest-python-ga.json: -------------------------------------------------------------------------------- 1 | { 2 | "redirectTo": "intro-python-part2", 3 | "labId": "coding-102-rest-python-ga", 4 | "title": "Coding 102: Calling REST APIs from Python", 5 | "slug": "Learn the basics of how to call and consume a REST API in Python", 6 | "time": 35, 7 | "byod": true, 8 | "files": [ 9 | {"title": "Step 1: Find the DNA Center API Reference documentation", 10 | "file": "1.md"}, 11 | {"title": "Step 2: Make your first REST call from Python", 12 | "file": "2.md"}, 13 | {"title": "Step 3: Get information about the network", 14 | "file": "3.md"}, 15 | {"title": "Step 4: Get network devices", 16 | "file": "4.md"}, 17 | {"title": "Step 5: Build network topology", 18 | "file": "5.md"}, 19 | {"title": "Step 6: Build network topology and graphical display", 20 | "file": "6.md"} 21 | ], 22 | "tags": [ 23 | {"title": "Coding"}, 24 | {"title": "Python"}, 25 | {"title": "REST"}, 26 | {"title": "APIC-EM"}, 27 | {"title": "JSON"}, 28 | {"title": "NEXT UI"} 29 | ], 30 | "related": [ 31 | { 32 | "labId": "coding-101-rest-basics-ga", 33 | "title": "Coding 101: REST API Basics" 34 | }, 35 | { 36 | "labId": "coding-201-parsing-xml", 37 | "title": "Coding 201: Parsing XML with Python" 38 | }, 39 | { 40 | "labId": "coding-202-parsing-json", 41 | "title": "Coding 202: Parsing JSON with Python" 42 | }, 43 | { 44 | "labId": "coding-203-getting-input", 45 | "title": "Coding 203: Getting input from a user using Python" 46 | }, 47 | { 48 | "labId": "coding-204-reading-a-file", 49 | "title": "Coding 204: Reading from a file using Python" 50 | }, 51 | { 52 | "labId": "coding-205-writing-file-ga", 53 | "title": "Coding 205: Writing data to a file using Python" 54 | }, 55 | { 56 | "labId": "coding-206-logging", 57 | "title": "Coding 206: How to use the logging module in Python" 58 | }, 59 | { 60 | "labId": "coding-207-putting-it-together-ga", 61 | "title": "Coding 207:Python - Putting it all together" 62 | } 63 | ], 64 | "authors": [ 65 | {"name": "brtiller", "email": "brtiller@cisco.com"} 66 | ], 67 | "active": true 68 | } 69 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2. Understand the returned XML data 2 | 3 | Before parsing the returned XML, take a moment to understand the structure and contents of the XML. It is difficult to see what an unformatted blob of text represents. So, the next step is to format the returned data so you can see its structure. 4 | 5 | ### Using Python's Minidom Library 6 | 7 | The large XML result that the script returns is a string. Thankfully, Python comes with a library that provides a Minimal DOM implementation called *Minidom*. Mindom can "pretty print" XML in a more human-readable format. 8 | 9 | 1. To use this functionality, modify `get-tenants-xml.py` and insert this import statement on the second line, which imports the Minidom library: 10 | ```python 11 | import xml.dom.minidom 12 | ``` 13 | 2. Replace the `print(tenants.text)` line with the following: 14 | ```python 15 | dom = xml.dom.minidom.parseString(tenants.text) 16 | xml = dom.toprettyxml() 17 | print(xml) 18 | ``` 19 | This snippet: 20 | - parses `response.text` as Document Object Model (DOM) 21 | - calls a method off of Minidom that returns a string as formatted XML 22 | - printing the formatted XML 23 | 3. Save the `get-tenants-xml.py` file. To download or review the current code, you can get it from GitHub here. 24 | 25 | 4. Run your `get-tenants-xml.py` file using Python: 26 | ``` 27 | python get-tenants-xml.py 28 | ``` 29 | > **Note**: Ensure that the Python version in use is greater than 3.4. If you get errors, verify the version of Python and double-check the code. 30 | 31 | The response is still a formidable amount of text, but you can see some of the structure of the XML document itself. 32 | 33 | ![](assets/images/xml-output-pretty-new.png) 34 | 35 | ---------- 36 | 37 | A key point to notice is the hierarchical structure of the returned data. Notably, the XML element with the tag name `fvTenant` has sub-objects which can have objects (depending on how we filter our query for data against the APIC). For this exercise, we are interested in the returned tenants (`fvTenant`), their names, and their current health scores. Because the `healthInst` object is a sub-object of the `fvTenant`, we have to move between different levels of the returned XML to get the information we want, in thie case the `name` inside of `fvTenant` and `cur` inside of `healthInst`. 38 | 39 | Structurally, the XML elements have the following order: 40 | 41 | <fvTenant>
42 |     <healthInst/>
43 | </fvTenant>
44 | 45 | It may not look interesting, but inside of each of the tags, we can see that multiple values are stored for different properties of that element. 46 | 47 | In the description shown, the elements tagged as `fvTenant` have sub-elements of `dn` and `modTS` and `name` (there are more, but they will likely be blank), which detail the "Distinguished Name" of the object, its modification time, and its "Relative Name (name)" A full `fvTenant` element from the data can look like this (you'll see the `healthInst` tag nested inside of the `fvTenant`): 48 | ``` 49 | 50 | 51 | 52 | ``` 53 | Where the tag is "fvTenant" and the attributes follow after the tag. You can also see the health tag and its subsequent attributes. 54 | 55 | Now, you have a better understanding of what the structure looks like. Next, you'll parse the data. 56 | 57 | **Next step:** 58 | 59 | Proceed to Step 3: Get XML elements in Python. 60 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Get XML elements in Python 2 | 3 | ### Iterate through elements in XML 4 | 5 | Because you know the structure of the returned XML, the first approach could be to get the first element and sift through that elements children looking for the ones that match what you are looking for. This could be the tag name of the element, a particular value of an attribute, whether or not a child has sub-elements, or even the element's position in the hierarchy of the XML document. For example, you may want to get only the 3rd-level children from the root of the document. Another example might be that you want to get all of the child nodes with a particular attribute whose value is `100`. 6 | 7 | To understand how this might work, modify your script to include some code that loops through the children looking for the information you want to collect, keeping in mind that we'll need to loop through two tiers of tags and store the variables accordingly. Here, find the `fvTenant` elements, output the name of the tenant (`name`), then find the `healthInst` element within each `fvTenant` and print the current health score (`cur`). 8 | 9 | 1. In `get-tenats.py`, insert the following after the `print(xml)` line. Keep the spaces because Python is sensitive to indentation. 10 | ```python 11 | tenant_objects = dom.firstChild 12 | if tenant_objects.hasChildNodes: 13 | tenant_element = tenant_objects.firstChild 14 | while tenant_element is not None: 15 | if tenant_element.tagName == 'fvTenant': 16 | health_element = tenant_element.firstChild 17 | output = "Tenant: " + tenant_element.getAttribute('name') + '\t Health Score: ' + health_element.getAttribute('cur') 18 | print(output.expandtabs(40)) 19 | tenant_element = tenant_element.nextSibling 20 | ``` 21 | This snippet: 22 | - Gets the first element from the Document Object Model (DOM). 23 | - Determines if the first element has children. 24 | - If the first element has children, it begins iterating through them. 25 | - As it iterates through the first elements children, it stores the second element's children as variables for access of information 26 | - For each child, if its tag name is `fvTenant`, print out its `name` and current health score (stored in the `cur` attribute of the `healthInst` tag for a given `fvTenant`). 27 | - The `expandtabs(40)` at the end of `print` statement allows for an easy view of returned data, as the name of each tenant could be of diffent length. If the columns are not aligned, increase the value to something larger (50 or so). 28 | 29 | 1. Save the `get-tenants-xml.py` file. To download or review the current code, you can get it from GitHub here. 30 | 31 | 2. Enter the following command to run your file. 32 | ``` 33 | python get-tenants-xml.py 34 | ``` 35 | > **Note**: Ensure that the Python version in use is greater than 3.4. If you get errors, verify the version of Python and double-check the code. 36 | 37 | When you run the Python script, you should get an output at the end of the data values extracted from the XML returned for each tenant. 38 | 39 | ![](assets/images/xml-output-parse-001-new.png) 40 | 41 | ---------- 42 | 43 | Using Python and Minidom, you have extracted specific information from ACI using the `fvTenant` and nested `healthInst` elements and retrived values defined by the element's attributes. However, what if you want to quickly get the `fvTenant` name and you don't care about anything else in the document? Next, look at how you could parse that out quickly. 44 | 45 | **Next step:** 46 | 47 | Proceed to Step 4: Get XML elements in Python. 48 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Get XML elements in Python 2 | 3 | ### Retrieve Elements by Tag Name 4 | 5 | Rather than manually evaluate each child in a series of nodes, Minidom offers functionality to extract a collection of elements by their tag name. You can use the `getElementsByTagName()` method to return an array of elements. 6 | 7 | 1. In `get-tenants-xml.py`, replace the code you inserted in Step 3 (everything after the `print(xml)` line) with the following code. (Be careful to maintain the indentation.) 8 | 9 | ```python 10 | tenant_list = dom.getElementsByTagName('fvTenant') 11 | for tenants in tenant_list: 12 | tenant_name = tenants.getAttribute('name') 13 | tenant_dn = tenants.getAttribute('dn') 14 | health_score = tenants.firstChild.getAttribute('cur') 15 | output = "Tenant: " + tenant_name + "\t Health Score: " + health_score + "\n DN: " + tenant_dn 16 | print(output.expandtabs(40)) 17 | ``` 18 | 19 | This snippet: 20 | - Gets elements whose tag is `fvTenant`. 21 | - Iterates through those elements. 22 | - Stores the healthscore by looking at the `firstChild` of the tenant, which is `healthInst`, then gets the `cur` health score attribute 23 | - For each child, prints out its `name`, `cur` health score, and the tenant `dn` with appropriate formatting 24 | 25 | 1. Save the `get-tenants-xml.py` file. To download or review the current code, you can get it from GitHub here. 26 | 27 | 2. Enter the following command to run your file. 28 | ``` 29 | python get-tenants-xml.py 30 | ``` 31 | > **Note**: Ensure that the Python version in use is greater than 3.4. If you get errors, verify the version of Python and double-check the code. 32 | 33 | When you run the Python script, it should return output that is similar to what you saw before, with the addition of the tenant distinguished name below the tenant name. 34 | 35 | ![](assets/images/xml-output-parse-002-new.png) 36 | 37 | ---------- 38 | 39 | Using Python and Minidom, you have extracted and displayed specific information from ACI. 40 | 41 | Next, in the last step, see which resources you can use to learn more about parsing XML with Python. 42 | 43 | **Next step:**: 44 | 45 | Proceed to Step 5: Find additional resources. 46 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/5.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Find additional resources 2 | 3 | The following sections provide additional resources for learning about the topics that were covered by this lab. 4 | 5 | ### Extensible Markup Language (XML) 6 | 7 | If some of the XML terminology is still confusing, a good next step would be to visit: [https://www.w3schools.com/xml/](https://www.w3schools.com/xml/ "W3Schools XML"). 8 | 9 | To learn more about XML, you can also review the XML standard at [https://www.w3.org/TR/REC-xml/](https://www.w3.org/TR/REC-xml/ "Extensible Markup Language (XML) 1.0 (Fifth Edition)"). 10 | 11 | ### Python 12 | 13 | Python is a powerful tool. To learn more, use the [https://docs.python.org/3.4/tutorial/](https://docs.python.org/3.4/tutorial/ "Python Tutorial"). 14 | 15 | **Python XML Libraries**
16 | There are several libraries and approaches for parsing XML content. The Minidom library you used in this lab is one tool. Another popular Python library is [ElementTree](https://docs.python.org/3.4/library/xml.etree.elementtree.html "ElementTree XML API"). 17 | 18 | You can find a good summary of the major standard and external libraries at [https://wiki.python.org/moin/PythonXml](https://wiki.python.org/moin/PythonXml "PythonXML"). 19 | 20 | Additionally, for an overview of the Python modules for Stream and Document Object Model parsing, see [https://docs.python.org/3.4/whatsnew/2.0.html#xml-modules](https://docs.python.org/3.4/whatsnew/2.0.html#xml-modules "XML-Modules"). 21 | 22 | ### Application Centric Infrastructure 23 | 24 | **Product Information**
25 | [https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html](https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html "Application Centric Infrastructure (ACI) Product Site") 26 | 27 | **Developer Resources**
28 | [https://developer.cisco.com/site/aci/](https://developer.cisco.com/site/aci/ "Application Centric Infrastructure Developer Site") 29 | 30 | **Application Centric Infrastructure (ACI) API Documentation**
31 | [https://developer.cisco.com/docs/aci/](https://developer.cisco.com/docs/aci/ "ACI API Documentation") 32 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-new.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-parse-001-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-parse-001-new.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-parse-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-parse-001.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-parse-002-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-parse-002-new.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-parse-002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-parse-002.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-pretty-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-pretty-new.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output-pretty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output-pretty.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/assets/images/xml-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-201-parsing-xml/assets/images/xml-output.png -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/byod.html: -------------------------------------------------------------------------------- 1 |
2 | For this lab we will be using Python 3.4+. To verify your version run the following command in a terminal window: 3 | 4 | python --version 5 | 6 |
-------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/coding-201-parsing-xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "redirectTo": "parsing-xml", 3 | "labId": "coding-201-parsing-xml", 4 | "title": "Parsing XML", 5 | "slug": "Learn the basics of how to use parse XML results using Python.", 6 | "byod": true, 7 | "time": "20", 8 | "files": [ 9 | {"title": "Step 1: Make an HTTP REST call with Python", 10 | "file": "1.md"}, 11 | {"title": "Step 2. Understand the returned XML data", 12 | "file": "2.md"}, 13 | {"title": "Step 3: Get XML elements in Python", 14 | "file": "3.md"}, 15 | {"title": "Step 4: Get XML elements in Python", 16 | "file": "4.md"}, 17 | {"title": "Step 5: Find additional resources", 18 | "file": "5.md"} 19 | ], 20 | "tags": [ 21 | {"title": "Cloud"}, 22 | {"title": "Coding"}, 23 | {"title": "Parsing"}, 24 | {"title": "XML"}, 25 | {"title": "Python"}, 26 | {"title": "ACI"}, 27 | {"title": "Sandbox" } 28 | ], 29 | "related": [ 30 | { 31 | "labId": "rest-basics", 32 | "title": "REST API Basics" 33 | }, 34 | { 35 | "labId": "rest-python", 36 | "title": "Calling REST APIs from Python" 37 | }, 38 | { 39 | "labId": "parsing-xml", 40 | "title": "Parsing XML with Python" 41 | }, 42 | { 43 | "labId": "parsing-json", 44 | "title": "Parsing JSON with Python" 45 | }, 46 | { 47 | "labId": "getting-input", 48 | "title": "Getting input from a user using Python" 49 | }, 50 | { 51 | "labId": "reading-a-file", 52 | "title": "Reading from a file using Python" 53 | }, 54 | { 55 | "labId": "writing-file", 56 | "title": "Writing data to a file using Python" 57 | }, 58 | { 59 | "labId": "logging", 60 | "title": "How to use the logging module in Python" 61 | }, 62 | { 63 | "labId": "putting-it-together", 64 | "title": "Python - Putting it all together" 65 | } 66 | ], 67 | "authors": [ 68 | {"name": "brtiller", "email": "brtiller@cisco.com"}, 69 | {"name": "qsnyder", "email": "qsnyder@cisco.com"} 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/get-ap-xml.py: -------------------------------------------------------------------------------- 1 | from urllib.request import Request, urlopen 2 | import xml.dom.minidom 3 | 4 | # Let's construct a request with headers 5 | req = Request('https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone') 6 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc==') 7 | 8 | # Actually open the request 9 | response = urlopen(req) 10 | 11 | # Read the response into a String 12 | responseString = response.read().decode("utf-8") 13 | 14 | # Parse the string into an XML Document Object Model 15 | dom = xml.dom.minidom.parseString(responseString) 16 | xml = dom.toprettyxml() 17 | 18 | # Print out the formatted response string 19 | print(xml) 20 | 21 | # Get the first object of the document 'Floor' 22 | floor_element = dom.firstChild 23 | if floor_element.hasChildNodes : 24 | child = floor_element.firstChild 25 | while child is not None: 26 | if child.tagName == 'AccessPoint' : 27 | output = child.tagName + ": " + child.getAttribute('name') + '\t eth: ' + child.getAttribute('ethMacAddress') 28 | print(output) 29 | child = child.nextSibling 30 | 31 | # Load the XML into a collection of Access Point information 32 | access_points = dom.getElementsByTagName('AccessPoint') 33 | for access_point in access_points: 34 | ap_name = access_point.getAttribute('name') 35 | ap_eth_addr = access_point.getAttribute('ethMacAddress') 36 | ap_ip_addr = access_point.getAttribute('ipAddress') 37 | print(access_point.tagName + ": " + ap_name + '\t eth: ' + ap_eth_addr + '\t ip: ' + ap_ip_addr) 38 | 39 | # Let's close the response we opened 40 | response.close() 41 | -------------------------------------------------------------------------------- /labs/coding-201-parsing-xml/get-tenants-xml.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) 35 | 36 | # Now lets use DOM to clean up the XML from its completely raw format 37 | dom = xml.dom.minidom.parseString(tenants.text) 38 | xml = dom.toprettyxml() 39 | print(xml) 40 | 41 | # 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 42 | #tenant_objects = dom.firstChild 43 | #if tenant_objects.hasChildNodes: 44 | # tenant_element = tenant_objects.firstChild 45 | # while tenant_element is not None: 46 | # if tenant_element.tagName == 'fvTenant': 47 | # health_element = tenant_element.firstChild 48 | # output = "Tenant: " + tenant_element.getAttribute('name') + '\t Health Score: ' + health_element.getAttribute('cur') 49 | # print(output.expandtabs(40)) 50 | # tenant_element = tenant_element.nextSibling 51 | 52 | # Now we'll do something similar, but done using a direct access method of the data, rather than interation and loops 53 | tenant_list = dom.getElementsByTagName('fvTenant') 54 | for tenants in tenant_list: 55 | tenant_name = tenants.getAttribute('name') 56 | tenant_dn = tenants.getAttribute('dn') 57 | health_score = tenants.firstChild.getAttribute('cur') 58 | output = "Tenant: " + tenant_name + "\t Health Score: " + health_score + "\n DN: " + tenant_dn 59 | print(output.expandtabs(40)) -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Use the JSON Python library 2 | 3 | ### Use Python's JSON object 4 | 5 | The large JSON result you got in the previous step is a string. It has no special properties beyond that. To parse it, you would parse it as a string. However, Python comes with a standard `json` library for encoding/decoding and accessing JSON content. This library uses patterns that are familiar to Python developers. When you load a string using the `json` decoder, it converts JSON objects into Python [dictionaries](https://docs.python.org/3.4/reference/expressions.html#dictionary-displays) and JSON arrays into Python [lists](https://docs.python.org/3.4/reference/expressions.html#list-displays). This is useful because it then enables you to access and iterate through JSON as Python data. 6 | 7 | Another useful tool of the JSON library is it's ability to "pretty print" the JSON output into a hierarchical structure. This makes it easier to see the overall structure of the data. Now, use that capability to print the data into a more human-readable output. 8 | 9 | > **Note**: The `requests` library has the ability to return the data from the query in JSON without any additional lines of code, however, in this lab we will not be using this ability in order to understand how the `json` library works within Python. 10 | 11 | 1. Normally, we'd need to odify the second line of `get-tenant-json.py` to import the JSON library, however, due to the construct of the ACI authentication, we've already imported it. You can verify that this line is present in the file: 12 | 13 | ``` 14 | import json 15 | ``` 16 | 17 | 2. Comment out the `print(tenants.text)` line by putting a pound or hash sign at the front of the line: 18 | 19 | ``` 20 | # print(tenants.text) 21 | ``` 22 | You are commenting out this line because you are going to use the `json` library to pretty print your output. 23 | 24 | 3. Update `get-tenant-json.py` by adding the following line below `#print(tenants.text)`: 25 | 26 | ``` 27 | json_response = json.loads(tenants.text) 28 | ``` 29 | 30 | The `json.loads()` method loads the `tenants.text` into a JSON object. If it is successful, you can use square brackets to get a particular element from `json_response`. 31 | 32 | 4. Add the following line just below the previous line you added: 33 | 34 | ``` 35 | print(json.dumps(json_response, sort_keys=True, indent=4)) 36 | ``` 37 | 38 | This line prints the elements `dumps()` method returns from the `json_response`. The arguments control how the output is displayed. 39 | 40 | 5. Save the `get-tenant-json.py` file. To download or review the current code, you can get it from GitHub [here](https://github.com/CiscoDevNet/coding-skills-sample-code/blob/master/coding202-parsing-json/get-tenant-json-2.py). 41 | 42 | 6. To run your newly created file, enter: 43 | 44 | ``` 45 | python get-tenant-json.py 46 | ``` 47 | 48 | 7. The Python script gets and displays the following JSON data. 49 | 50 | ![](assets/images/json-output-pretty-new.png) 51 | 52 | -------------------------------------------------------------------------------- 53 | 54 | The content and structure of this data is easier for you to read and understand. 55 | 56 | ### Understanding the returned JSON data 57 | 58 | Because you are getting JSON data, the content you get back has a particular order or schema. Elements of the returned 'fv-Tenant' ACI Managed Object (MO) class parsed in JSON data have sub-objects and even sub-dictionaries and sub-lists. For this exercise, you are interested in the **name**, **dn**, and **health** of each of the tenants configured within the fabric. This approach returns the desired information, as well as additional bits returned as part of the query to the `fv-Tenant` class. 59 | 60 | ``` 61 | {fvTenant} 62 | {attributes} 63 | annotation 64 | childAction 65 | descr 66 | dn 67 | extMngdBy 68 | lcOwn 69 | modTs 70 | monPolDn 71 | name 72 | nameAlias 73 | ownerKey 74 | ownerTag 75 | status 76 | uid 77 | {children} 78 | {healthInst} 79 | {attributes} 80 | ... 81 | ... 82 | ... 83 | ``` 84 | 85 | In the example shown, `fvTenant` is dictionary of multiple tenant objects - each with their `name`, `dn`, and other attributes. 86 | 87 | Now that you have seen this structure, go to the next step and learn how to get only the data you care about. 88 | 89 | **Next step:** 90 | 91 | Proceed to Step 3: Iterate through a JSON dictionary in Python. 92 | -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Iterate through a JSON dictionary in Python 2 | 3 | ### Loop through a Python dictionary 4 | 5 | In the previous step, you decoded the JSON content into a `json_response` variable. This conversion allows a developer to easily access the information contained within using loops to iterate through the data. Using this method, we will loop through the tenants, print their name, DN, and their health score. 6 | 7 | To loop through the tenants within a dictionary, first get the tenants using the `json` library. Then, use a Python `for` loop to go through each element of the list. A second loop won't be required, as the list contained within the `children` element returned only contains a single value, `healthInst`. 8 | 9 | Keep in mind that you may need to reference the pretty-print JSON that we created in the previous section, focusing on a single tenant within the output, in order to iterate through the object correctly. You can also run the script from the previous section in "interactive" mode using `python -i`, which will allow you to interact with the stored variables to determine what the nested types are and how to access different elements to get to the desired key-value pairs in the JSON. 10 | 11 | > **Note**: this looks like a lot of manipulation and parsing, but it will provide a very good testbed to understand how to iterate through JSON 12 | 13 | 1. Preserving the indentation, comment out the previous print statement (wherein we printed the "pretty" JSON) and add the following lines: 14 | 15 | ```python 16 | json_tenants = json_response['imdata'] 17 | for tenant in json_tenants: 18 | tenant_name = tenant['fvTenant']['attributes']['name'] 19 | tenant_dn = tenant['fvTenant']['attributes']['dn'] 20 | tenant_health = tenant['fvTenant']['children'][0]['healthInst']['attributes']['cur'] 21 | output = "Tenant: " + tenant_name + "\t Health Score: " + tenant_health + "\n DN: " + tenant_dn 22 | print(output.expandtabs(40)) 23 | ``` 24 | 25 | This snippet: 26 | 27 | - Starts the initial entry point inside of the `imdata` dictionary 28 | - Creates a `for` loop to iterate through the list of `fvTenant` objects sequentially 29 | - Gathers the `name` and `dn` values within the `attributes` dictionary contained within the `fvTenant` dictionary 30 | - Gathers the current health score by pulling the value from the `children` dictionary. This is pulled from the list of child objects (there's only a single item, which is why this can be safely set to `0`), and then moving through the `healthInst` dictionary, followed by the `attributes` dictionary and pulling the value from `cur` 31 | - Prints the resulting data with nice formatting, using the `expandtabs` method. If the resulting printed data is not aligned, increase this value to 50 or so (results will vary due to length of configured tenant names on the fabric at any one time) 32 | 33 | 2. Save the `get-tenant-json.py` file. To download or review the current code, you can get it from GitHub [here](https://github.com/CiscoDevNet/coding-skills-sample-code/blob/master/coding202-parsing-json/get-tenant-json-3.py) 34 | 35 | 3. Enter the following command to run your file. 36 | 37 | ``` 38 | python get-tenant-json.py 39 | ``` 40 | 41 | 4. When you run the Python script, at the end of the output, you should get the JSON data values returned for each tenant in a format that looks similar to this: 42 | 43 | ![](assets/images/json-output-parse-001-new.png) 44 | 45 | -------------------------------------------------------------------------------- 46 | 47 | This is a very direct way to use Python to get data from a REST service using JSON and parse out only the information you care about. Depending on the capabilities of the REST API, you can also sometimes pass in query parameters or other information to reduce the scope of returned data or search for a single or group of specific items. 48 | 49 | For a summary of resources, continue on to the last step. 50 | 51 | **Next step:** 52 | 53 | Proceed to Step 4: Find additional resources. 54 | -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Find additional resources 2 | 3 | For more information on the topics covered, visit the following resources. 4 | 5 | ### JavaScript Object Notation (JSON) 6 | 7 | For more information on JavaScript Object Notation (JSON), visit [https://www.json.org/](https://www.json.org/ "JSON.org"). 8 | 9 | Also consider visiting the JavaScript Object Notation (JSON) tutorials at [https://www.w3schools.com/js/js_json_intro.asp](https://www.w3schools.com/js/js_json_intro.asp "W3Schools JSON") 10 | 11 | ### Python 12 | 13 | Python is a powerful tool. To learn more, visit [https://docs.python.org/3.4/tutorial/](https://docs.python.org/3.4/tutorial/ "Python Tutorial"). 14 | 15 | **Python JSON Libraries**
16 | The documentation for the JSON Python library can be found at [https://docs.python.org/3.4/library/json.html](https://docs.python.org/3.4/library/json.html "Python JSON"). 17 | 18 | ### Application Centric Infrastructure 19 | 20 | **Product Information**
21 | [https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html](https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html "Application Centric Infrastructure (ACI) Product Site") 22 | 23 | **Developer Resources**
24 | [https://developer.cisco.com/site/aci/](https://developer.cisco.com/site/aci/ "Application Centric Infrastructure Developer Site") 25 | 26 | **Application Centric Infrastructure (ACI) API Documentation**
27 | [https://developer.cisco.com/docs/aci/](https://developer.cisco.com/docs/aci/ "ACI API Documentation") 28 | -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/assets/images/json-output-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-202-parsing-json/assets/images/json-output-new.png -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/assets/images/json-output-parse-001-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-202-parsing-json/assets/images/json-output-parse-001-new.png -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/assets/images/json-output-parse-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-202-parsing-json/assets/images/json-output-parse-001.png -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/assets/images/json-output-pretty-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-202-parsing-json/assets/images/json-output-pretty-new.png -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/assets/images/json-output-pretty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-202-parsing-json/assets/images/json-output-pretty.png -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/assets/images/json-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-202-parsing-json/assets/images/json-output.png -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/byod.html: -------------------------------------------------------------------------------- 1 |
2 | For this lab we will be using Python 3.4+. To verify your version run the following command in a terminal window: 3 | 4 | python --version 5 | 6 |
-------------------------------------------------------------------------------- /labs/coding-202-parsing-json/coding-202-parsing-json.json: -------------------------------------------------------------------------------- 1 | { 2 | "redirectTo": "parsing-json", 3 | "labId": "coding-202-parsing-json", 4 | "title": "Parsing JSON", 5 | "slug": "Learn the basics of how to use parse JSON results using Python.", 6 | "byod": true, 7 | "time": "15", 8 | "files": [ 9 | {"title": "Step 1: Make an HTTP REST call with Python", 10 | "file": "1.md"}, 11 | {"title": "Step 2: Use the JSON Python library", 12 | "file": "2.md"}, 13 | {"title": "Step 3: Iterate through a JSON dictionary in Python", 14 | "file":"3.md"}, 15 | {"title": "Step 4: Find additional resources", 16 | "file": "4.md"} 17 | ], 18 | "tags": [ 19 | {"title" : "Cloud"}, 20 | {"title" : "Coding"}, 21 | {"title": "Parsing"}, 22 | {"title": "JSON"}, 23 | {"title": "Python"}, 24 | {"title": "ACI"}, 25 | {"title" : "Sandbox" } 26 | ], 27 | "related": [ 28 | { 29 | "labId": "rest-basics", 30 | "title": "REST API Basics" 31 | }, 32 | { 33 | "labId": "rest-python", 34 | "title": "Calling REST APIs from Python" 35 | }, 36 | { 37 | "labId": "parsing-xml", 38 | "title": "Parsing XML with Python" 39 | }, 40 | { 41 | "labId": "parsing-json", 42 | "title": "Parsing JSON with Python" 43 | }, 44 | { 45 | "labId": "getting-input", 46 | "title": "Getting input from a user using Python" 47 | }, 48 | { 49 | "labId": "reading-a-file", 50 | "title": "Reading from a file using Python" 51 | }, 52 | { 53 | "labId": "writing-file", 54 | "title": "Writing data to a file using Python" 55 | }, 56 | { 57 | "labId": "logging", 58 | "title": "How to use the logging module in Python" 59 | }, 60 | { 61 | "labId": "putting-it-together", 62 | "title": "Python - Putting it all together" 63 | } 64 | ], 65 | "authors": [ 66 | {"name": "brtiller", "email": "brtiller@cisco.com"}, 67 | {"name": "qsnyder", "email": "qsnyder@cisco.com"} 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /labs/coding-202-parsing-json/get-ap-json.py: -------------------------------------------------------------------------------- 1 | from urllib.request import Request, urlopen 2 | import json 3 | 4 | # Let's construct a request with headers 5 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone') 6 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=') 7 | req.add_header('Accept', 'application/json') 8 | 9 | # Actually open the request 10 | response = urlopen(req) 11 | 12 | # Read the response into a JSON String 13 | responseString = response.read().decode("utf-8") 14 | 15 | #res = json.dump(obj, out, sort_keys=True, indent=4, separators=(',', ': ')) 16 | # Print out the response string 17 | #print(responseString) 18 | 19 | # Load the JSON string into a JSON object 20 | json_object = json.loads(response_string) 21 | #print(json_object) 22 | print(json.dumps(json_object, sort_keys=True, indent=4)) 23 | 24 | # Only output what we are interested in - the AP name and IP address 25 | #access_points = json_object['accessPoints'] 26 | #for ap in access_points: 27 | # print('Access Point: ' + ap['name'] + '\t mac: ' + ap['radioMacAddress']) 28 | 29 | # Let's close the response we opened 30 | response.close() 31 | -------------------------------------------------------------------------------- /labs/coding-203-getting-input/1.md: -------------------------------------------------------------------------------- 1 | # Coding 203: Getting input from a user in Python 2 | 3 | In this Learning Lab, you learn how to ask the user for data. 4 | 5 | 6 | ## Objectives 7 | 8 | * Understand how to prompt a user to enter data. 9 | * Understand how to use the data entered by the user. 10 | 11 | 12 | ## Prerequisites 13 | 14 | **Python** 15 | * To run the code samples, you need to have Python 3 installed on your computer. 16 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, Python 3.x is already installed.. 17 | * See the previous **BYOD** section for information on how to install Python on your computer. 18 | 19 | 20 | ## Step 1: Understand how to get input from a user 21 | 22 | You often need to ask the user a question, and then use his/her answer to make decisions in an application. 23 | 24 | Python makes this operation easy. 25 | 26 | For example, ask the user about his favorite vegetable. 27 | 28 | You can ask him/her and then display the answer like this. 29 | 30 | ```python 31 | # ask the user to enter his/her favorite vegetable 32 | favorite_veg = input("What's your favorite vegetable? ") 33 | 34 | # Use the input to create a response 35 | print("I like " + favorite_veg + " too!") 36 | 37 | ``` 38 | Fairly simple, right? Now, you try it! 39 | 40 | **Next step:** 41 | 42 | Proceed to Step 2: Try it out! 43 | -------------------------------------------------------------------------------- /labs/coding-203-getting-input/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Try it out! 2 | Here is some example code that asks a user to enter his/her favorite vegetable, and then creates a response using the vegetable that was entered. 3 | 4 | ```python 5 | favorite_veg = input("What's your favorite vegetable? ") 6 | print("I like " + favorite_veg + " too!") 7 | 8 | favorite_sauce = input("What is your favorite sauce? ") 9 | print("I like " + favorite_veg + " with " + favorite_sauce + " on it!") 10 | 11 | ``` 12 | Now, look at what is going on in the code. 13 | 14 | * The **input("What's your favorite vegetable? ")** statement asks the user the question and waits for the response. 15 | * The response the user types is stored in the variable named `favorite_veg`. 16 | * You can use `favorite_veg` in your program the way you normally use variables. 17 | 18 | ### Give it a try! 19 | 20 | To run this code sample: 21 | 1. Open a text editor. 22 | * For example, *on a DevNet Learning Lab computer*, open Notepad++. (**Start > Notepad++**) 23 | 3. Create a folder for this lab. 24 | * For example, *on a DevNet Learning Lab computer*, create a folder in "C:\Coding-101\yourname". 25 | 6. Copy/paste the code shown into your new file. 26 | 7. Save the file with the `.py` extension to your new directory. For example, `get-user-input.py`. 27 | 8. Open a command prompt. 28 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt** 29 | 9. At the command line, go to the directory where you saved the `get-user-input.py` file. 30 | * For example, *On a DevNet Learning Lab computer*, enter: `cd C:\Coding-101\yourname` 31 | 10. At the command prompt, enter the `python` command followed by the filename. 32 | * On Windows, enter: `py -3 get-user-input.py` 33 | * On macOS or Linux, enter: `python3 get-user-input.py` 34 | 11. The program should run or display an error message. 35 | 36 | You should see a result like this: 37 | 38 | ![](assets/images/step2-results.jpg) 39 | 40 | ### Things to try 41 | * Try asking for some new inputs. 42 | * Try constructing some new responses based on the inputs. 43 | * Try using an [if](https://docs.python.org/3.4/reference/compound_stmts.html# if) statement to make your response vary based on the user's input. 44 | -------------------------------------------------------------------------------- /labs/coding-203-getting-input/assets/images/step2-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-203-getting-input/assets/images/step2-results.jpg -------------------------------------------------------------------------------- /labs/coding-203-getting-input/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | To work on this lab on your own machine, you will need to install Python.. 4 |

5 | 6 |

Install Python

7 | 12 | 13 |
-------------------------------------------------------------------------------- /labs/coding-203-getting-input/coding-203-getting-input.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "coding-203-getting-input", 3 | "title": "Coding 203: Getting Input from a User Using Python", 4 | "byod": true, 5 | "slug": "Learn the basics of how to get input from a user", 6 | "time": "5", 7 | "files": [ 8 | {"title": "Step 1: Understand how to get input from a user", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Try it out!", 11 | "file": "2.md"} 12 | ], 13 | "tags": [ 14 | {"title" : "Coding"}, 15 | {"title": "Python"}, 16 | {"title" : "Sandbox" } 17 | ], 18 | "related": [ 19 | { 20 | "labId": "coding-101-rest-basics", 21 | "title": "Coding 101: REST API Basics" 22 | }, 23 | { 24 | "labId": "coding-102-rest-python", 25 | "title": "Coding 102: Calling REST APIs from Python" 26 | }, 27 | { 28 | "labId": "coding-201-parsing-xml", 29 | "title": "Coding 201: Parsing XML with Python" 30 | }, 31 | { 32 | "labId": "coding-202-parsing-json", 33 | "title": "Coding 202: Parsing JSON with Python" 34 | }, 35 | { 36 | "labId": "coding-203-getting-input", 37 | "title": "Coding 203: Getting input from a user using Python" 38 | }, 39 | { 40 | "labId": "coding-204-reading-a-file", 41 | "title": "Coding 204: Reading from a file using Python" 42 | }, 43 | { 44 | "labId": "coding-205-writing-file", 45 | "title": "Coding 205: Writing data to a file using Python" 46 | }, 47 | { 48 | "labId": "coding-206-logging", 49 | "title": "Coding 206: How to use the logging module in Python" 50 | }, 51 | { 52 | "labId": "coding-207-putting-it-together", 53 | "title": "Coding 207:Python - Putting it all together" 54 | } 55 | ], 56 | "authors": [ 57 | {"name": "brtiller", "email": "brtiller@cisco.com"} 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/1.md: -------------------------------------------------------------------------------- 1 | # Coding 204: Reading data from a file using Python 2 | 3 | In this Learning Lab, you learn how to read data from a file using Python. 4 | 5 | ## Objectives 6 | 7 | * Understand how to read data from a file. 8 | * Understand the different modes that you can use when opening a file. 9 | * Understand how to read JSON from a file. 10 | 11 | 12 | ## Prerequisites 13 | 14 | **Python** 15 | * To run the code samples, you need to have Python 3 installed on your computer. 16 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, Python 3.x is already installed.. 17 | * See the previous **BYOD** section for information on how to install Python on your computer. 18 | 19 | 20 | ## Step 1: Understand how to read and display data from a text file 21 | 22 | In the [Coding 203: Getting input from a user in Python](/lab/coding-203-getting-input/step/1) learning lab, you learned how to get input from the user with the keyboard. 23 | 24 | Another common way to get input is to read data from a text file. 25 | 26 | Python makes this operation easy. 27 | 28 | Now, suppose that you have a file, **myfile.txt**, that contains the following code: 29 | 30 | ```text 31 | This is the first line. Absolutely, the first line. 32 | This is the second line. Yep, this is the second line. 33 | ``` 34 | 35 | To display this text, use the following statement. 36 | 37 | ```python 38 | # Opens the file and create an object called my_file_object that holds the reference to the file 39 | my_file_object = open("my-file.txt", "r") 40 | 41 | # read() reads in the entire file and prints it to the screen. 42 | print (my_file_object.read()) 43 | ``` 44 | 45 | Fairly simple, right? Now, try some examples. 46 | 47 | **Next step:** 48 | 49 | Proceed to Step 2: Read the contents of a file and display to the screen. 50 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Read the contents of a file and display to the screen 2 | The following code opens **my-file.txt**, located in the same directory as this python file. 3 | 4 | ```python 5 | # Use the open method to open a file 6 | # Pass in the name of the file to open and mode. 'r' for read only 'w' if you want to write to the file 7 | my_file_object = open("my-file.txt", "r") 8 | 9 | print ("Read the whole file at once:") 10 | 11 | # read() reads in the entire file. In this line of code, you read in the contents of the file and print it to the screen. 12 | print (my_file_object.read()) 13 | print ("\n") 14 | 15 | # .close closes the file object 16 | my_file_object.close() 17 | 18 | ``` 19 | Now, look at what is going on in the code. 20 | 21 | * `my_file_object = open("my-file.txt", "r")` opens the file in Read mode. 22 | * Pass the name of the file and the mode to the open method. 23 | * The "r" specifies that you want to open the file in Read mode because you only want to read from the file (use 'w' to write to file). 24 | * `my_file_object.read()` reads in the entire contents of the file. 25 | * `my_file_object.close()` closes the file when you are finished. (Don't forget to close the file!) 26 | 27 | 28 | ### Give it a try! 29 | 30 | To run this code sample: 31 | 1. Create a folder for this lab. For example, *on a DevNet Learning Lab computer*, create a folder based on your name (e.g., "C:\Coding-204\&# 123;yourname&# 125;"). In a command window, you can enter `mkdir \Coding-204\&# 123;yourname&# 125;`. 32 | 2. Open a text editor such as Notepad++ (**Start Menu > Notepad++**). 33 | 3. Create a new file that contains some text and save it to your new folder as a `.txt` file 34 | 5. Create a second new file. 35 | 6. Copy/paste the code shown into the file. 36 | 7. Save the file with the extension `.py` in the your new directory. For example, `read-file.py`. 37 | 8. Open a command prompt. For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 38 | 9. At the command line, go to the directory where you saved the `read-file.py` file. For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-204\&# 123;yourname&# 125;` 39 | 10. At the command prompt, enter the `python` command followed by the filename. 40 | * On Windows, enter: `py -3 read-file.py` 41 | * On macOS or Linux, enter: `python3 read-file.py` 42 | 11. The program should run or display an error message. 43 | 44 | Using this text file: 45 | 46 | ```python 47 | This is the first line. Absolutely, the first line. 48 | This is the second line. Yep, this is the second line. 49 | 50 | ``` 51 | 52 | You should see a result like this: 53 | 54 | ![](assets/images/step2-results.jpg) 55 | 56 | ### Things to try 57 | * What happens if you have a typo in the name of the file? 58 | 59 | **Next step:** 60 | 61 | Proceed to Step 3: Read one line at a time. 62 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Read one line at a time 2 | Sometimes, it is useful to read the data from a file one line at a time. 3 | 4 | You can use the `.readline()` method to read one line at a time. 5 | 6 | Here is some code that reads only the first line of the text file. 7 | 8 | ```python 9 | # .readline() reads in only 1 line of the file at a time. 10 | print ("Read only the first line of the file:") 11 | my_file_object = open("my-file.txt", "r") 12 | print (my_file_object.readline()) 13 | print ("\n") 14 | my_file_object.close() 15 | 16 | ``` 17 | 18 | Now, look at what is going on in the code. 19 | 20 | * `my_file_object = open("my-file.txt", "r")` opens the file in Read mode. 21 | * Pass the name of the file and the mode to the open method. 22 | * The "r" specifies that you want to open the file in Read mode because you only want to read from the file (use 'w' to write to file). 23 | * `my_file_object.readline()` reads in only the first line of the file. 24 | * `my_file_object.close()` closes the file when you are finished. (Don't forget to close the file!) 25 | 26 | ### Give it a try! 27 | 28 | To run this code sample: 29 | 1. Open a text editor. 30 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 31 | 2. Open your `read-file.py` file that you created in step 2. 32 | 3. Modify your code to use `.readline()` instead of `.read()`. 33 | 4. Save your file. 34 | 5. Open a command prompt. 35 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 36 | 6. At the command line, go to the directory where you saved the `read-file.py` file. 37 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-204\yourname` 38 | 7. At the command prompt, enter the `python` command followed by the filename. 39 | * On Windows, enter: `py -3 read-file.py` 40 | * On macOS or Linux, enter: `python3 read-file.py` 41 | 8. The program should run or display an error message. 42 | 43 | Using this text file: 44 | 45 | ```python 46 | This is the first line. Absolutely, the first line. 47 | This is the second line. Yep, this is the second line. 48 | 49 | ``` 50 | 51 | You should see a result like this: 52 | 53 | ![](assets/images/step3-results.jpg) 54 | 55 | ### Things to try 56 | * What happens if you call `.readline()` multiple times? 57 | 58 | **Next step:** 59 | 60 | Step 3: Read one line at a time. 61 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Read the file one line at a time using a loop 2 | Sometimes, it is useful to read the data from a file one line at a time and use a loop to keep repeating the operation until you have read the entire file. 3 | 4 | You can use a file object and a `for` loop to move through the file. 5 | 6 | ```python 7 | # You can also loop through the lines and read each line in a loop. 8 | print ("Loop through and read each line") 9 | 10 | my_file_object = open("my-file.txt", "r") 11 | x=1 12 | for line in my_file_object: 13 | print ("Line " + str(x) + ": " + line) 14 | x += 1 15 | 16 | my_file_object.close() 17 | 18 | ``` 19 | 20 | Now, look at what is going on in the code. 21 | 22 | * `my_file_object = open("my-file.txt", "r")` opens the file in Read mode. 23 | * Pass the name of the file and the mode to the open method. 24 | * The "r" specifies that you want to open the file in Read mode because you only want to read from the file (use 'w' to write to file). 25 | * `for` each line in the file runs the code in the loop, prints the line, and increments the counter, `x`. 26 | * `my_file_object.close()` closes the file when you are finished. (Don't forget to close the file!) 27 | 28 | ### Give it a try! 29 | 30 | To run this code sample: 31 | 1. Open a text editor. 32 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 33 | 2. Open your `read-file.py` file that you created in step 2. 34 | 3. Modify your code to use the loop shown. 35 | 4. Save your file. 36 | 5. Open a command prompt. 37 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 38 | 6. At the command line, go to the directory where you saved the `read-file.py` file. 39 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-204\yourname` 40 | 7. At the command prompt, enter the `python` command followed by the filename. 41 | * On Windows, enter: `py -3 read-file.py` 42 | * On macOS or Linux, enter: `python3 read-file.py` 43 | 8. The program should run or display an error message. 44 | 45 | Using this text file: 46 | 47 | ```python 48 | This is the first line. Absolutely, the first line. 49 | This is the second line. Yep, this is the second line. 50 | 51 | ``` 52 | 53 | You should see a result like this: 54 | 55 | ![](assets/images/step4-results.jpg) 56 | 57 | ### Things to try 58 | * Can you add some more code that runs inside the loop? 59 | 60 | **Next step:** 61 | 62 | Proceed to Step 5: Using `with` to read a file. 63 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/5.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Using `with` to read a file 2 | The best way to open and read from a file in Python is to use the [with](https://docs.python.org/3.4/reference/compound_stmts.html# with) statement. 3 | 4 | The `with` statement wraps a block with methods defined by a context manager. 5 | 6 | When you are opening files, `with` provides better exception handling and automatically closes the file. 7 | 8 | Using `with` is definitely the best practice when working with files. 9 | 10 | Here is an example: 11 | 12 | ```python 13 | print ("Loop through and read each line using with to open the file") 14 | x=1 15 | 16 | # You can open the file using 'with'. 17 | # 'with' provides better exception handling and closes the file 18 | with open("my-file.txt") as file: 19 | for line in file: 20 | print ("Line " + str(x) + ": " + line) 21 | x += 1 22 | 23 | ``` 24 | 25 | Now, look at what is going on in the code. 26 | 27 | * Open the file using `with open("my-file.txt") as file:` 28 | * The default mode is 'r' for Read, but you can still specify the mode as you did before. 29 | * The file object will be returned to the variable named `file`. 30 | * You put the same `for` loop that was used in the previous step inside the `with` statement. 31 | * You don't need a `.close()` statement because `with` closes the file. 32 | 33 | ### Give it a try! 34 | 35 | To run this code sample: 36 | 1. Open a text editor. 37 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 38 | 2. Open your `read-file.py` file that you created in step 2. 39 | 3. Modify your code to use the statement and loop shown. 40 | 4. Save your file. 41 | 5. Open a command prompt. 42 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 43 | 6. At the command line, go to the directory where you saved the `read-file.py` file. 44 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-204\yourname` 45 | 7. At the command prompt, enter the `python` command followed by the filename. 46 | * On Windows, enter: `py -3 read-file.py` 47 | * On macOS or Linux, enter: `python3 read-file.py` 48 | 8. The program should run or display an error message. 49 | 50 | Using this text file: 51 | 52 | ```python 53 | This is the first line. Absolutely, the first line. 54 | This is the second line. Yep, this is the second line. 55 | 56 | ``` 57 | 58 | You should see a result like this: 59 | 60 | ![](assets/images/step5-results.jpg) 61 | 62 | **Next step:** 63 | 64 | Proceed to Step 6: Read JSON from a file. 65 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/6.md: -------------------------------------------------------------------------------- 1 | ## Step 6: Read JSON from a file 2 | 3 | If you are using REST APIs, see [Coding 101: Rest Basics Learning Lab](/lab/coding-101-rest-basics-ga/step/1) for more information. Often, load some JSON from a file. 4 | 5 | You can use the same techniques that you used in the previous steps to help you read JSON from a file. 6 | 7 | You are going to look at an example that reads some JSON that is returned by the [DNA Center API](https://developer.cisco.com/site/dnac/). 8 | 9 | The JSON contains a list of network devices that is returned by the DNA Center APIs. 10 | 11 | Here are the contents of the JSON file: 12 | 13 | ```json 14 | { 15 | "response": [ 16 | { 17 | "id": "d4b33d28-04dd-4733-a6de-8877ec26c196", 18 | "tag": "campus", 19 | "networkDeviceId": "e5f93514-3ae5-4109-8b52-b9fa876e1eae", 20 | "attributeInfo": {} 21 | }, 22 | { 23 | "id": "d4b33d28-04dd-4733-a6de-8877ec26c196", 24 | "tag": "campus", 25 | "networkDeviceId": "da733ffb-e34b-4733-bd85-b615fb7e61f3", 26 | "attributeInfo": {} 27 | }, 28 | { 29 | "id": "d4b33d28-04dd-4733-a6de-8877ec26c196", 30 | "tag": "campus", 31 | "networkDeviceId": "f8c3fc68-cd26-4576-bcec-51f9b578f71e", 32 | "attributeInfo": {} 33 | } 34 | ], 35 | "version": "0.0" 36 | } 37 | 38 | ``` 39 | 40 | Here is the code you can use to load this JSON from the file and then display the network device IDs to the screen. 41 | 42 | ```python 43 | 44 | # Import the JSON library. This library provides many handy features for formatting, displaying 45 | # and manipulating json. 46 | import json 47 | 48 | # Use 'with" to open the file containing JSON 49 | with open('my-json.json') as file: 50 | # read the whole file 51 | data = json.loads(file.read()) 52 | 53 | # Access values from the JSON and loop through devices and display the network device id 54 | i = 0 55 | for item in data["response"]: 56 | print ("Network Device ID: " + data["response"][i]["networkDeviceId"]) 57 | i += 1 58 | 59 | ``` 60 | 61 | Now, look at what is going on in the code. 62 | 63 | * The `import json` statement loads the JSON library. 64 | * Use the `with open('my-json.json') as file:` to open the file containing the JSON. 65 | * Use `file.read()` to read the entire contents of the file. 66 | * Use `json.loads()` to load the contents of the file into a JSON object. 67 | * Now, you have the contents of the file in memory in a JSON object and you can loop through and manipulate the JSON as usual. 68 | 69 | See [Coding 202 Parsing JSON](/lab/coding-202-parsing-json/step/1) for more information on how to parse JSON. 70 | 71 | ### Give it a try! 72 | 73 | To run this code sample: 74 | 1. Open a text editor. 75 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 76 | 2. Create a new text file. 77 | * Copy/paste the JSON shown into the file. 78 | * Be sure you do not add any leading or trailing spaces or blank lines. 79 | 3. Save your new text file in your folder. 80 | 4. Create another new text file. 81 | 5. Copy/paste the code shown into the file. 82 | 6. Save the file with the extension `.py` in the your new directory. For example, `read-json-file.py`. 83 | 7. Open a command prompt. 84 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 85 | 8. At the command line, go to the directory where you saved the `read-file-json.py` file. 86 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-204\yourname` 87 | 9. At the command prompt, enter the `python` command followed by the filename. 88 | * On Windows, enter: `py -3 read-file-json.py` 89 | * On macOS or Linux, enter: `python3 read-file-json.py` 90 | 10. The program should run or display an error message. 91 | 92 | Using the example JSON file shown: 93 | 94 | You should see a result like this: 95 | 96 | ![](assets/images/step6-results.jpg) 97 | 98 | ### Things to try 99 | * Can you display the tags for each device? 100 | -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/assets/images/step2-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-204-reading-a-file/assets/images/step2-results.jpg -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/assets/images/step3-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-204-reading-a-file/assets/images/step3-results.jpg -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/assets/images/step4-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-204-reading-a-file/assets/images/step4-results.jpg -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/assets/images/step5-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-204-reading-a-file/assets/images/step5-results.jpg -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/assets/images/step6-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-204-reading-a-file/assets/images/step6-results.jpg -------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | To work on this lab on your own machine, you will need to install Python.. 4 |

5 | 6 |

Install Python

7 | 12 | 13 |
-------------------------------------------------------------------------------- /labs/coding-204-reading-a-file/coding-204-reading-a-file.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "coding-204-reading-a-file", 3 | "title": "Coding 204: Reading data from a file using Python", 4 | "byod": true, 5 | "slug": "Learn the basics of how to read data from a file using Python", 6 | "time": "10", 7 | "files": [ 8 | {"title": "Step 1: Understand how to read and display data from a text file", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Read the contents of a file and display to the screen", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Read one line at a time", 13 | "file": "3.md"}, 14 | {"title": "Step 4: Read the file one line at a time using a loop", 15 | "file": "4.md"}, 16 | {"title": "Step 5: Using 'with' to read a file", 17 | "file": "5.md"}, 18 | {"title": "Step 6. Read JSON from a file", 19 | "file": "6.md"} 20 | ], 21 | "tags": [ 22 | {"title": "Coding"}, 23 | {"title": "JSON"}, 24 | {"title": "Python"}, 25 | {"title": "Sandbox"} 26 | ], 27 | "related": [ 28 | { 29 | "labId": "coding-101-rest-basics", 30 | "title": "Coding 101: REST API Basics" 31 | }, 32 | { 33 | "labId": "coding-102-rest-python", 34 | "title": "Coding 102: Calling REST APIs from Python" 35 | }, 36 | { 37 | "labId": "coding-201-parsing-xml", 38 | "title": "Coding 201: Parsing XML with Python" 39 | }, 40 | { 41 | "labId": "coding-202-parsing-json", 42 | "title": "Coding 202: Parsing JSON with Python" 43 | }, 44 | { 45 | "labId": "coding-203-getting-input", 46 | "title": "Coding 203: Getting input from a user using Python" 47 | }, 48 | { 49 | "labId": "coding-204-reading-a-file", 50 | "title": "Coding 204: Reading from a file using Python" 51 | }, 52 | { 53 | "labId": "coding-205-writing-file", 54 | "title": "Coding 205: Writing data to a file using Python" 55 | }, 56 | { 57 | "labId": "coding-206-logging", 58 | "title": "Coding 206: How to use the logging module in Python" 59 | }, 60 | { 61 | "labId": "coding-207-putting-it-together", 62 | "title": "Coding 207:Python - Putting it all together" 63 | } 64 | ], 65 | "authors": [ 66 | {"name": "brtiller", "email": "brtiller@cisco.com"} 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/1.md: -------------------------------------------------------------------------------- 1 | # Coding 205: Writing data to a file using Python 2 | 3 | In this Learning Lab, you learn how to write data to a file. 4 | 5 | 6 | ## Objectives 7 | 8 | * Understand how to write data to a file. 9 | * Understand how to append data to a file. 10 | 11 | 12 | ## Prerequisites 13 | 14 | **Python** 15 | * To run the code samples, you need to have Python 3 installed on your computer. 16 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, Python 3.x is already installed.. 17 | 18 | For more information, click the "How to Set Up Your Computer" link at the top of this lab. 19 | 20 | **Python Requests Library** 21 | * The code sample in Step 5 uses the Python Requests Library to simplify making REST API calls. 22 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, the Requests Library is already installed. 23 | 24 | For more information, click the "How to Set Up Your Computer" link at the top of this lab. 25 | 26 | **Clone Git Repo** 27 | * **If you are working on a DevNet Learning Lab computer at a DevNet event** 28 | * Open the Git Command window by clicking the *Git CMD* icon on the Task Bar or click the Start button. Then, in the Run bar, enter: `git cmd`. 29 | * **If you are working from your computer**, on your computer open a command terminal. 30 | * Go to the root directory by entering: `cd \` 31 | * Create a directory called 'C:\DevNetCode\yourname' by entering: `mkdir DevNetCode\` 32 | * For example: `mkdir DevNetCode\brTiller` 33 | * Go to the new directory by entering: `cd \DevNetCode\` 34 | * For example: `cd \DevNetCode\brTiller` 35 | * Clone the coding skills sample code from GitHub. Enter the following command. 36 | 37 | ``` 38 | git clone https://github.com/CiscoDevNet/coding-skills-sample-code 39 | ``` 40 | 41 | ![](assets/images/github-clone.png)

42 | Inside the directory you created , you should see a new directory, 'coding-skills-sample-code'.

43 | ![](assets/images/github-clone-listing.png)

44 | 45 | ## Step 1: Understand how to write data to a file 46 | 47 | When writing applications, you often need to save some information to a text file. 48 | 49 | Python makes this operation easy. 50 | 51 | Here is a simple example that creates a file named **my-new-file.txt** and writes the line "The grey penguin flies at noon." to the file. 52 | 53 | ```python 54 | # Use the open method to open a file 55 | # Pass in the name of the file to open and mode. 'r' for read only 'w' if you want to write to the file 56 | # To write to this file you use "w" 57 | # If the file does not exist, it will be created. 58 | my_file_object = open("my-new-file.txt", "w") 59 | 60 | my_file_object.write("The grey penguin flies at noon.") 61 | 62 | my_file_object.close() 63 | 64 | ``` 65 | Fairly simple, right? Now, try it! 66 | 67 | ## Next step 68 | 69 | Proceed to Step 2: Write to a file. 70 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Write to a file 2 | Here is some example code that writes a sentence to a file. 3 | 4 | ```python 5 | # Use the open method to open a file 6 | # Pass in the name of the file to open and mode. 'r' for read only 'w' if you want to write to the file 7 | # To write to this file you use "w" 8 | # If the file does not exist, it will be created. 9 | my_file_object = open("my-new-file.txt", "w") 10 | 11 | my_file_object.write("The grey penguin flies at noon.") 12 | 13 | my_file_object.close() 14 | 15 | ``` 16 | Now, look at what is going on in the code. 17 | 18 | * The `my_file_object = open("my-new-file.txt", "w")` statement opens a file in 'write' mode. 19 | * The "w" opens the file in write mode. 20 | * When using "w" write mode, the contents of the file will be OVERWRITTEN. 21 | * If the file does not already exist, it will be created. 22 | * The `my_file_object.write()` statement writes the specified statement to the file. 23 | * The `my_file_object.close()` statement closes the file. (Don't forget to close your files!) 24 | 25 | ### Give it a try! 26 | 27 | To run this code sample: 28 | 1. Open a text editor. 29 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 30 | 3. Create a folder for this lab. 31 | * For example, *on a DevNet Learning Lab computer*, create a folder in "C:\Coding-205\yourname". Enter command: `mkdir Coding-205\{yourname}` 32 | * where {yourname} is replaced by your first name. 33 | 6. Copy/paste the code shown into your new file. 34 | 7. Save the file with the extension `.py` in your new directory. For example, `write-file.py`. 35 | 8. Open a command prompt. 36 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 37 | 9. At the command line, go to the directory where you saved the `write-file.py` file. 38 | * For example, *on a DevNet Learning Lab computer*, enter: `cd Coding-205\{yourname}` 39 | 10. At the command prompt, enter the `python` command followed by the filename. 40 | * On Windows, enter: `py -3 write-file.py` or enter: `python write-file.py` 41 | * On macOS or Linux, enter: `python3 write-file.py` 42 | 11. The program should run or display an error message. 43 | 44 | Your text file should contain the following when you open it after running your program. 45 | 46 | ![](assets/images/step2-results.jpg) 47 | 48 | ### Things to try 49 | * Try writing multiple lines of text to the file. 50 | 51 | **Next step:** 52 | 53 | Proceed to Step 3: Write to a file using `with`. 54 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Write to a file using `with` 2 | The best way to open and write to a file in Python is to use the [with](https://docs.python.org/3.4/reference/compound_stmts.html# with) statement. 3 | 4 | The `with` statement wraps a block with methods defined by a context manager. 5 | 6 | When you are opening files, `with` provides better exception handling and automatically closes the file. 7 | 8 | Using `with` is definitely the best practice when working with files. 9 | 10 | ```python 11 | print ("Writing to file..") 12 | 13 | # You can open the file using 'with'. 14 | # 'with' provides better exception handling and closes the file 15 | with open("my-new-file2.txt", "w") as file: 16 | file.write("Cisco Developers are 1337!\n") 17 | file.write("DevNet Developers rock!") 18 | ``` 19 | 20 | Now, look at what is going on in the code. 21 | 22 | * Open the file using `with open("my-new-file2.txt", "w") as file:` 23 | * Open the file in **Write** mode by passing in `w`. 24 | * The file object will be returned to the variable named `file` 25 | * Then, write two lines to the file. 26 | * The '\n' character is like pressing the return key. 27 | * The code doesn't need a `.close()` statement because `with` closes the file. 28 | 29 | ### Give it a try! 30 | 31 | To run this code sample: 32 | 1. Open a text editor. 33 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 34 | 3. Open your `write-file.py` file you created in the previous step. 35 | 6. Copy/paste the code shown into your new file. 36 | 7. Save the file with the extension `.py` in your new directory. For example, `write-file.py`. 37 | 8. Open a command prompt. 38 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 39 | 9. At the command line, go to the directory where you saved the `write-file.py` file. 40 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-205\yourname` 41 | 10. At the command prompt, enter the `python` command followed by the filename. 42 | * On Windows, enter: `py -3 write-file.py` or enter: `python write-file.py` 43 | * On macOS or Linux, enter: `python3 write-file.py` 44 | 11. The program should run or display an error message. 45 | 46 | Your text file should contain the following when you open it after running your program. 47 | 48 | ![](assets/images/step3-results.jpg) 49 | 50 | ## Next step 51 | 52 | Proceed to Step 4: Append to a file. 53 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Append to a file 2 | Look at the following code. 3 | 4 | What do you think the result will be? 5 | 6 | ```python 7 | print ("Writing to file..") 8 | 9 | # You can open the file using 'with'. 10 | # 'with' provides better exception handling and closes the file 11 | with open("my-new-file2.txt", "w") as file: 12 | file.write("Cisco Developers are 1337!\n") 13 | file.write("DevNet Developers rock!") 14 | 15 | print ("Do some stuff outside of the block") 16 | 17 | # open the file again and append some additional text 18 | with open("my-new-file2.txt", "w") as file: 19 | file.write("Level up!\n") 20 | file.write("Go to developer.cisco.com and do more learning labs!") 21 | 22 | ``` 23 | Copy this code into your `write-file.py` file and run it. 24 | 25 | What happened? 26 | 27 | ![](/posts/files/coding-205-writing-file-ga/assets/images/step4a-results.jpg) 28 | 29 | * The first two lines that you wrote are **OVERWRITTEN** by the second two lines. Oops! 30 | * When you open a file using the `w` Write mode, the file is written over if it exists. 31 | * But, what if you want to add to file? 32 | * To append to a file, use `a` when opening the file. 33 | 34 | Here is an example: 35 | 36 | ```python 37 | print ("Writing to file..") 38 | 39 | # You can open the file using 'with'. 40 | # 'with' provides better exception handling and closes the file 41 | with open("my-new-file2.txt", "w") as file: 42 | file.write("Cisco Developers are 1337!\n") 43 | file.write("DevNet Developers rock!") 44 | 45 | print ("Do some stuff outside of the block") 46 | 47 | # open the file again and append some additional text 48 | with open("my-new-file2.txt", "a") as file: 49 | file.write("Level up!\n") 50 | file.write("Go to developer.cisco.com and do more learning labs!") 51 | ``` 52 | 53 | ### Give it a try! 54 | 55 | To run this code sample: 56 | 1. Open a text editor. 57 | * For example, *on a DevNet Learning Lab computer*, open Notepad++. (e.g., **Start > Notepad++**) 58 | 3. Open your `write-file.py` file you created in the previous step. 59 | 6. Copy/paste the code shown into your new file. 60 | 7. Save the file with the extension `.py` in your new directory. For example, `write-file.py`. 61 | 8. Open a command prompt. 62 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 63 | 9. At the command line, go to the directory where you saved the `write-file.py` file. 64 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-205\yourname` 65 | 10. At the command prompt, enter the `python` command followed by the filename. 66 | * On Windows, enter: `py -3 write-file.py` or enter: `python write-file.py` 67 | * On Mac OS or Linux, enter: `python3 write-file.py` 68 | 11. The program should run or display an error message. 69 | 70 | Your text file should contain the following when you open it after running your program. 71 | 72 | ![](assets/images/step4-results.jpg) 73 | 74 | ## Next step 75 | 76 | Proceed to Step 5: Save data from JSON to a file. 77 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/5.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Save data from JSON to a file 2 | Often, when you are working with REST APIs (see [Coding 101: Rest Basics Learning Lab](/lab/coding-101-rest-basics-ga/step/1) ), it is handy to be able to save some data to a file. 3 | 4 | You can combine the techniques for writing to a file with the techniques for calling REST APIs that you learned in [Coding 102 Calling REST APIs from Python](/lab/coding-102-rest-python-ga/step/1) 5 | 6 | Now, look at an example that retrieves some JSON from the [DNA Center APIs](https://developer.cisco.com/site/dna-center-rest-api/). 7 | 8 | ```python 9 | # Import the requests library so you can use it to make REST calls (https://docs.python-requests.org/en/latest/index.html) 10 | import requests 11 | 12 | # Import the JSON library. This library provides many handy features for formatting, displaying 13 | # and manipulating json. 14 | import json 15 | 16 | # All of your REST calls will use the URL for the DNA Center as the base URL 17 | # Define a variable for the controller IP or DNS so you don't have to keep entering it 18 | controller_url = "https://devnetapi.cisco.com/sandbox/dnac" 19 | 20 | # The username and password to access the DNA Center 21 | payload = {"username":"devnetuser","password":"Cisco123!"} 22 | 23 | ticket_url = controller_url + "/api/v1/ticket" 24 | 25 | # Content type must be included in the header 26 | header = {"content-type": "application/json"} 27 | 28 | # Perform a POST on the specified url to get the token 29 | response= requests.post(ticket_url,data=json.dumps(payload), headers=header, verify=False) 30 | 31 | # Convert response to JSON format 32 | r_json=response.json() 33 | 34 | # Parse the JSON to get the token 35 | ticket = r_json["response"]["serviceTicket"] 36 | 37 | # Get Devices 38 | # This function enables you to view a list of 3 of the devices in the network(routers and switches). 39 | get_devices_url = controller_url + '/api/v1/network-device/1/3' 40 | 41 | # Include the content type and ticket in the header 42 | header = {"content-type": "application/json", "X-Auth-Token":ticket} 43 | 44 | # Perform GET on get_devices_url 45 | get_devices_response = requests.get(get_devices_url, headers=header, verify=False) 46 | 47 | # The JSON method of the response object returned by requests.get returns the request body in JSON format 48 | get_devices_json = get_devices_response.json() 49 | 50 | # Now, read and display some specific information from the JSON 51 | 52 | # Set your parent as the top level response object 53 | parent = get_devices_json["response"] 54 | 55 | print ("Devices = ") 56 | # You can open the file using 'with'. 57 | # 'with' provides better exception handling and closes the file 58 | with open("list-of-devices.txt", "w") as file: 59 | # For each device returned, write the networkDeviceId and type value to the file 60 | for item in parent: 61 | device="id = " + item["id"] + " type = " + item["type"] 62 | file.write (device + "\n") 63 | print(device) 64 | 65 | ``` 66 | Now, look at what is going on in the code. 67 | 68 | * First, you use the Request library to create a token using the DNA Center API. 69 | * You then call the DNA Center API and pass in the ticket to retrieve the list of network devices. 70 | * This statement, `get_devices_response = requests.get(get_devices_url, headers=header, verify=False)`, is the line that calls the API. 71 | * Then, you create a JSON object, `get_devices_json`, containing the JSON that is returned. 72 | * Next, you open a file and loop through the JSON object and print the ID and type for each device that was returned to the file and the screen. 73 | 74 | ### Give it a try! 75 | To run this code sample: 76 | 1. In a terminal, enter: 77 | `cd \DevNetCode\~your-name~\coding-skills-sample-code\coding-205-writing-file-ga` 78 | 2. Assign the DNA Center IP address or DNS to the `controller_url` variable. 79 | * Open the file `write-json-to-file.py`. For example, in Windows, enter: `notepad write-json-to-file.py` 80 | * *If you are not using your DNA Center*, use the [DevNet Sandbox](https://developer.cisco.com/site/devnet/sandbox/) DNA Center Lab: [devnetapi.cisco.com/sandbox/dnac](https://devnetapi.cisco.com/sandbox/dnac) 81 | * controller_url='https://devnetapi.cisco.com/sandbox/dnac' 82 | 3. Save the file. If encoding type is an option, select **UTF-8**. 83 | 4. At the command prompt, enter the `python` command followed by the filename. 84 | * On Windows, enter: `py -3 write-json-to-file.py` or `python write-json-to-file.py` 85 | * On macOS or Linux, enter: `python3 write-json-to-file.py` 86 | 5. The program should run or display an error message. 87 | 88 | 89 | Your text file should contain the following when you open it after running your program. 90 | 91 | ![](assets/images/step5-results.jpg) 92 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/github-clone-listing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/github-clone-listing.png -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/github-clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/github-clone.png -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/step2-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/step2-results.jpg -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/step3-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/step3-results.jpg -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/step4-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/step4-results.jpg -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/step4a-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/step4a-results.jpg -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/assets/images/step5-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-205-writing-file-ga/assets/images/step5-results.jpg -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | To work on this lab on your own machine, you will need to install Python and the Requests library. 4 |

5 |

Install Python

6 | 10 | 11 |

Install the Requests Library

12 |
    13 |
  • You can read more about the Requests Library here
  • 14 |
  • To install Requests for Python 3 on Mac OS, use these command line commands: 15 |
      16 |
    • 17 | sudo curl -O https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py
      18 | sudo python3 get-pip.py
      19 | pip3 install requests
      20 |             
    • 21 |
    22 |
  • 23 |
  • To install Requests on Windows: 24 |
      25 |
    • Pip comes with Python 3.4 Windows
    • 26 |
    • Check to see if Pip is in your python 3 path
    • 27 |
    • 28 |
      29 | C:\>pip –V
      30 | pip 1.5.6 from C:\Python34\lib\site-packages
      31 |                 
      32 |
    • 33 |
    • If pip is in the Python34 path, the execute 34 |
      35 | pip install requests
      36 |                 
      37 |
    • 38 |
    39 |
  • 40 |
  • 41 | You will also need Access to DNA Center. 42 | 47 |
  • 48 |
49 | 50 |

Clone Git Repo

51 |
    52 |
  • Clone the coding skills sample code
  • 53 |
  • git clone https://github.com/CiscoDevNet/coding-skills-sample-code
  • 54 |
55 |
56 | -------------------------------------------------------------------------------- /labs/coding-205-writing-file-ga/coding-205-writing-file-ga.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "coding-205-writing-file-ga", 3 | "title": "Coding 205: Writing data to a file using Python", 4 | "byod": true, 5 | "slug": "Learn the basics of how to write data to a file using Python.", 6 | "time": "15", 7 | "files": [ 8 | {"title": "Step 1: Understand how to write data to a file", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Write to a file", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Write to a file using 'with'", 13 | "file": "3.md"}, 14 | {"title": "Step 4: Append to a file", 15 | "file": "4.md"}, 16 | {"title": "Step 5: Save data from JSON to a file", 17 | "file": "5.md"} 18 | ], 19 | "tags": [ 20 | {"title": "Coding"}, 21 | {"title": "Python"}, 22 | {"title": "JSON"}, 23 | {"title": "Sandbox"}, 24 | {"title": "DNA Center"} 25 | ], 26 | "related": [ 27 | { 28 | "labId": "coding-101-rest-basics-ga", 29 | "title": "Coding 101: REST API Basics" 30 | }, 31 | { 32 | "labId": "coding-102-rest-python-ga", 33 | "title": "Coding 102: Calling REST APIs from Python" 34 | }, 35 | { 36 | "labId": "coding-201-parsing-xml", 37 | "title": "Coding 201: Parsing XML with Python" 38 | }, 39 | { 40 | "labId": "coding-202-parsing-json", 41 | "title": "Coding 202: Parsing JSON with Python" 42 | }, 43 | { 44 | "labId": "coding-203-getting-input", 45 | "title": "Coding 203: Getting input from a user using Python" 46 | }, 47 | { 48 | "labId": "coding-204-reading-a-file", 49 | "title": "Coding 204: Reading from a file using Python" 50 | }, 51 | { 52 | "labId": "coding-205-writing-file-ga", 53 | "title": "Coding 205: Writing data to a file using Python" 54 | }, 55 | { 56 | "labId": "coding-206-logging", 57 | "title": "Coding 206: How to use the logging module in Python" 58 | }, 59 | { 60 | "labId": "coding-207-putting-it-together-ga", 61 | "title": "Coding 207:Python - Putting it all together" 62 | } 63 | ], 64 | "authors": [ 65 | {"name": "brtiller", "email": "brtiller@cisco.com"} 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /labs/coding-206-logging/1.md: -------------------------------------------------------------------------------- 1 | # Coding 206: Using the logging module in Python 2 | 3 | In this Learning Lab, you learn the basics of how to use the logging module. 4 | 5 | 6 | ## Objectives 7 | 8 | 9 | * Understand how to use the logging module. 10 | * Understand the different logging levels. 11 | * Understand how to log to the console or to a file. 12 | * Understand how to format the output of the logger. 13 | 14 | 15 | ## Prerequisites 16 | 17 | **Python** 18 | * To run the code samples, you need to have Python 3 installed on your computer. 19 | * **If you are working on a DevNet Learning Lab computer at a DevNet event**, Python 3.x is already installed.. 20 | * See the previous **BYOD** section for information on how to install Python on your computer. 21 | 22 | 23 | ## Step 1: Understand the Python logging module 24 | 25 | While you are developing applications, it is important to be able to log messages and errors the app may generate. Python provides a good logging module that makes this easy to do. 26 | 27 | Start coding with best practices right from the beginning and always use a logger in your applications. 28 | 29 | Here is basic code that is required to log information to the console. 30 | 31 | ```python 32 | # Import the logging module 33 | import logging 34 | 35 | logging.warning('This is a warning!') # This line will print a message to the console 36 | 37 | ``` 38 | If you run this code, it displays this output in the console: 39 | 40 | ![](assets/images/step1-results.jpg) 41 | 42 | Fairly simple, right? Now, try it! 43 | 44 | **Next step:** 45 | 46 | Proceed to Step 2: Experiment with logging and logging levels. 47 | -------------------------------------------------------------------------------- /labs/coding-206-logging/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Experiment with logging and logging levels 2 | Here is code that performs simple logging to the console: 3 | 4 | ```python 5 | # Import the logging module 6 | import logging 7 | 8 | # Uncomment the following line to see both messages in the console 9 | # Logging.basicConfig(level=logging.INFO) 10 | 11 | logging.warning('This is a warning!') # This line will print a message to the console 12 | logging.info('This is information') # This will not print anything because the default logging level is warning. 13 | ``` 14 | 15 | Now, look at what is going on in the code. 16 | 17 | * First, import the logging module - `import logging`. 18 | * `logging.warning` logs a message with the level `warning`. 19 | * `logging.info` logs a message with the level `info`. 20 | * The default logging level in python is `warning`. If you use the default setting, then only the first message is displayed. 21 | * If you uncomment and use the `logging.basicConfig(level=logging.INFO)` statement, the logging level changes to `info`. 22 | * When the logging level is set to `info`, you see the second line in the console. 23 | 24 | Here is some information on the different logging levels and how they should be used. (Taken from the Python docs, see [Python Docs](https://docs.python.org/3/howto/logging.html) for more information.) 25 | 26 | * **DEBUG**: Detailed information, typically of interest only when diagnosing problems. 27 | * **INFO**: Confirmation that things are working as expected. 28 | * **WARNING**: An indication that something unexpected happened, or indicative of some problem in the near future (e.g., `disk space low`). The software is still working as expected. 29 | * **ERROR**: Due to a more serious problem, the software has not been able to perform some function. 30 | * **CRITICAL**: A serious error, indicating that the program itself may be unable to continue running. 31 | 32 | The default level is **WARNING**, which means that only events of this level and higher will be tracked, unless the logging package is configured to do otherwise. 33 | 34 | ### Give it a try! 35 | 36 | To run this code sample: 37 | 1. Open a text editor. 38 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 39 | 3. Create a folder for this lab. 40 | * For example, *on a DevNet Learning Lab computer*, create a folder in "C:\Coding-206\yourname". 41 | 6. Copy/paste the code shown into your new file. 42 | 7. Save the file with the extension `.py` in your new directory. For example, `simple-logging.py`. 43 | 8. Open a command prompt. 44 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 45 | 9. At the command line, go to the directory where you saved the `simple-logging.py` file. 46 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-206\yourname` 47 | 10. At the command prompt, enter the `python` command followed by the filename. 48 | * On Windows, enter: `py -3 simple-logging.py` 49 | * On macOS or Linux, enter: `python3 simple-logging.py` 50 | 11. The program should run or display an error message. 51 | 52 | With the logging level set to 'warning', you should see a result like this: 53 | 54 | ![](assets/images/step2a-results.jpg) 55 | 56 | With the logging level set to 'info', you should see a result like this: 57 | 58 | ![](assets/images/step2b-results.jpg) 59 | 60 | ### Things to try 61 | * Experiment with the different levels to log and display messages. 62 | 63 | **Next step:** 64 | 65 | Proceed to Step 3: Log to a file. 66 | -------------------------------------------------------------------------------- /labs/coding-206-logging/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Log to a file 2 | Normally, you want to save your logs to a file that can be opened and reviewed at any time. 3 | 4 | Here is an example that logs to a file instead of to the console. 5 | 6 | ```python 7 | # Import logging module 8 | import logging 9 | 10 | # Specify that you want to log to a file named mylog.log and that you want to track messages at the DEBUG level 11 | logging.basicConfig(filename='mylog.log',level=logging.DEBUG) 12 | 13 | logging.debug('This is a debug message. You should see this in the file.') 14 | logging.info('This is a debug message. You should see this in the file.') 15 | logging.warning('This is a debug message. You should see this in the file.') 16 | ``` 17 | 18 | Now, look at what is going on in the code. 19 | 20 | * First, import the logging module - `import logging`. 21 | * The `logging.basicConfig(filename='mylog.log',level=logging.DEBUG)` statement specifies the file to which you want to log messages. It also sets the logging level to `DEBUG`. 22 | 23 | ### Give it a try! 24 | 25 | To run this code sample: 26 | 1. Open a text editor. 27 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 28 | 3. Create a folder for this lab. 29 | * For example, *on a DevNet Learning Lab computer*, create a folder in "C:\Coding-206\yourname". 30 | 6. Copy/paste the code shown into your new file. 31 | 7. Save the file with the extension `.py` in your new directory. For example, `logging-step3.py`. 32 | 8. Open a command prompt. 33 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 34 | 9. At the command line, go to the directory where you saved the `logging-step3.py` file. 35 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-206\yourname` 36 | 10. At the command prompt, enter the `python` command followed by the filename. 37 | * On Windows, enter: `py -3 logging-step3.py` 38 | * On macOS or Linux, enter: `python3 logging-step3.py` 39 | 11. The program should run or display an error message. 40 | 41 | Now open the file `mylog.log`. You should see a result like the following one. 42 | 43 | ![](assets/images/step3-results.jpg) 44 | 45 | **Next step:** 46 | 47 | Proceed to Step 4: Format the log messages. 48 | 49 | 50 | 51 | ### Things to try 52 | * Experiment with the different levels to log and display messages. 53 | * Try running the program multiple times. Is the log file overwritten or appended to? 54 | -------------------------------------------------------------------------------- /labs/coding-206-logging/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Format the log messages 2 | 3 | When debugging an application, it is handy to have date and time stamps on the log messages. 4 | 5 | Python provides a way to include the date and time in log messages. 6 | 7 | The following example adds the date and time and some custom formatting the messages. 8 | 9 | ```python 10 | # Import the logging module 11 | import logging 12 | 13 | # Specify to log to a file, specify the format for the message and the date format and the logging level 14 | logging.basicConfig(filename='mylog.log',format='%(asctime)s %(levelname)s: %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.DEBUG) 15 | 16 | # Log some messages 17 | logging.debug('This is a debug message. You should see this in the file.') 18 | logging.info('This is an info message. You should see this in the file.') 19 | logging.warning('This is a warning message. You should see this in the file.') 20 | 21 | ``` 22 | Now, look at what is going on in the code. 23 | 24 | * First, import the logging module - `import logging` 25 | * Add some new things to the `logging.basicConfig` statement. 26 | * `format='%(asctime)s %(levelname)s:` adds the time and level name to the front of each message 27 | * `datefmt='%m/%d/%Y %I:%M:%S %p'` specifies the date/time format to use when displaying the date. 28 | 29 | ### Give it a try! 30 | 31 | To run this code sample: 32 | 1. Open a text editor. 33 | * For example, *on a DevNet Learning Lab computer*, open Notepad++ (**Start > Notepad++**). 34 | 3. Create a folder for this lab. 35 | * For example, *on a DevNet Learning Lab computer*, create a folder in "C:\Coding-206\yourname". 36 | 6. Copy/paste the code shown into your new file. 37 | 7. Save the file with the extension `.py` in your new directory. For example, `logging-step4.py`. 38 | 8. Delete the `mylog.log` file that you created in the previous step. 39 | 9. Open a command prompt. 40 | * For example, *on a DevNet Learning Lab computer*, click **Start > Command Prompt**. 41 | 10. At the command line, go to the directory where you saved the `logging-step4.py` file. 42 | * For example, *on a DevNet Learning Lab computer*, enter: `cd C:\Coding-206\yourname` 43 | 11. At the command prompt, enter the `python` command followed by the filename. 44 | * On Windows, enter: `py -3 logging-step4.py` 45 | * On macOS or Linux, enter: `python3 logging-step4.py` 46 | 12. The program should run or display an error message. 47 | 48 | Now open the file `mylog.log`. You should see a result like the following one. 49 | 50 | ![](assets/images/step4-results.jpg) 51 | 52 | ### Things to try 53 | * Experiment with different format options - you can read more about the format options [here](https://docs.python.org/3/howto/logging.html# changing-the-format-of-displayed-messages). 54 | -------------------------------------------------------------------------------- /labs/coding-206-logging/assets/images/step1-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-206-logging/assets/images/step1-results.jpg -------------------------------------------------------------------------------- /labs/coding-206-logging/assets/images/step2-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-206-logging/assets/images/step2-results.jpg -------------------------------------------------------------------------------- /labs/coding-206-logging/assets/images/step2a-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-206-logging/assets/images/step2a-results.jpg -------------------------------------------------------------------------------- /labs/coding-206-logging/assets/images/step2b-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-206-logging/assets/images/step2b-results.jpg -------------------------------------------------------------------------------- /labs/coding-206-logging/assets/images/step3-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-206-logging/assets/images/step3-results.jpg -------------------------------------------------------------------------------- /labs/coding-206-logging/assets/images/step4-results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-206-logging/assets/images/step4-results.jpg -------------------------------------------------------------------------------- /labs/coding-206-logging/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | To work on this lab on your own machine, you will need to install Python.. 4 |

5 | 6 |

Install Python

7 | 12 | 13 |
-------------------------------------------------------------------------------- /labs/coding-206-logging/coding-206-logging.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "coding-206-logging", 3 | "title": "Coding 206: How to use the Python logging module", 4 | "byod": true, 5 | "slug": "Learn the basics of how to use the logging module", 6 | "time": "15", 7 | "files": [ 8 | {"title": "Step 1: Understand the Python logging module", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Experiment with logging and logging levels", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Log to a file", 13 | "file": "3.md"}, 14 | {"title": "Step 4: Format the log messages", 15 | "file": "4.md"} 16 | ], 17 | "tags": [ 18 | {"title": "Coding"}, 19 | {"title": "Python"}, 20 | {"title": "Sandbox" } 21 | ], 22 | "related": [ 23 | { 24 | "labId": "coding-101-rest-basics", 25 | "title": "Coding 101: REST API Basics" 26 | }, 27 | { 28 | "labId": "coding-102-rest-python", 29 | "title": "Coding 102: Calling REST APIs from Python" 30 | }, 31 | { 32 | "labId": "coding-201-parsing-xml", 33 | "title": "Coding 201: Parsing XML with Python" 34 | }, 35 | { 36 | "labId": "coding-202-parsing-json", 37 | "title": "Coding 202: Parsing JSON with Python" 38 | }, 39 | { 40 | "labId": "coding-203-getting-input", 41 | "title": "Coding 203: Getting input from a user using Python" 42 | }, 43 | { 44 | "labId": "coding-204-reading-a-file", 45 | "title": "Coding 204: Reading from a file using Python" 46 | }, 47 | { 48 | "labId": "coding-205-writing-file", 49 | "title": "Coding 205: Writing data to a file using Python" 50 | }, 51 | { 52 | "labId": "coding-206-logging", 53 | "title": "Coding 206: How to use the logging module in Python" 54 | }, 55 | { 56 | "labId": "coding-207-putting-it-together", 57 | "title": "Coding 207:Python - Putting it all together" 58 | } 59 | ], 60 | "authors": [ 61 | {"name": "brtiller", "email": "brtiller@cisco.com"} 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Configure logging and ask the user for input 2 | The following code performs these steps: 3 | 4 | * Specify the logging file and logging level. 5 | * Ask the user if they want to save a list of routers or switches. 6 | * Ask the user for the filename that they want to use for the list of devices when saved. 7 | 8 | ```python 9 | import logging 10 | logging.basicConfig(filename='mylog.log',format='%(asctime)s %(levelname)s: %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.DEBUG) 11 | 12 | logging.info("Begin") 13 | logging.info("Asking user for device type") 14 | # Ask the user what kind of list they want to create 15 | device_type = input("Do you want to create a list of [r]outers or [s]witches?") 16 | 17 | # Create a variable called type to hold which kind of device to save 18 | if device_type == 'r': 19 | type = "router" 20 | else: 21 | type = "switch" 22 | 23 | logging.info("Device type is " + type) 24 | 25 | # Ask user for name of the file 26 | file_name = input("Specify the filename to use for the list:") 27 | 28 | logging.info("Will save device list to " + file_name) 29 | 30 | ``` 31 | Now, look at what is going on in the code. 32 | 33 | * This line `logging.basicConfig(filename='mylog.log',format='%(asctime)s %(levelname)s: %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.DEBUG)` sets the default logging level to be `Debug`, and formats the logging output to include the date and time. It also specifies `mylog.log` as the logging file. 34 | * Logging to indicates which part of the application is being executed. There are different levels of categorizing logs such as `debug`, `info`, and `warn`. The following logging, uses the `info` level. 35 | * `logging.info("Begin")` 36 | * `logging.info("Asking user for device type")` 37 | * Next, ask the user what kind of device they want to save to the list 38 | * `device_type = input("Do you want to create a list of [r]outers or [s]witches?")` 39 | * And then, ask the user for the filename `file_name = input("Specify the filename to use for the list:")` 40 | 41 | 42 | ### Things to think about 43 | * What other steps should you include in the log? 44 | 45 | **Next step:** 46 | 47 | Proceed to Step 3: Use the DNA Center APIs to retrieve the device list. 48 | -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Use the DNA Center APIs to retrieve the device list 2 | The following code uses the DNA Center REST API to perform the these steps: 3 | 4 | * Create a token to use for authentication when making API calls. 5 | * Get the total count of devices. 6 | * Get the list of network devices. 7 | 8 | ```python 9 | # Get Count of Devices 10 | # All of your REST calls use the URL for the DNA Center as the base URL. 11 | # Define a variable for the controller IP or DNS so you don't have to keep entering it. 12 | controller_url = "https://sandboxdnac.cisco.com" 13 | 14 | # Put the IP address or DNS of your DNA Center in this URL 15 | ticket_url = controller_url + '/api/v1/ticket' 16 | 17 | # The username and password to access the DNA Center 18 | payload = {"username":"devnetuser","password":"Cisco123!"} 19 | 20 | # Content type must be included in the header 21 | header = {"content-type": "application/json"} 22 | 23 | # Perform a POST on the specified url. 24 | response= requests.post(ticket_url,data=json.dumps(payload), headers=header, verify=False) 25 | 26 | # Convert response to JSON format 27 | r_json=response.json() 28 | 29 | # Parse the JSON to get the token 30 | ticket = r_json["response"]["serviceTicket"] 31 | 32 | # Specify URL for the devices count 33 | devices_count_url = controller_url + '/api/v1/network-device/count' 34 | 35 | logging.info("Calling DNA Center API url:" + devices_count_url) 36 | 37 | # Include the content type and ticket in the header 38 | header = {"content-type": "application/json", "X-Auth-Token":ticket} 39 | 40 | # Perform GET on devices_count_url 41 | devices_count_response = requests.get(devices_count_url, headers=header, verify=False) 42 | 43 | # Parse the returned jason to the get count 44 | count = devices_count_response.json()["response"] 45 | 46 | logging.debug("API response: " + json.dumps(devices_count_response.json(), indent=4, separators=(',', ': '))) 47 | 48 | # Get Devices 49 | # This function enables you to view a list of the devices in the network. 50 | # You specify that the list should start with the first device (1) and end with the last device # which is the count of the devices you retrieved in the previous step 51 | get_devices_url = controller_url + '/api/v1/network-device/1/' + str(count) 52 | 53 | logging.info("Calling DNA Center API url:" + get_devices_url) 54 | 55 | # Perform GET on get_devices_url 56 | get_devices_response = requests.get(get_devices_url, headers=header, verify=False) 57 | 58 | # The JSON method of the response object returned by requests.get returns the request body in JSON format 59 | get_devices_json = get_devices_response.json() 60 | 61 | logging.debug("API response: " + json.dumps(get_devices_json, indent=4, separators=(',', ': '))) 62 | ``` 63 | 64 | Now, look at what is going on in the code. 65 | 66 | * Using the [DNA Center API Reference](https://developer.cisco.com/site/dna-center-rest-api/), you can see that the URL `api/v1/ticket` returns the token that's used to authorize calls to the DNA Center APIs. Like the other 'post' and 'get' calls, it uses the Requests library to make a call to the DNA Center to retrieve the response data. 67 | * `api/v1/network-device/count` returns the total count of devices. 68 | * This statement `devices_count_response = requests.get(devices_count_url, headers=header, verify=False)` makes the 'get' call to retrieve the device count. 69 | * `devices_count_response` contain the response returned from the API 70 | * It is useful to log the response to the log file. This can be helpful when debugging. 71 | * `logging.debug("API response: " + json.dumps(devices_count_response.json(), indent=4, separators=(',', ': ')))` 72 | * Next, `/api/v1/network-device/{startIndex}/{endIndex}` DNA Center API call retrieves the full list of devices 73 | * Specify to start at record 1 and get the full list. Specify `1` and the count as the start and end index values. 74 | * `get_devices_url = controller_url + '/api/v1/network-device/1/' + str(count)` 75 | * This statement `get_devices_response = requests.get(get_devices_url, verify=False)` uses the Requests library to make the API call. 76 | * Log the response from this API call to the log file. 77 | * `logging.debug("API response: " + json.dumps(get_devices_response.json(), indent=4, separators=(',', ': ')))` 78 | 79 | 80 | ### Things to think about 81 | * What other DNA Center APIs in the [DNA Center API Reference](https://developer.cisco.com/site/dna-center-rest-api/) would you like to try? 82 | * For more information on using the Requests library to make API calls, see [Coding 102: Calling REST APIs from Python Learning Lab](/lab/coding-102-rest-python-ga/step/1). 83 | 84 | **Next step:** 85 | 86 | Proceed to Step 4: Parse the JSON in the response and write the devices to a file. 87 | -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/Menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/Menu.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/Ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/Ref.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/create-device-list-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/create-device-list-1.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/create-device-list-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/create-device-list-2.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/create-device-list-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/create-device-list-3.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/create-device-list-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/create-device-list-4.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/github-clone-listing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/github-clone-listing.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/github-clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/github-clone.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/login.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/assets/images/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-207-putting-it-together-ga/assets/images/register.png -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/byod.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | To work on this lab on your own machine, you will need to install Python and the Requests library. 4 |

5 |

Install Python

6 | 10 | 11 |

Install the Requests Library

12 |
    13 |
  • You can read more about the Requests Library here
  • 14 |
  • To install Requests for Python 3 on Mac OS, use these command line commands: 15 |
      16 |
    • 17 | sudo curl -O https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py
      18 | sudo python3 get-pip.py
      19 | pip3 install requests
      20 |             
    • 21 |
    22 |
  • 23 |
  • To install Requests on Windows: 24 |
      25 |
    • Pip comes with Python 3.4 Windows
    • 26 |
    • Check to see if Pip is in your python 3 path
    • 27 |
    • 28 |
      29 | C:\>pip –V
      30 | pip 1.5.6 from C:\Python34\lib\site-packages
      31 |                 
      32 |
    • 33 |
    • If pip is in the Python34 path, the execute 34 |
      35 | pip install requests
      36 |                 
      37 |
    • 38 |
    39 |
  • 40 |
  • 41 | You will also need Access to DNA Center. 42 | 47 |
  • 48 |
49 | 50 |

Clone Git Repo

51 |
    52 |
  • Clone the coding skills sample code
  • 53 |
  • git clone https://github.com/CiscoDevNet/coding-skills-sample-code
  • 54 |
55 |
56 | -------------------------------------------------------------------------------- /labs/coding-207-putting-it-together-ga/coding-207-putting-it-together-ga.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "coding-207-putting-it-together-ga", 3 | "title": "Coding 207: Python - Putting it all together", 4 | "byod": true, 5 | "slug": "Use all of the Coding 201 skills to retrieve and save a list of devices of specific type.", 6 | "time": "20", 7 | "files": [ 8 | {"title": "Step 1: Find the DNA Center API Reference documentation", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Configure logging and ask the user for input", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Use the DNA Center APIs to retrieve the device list", 13 | "file": "3.md"}, 14 | {"title": "Step 4: Parse the JSON in the response and write the devices to a file", 15 | "file": "4.md"} 16 | ], 17 | "tags": [ 18 | {"title": "Coding"}, 19 | {"title": "Python"}, 20 | {"title": "JSON"}, 21 | {"title": "DNA Center"}, 22 | {"title": "REST"}, 23 | {"title": "Sandbox"} 24 | ], 25 | "related": [ 26 | { 27 | "labId": "coding-101-rest-basics-ga", 28 | "title": "Coding 101: REST API Basics" 29 | }, 30 | { 31 | "labId": "coding-102-rest-python-ga", 32 | "title": "Coding 102: Calling REST APIs from Python" 33 | }, 34 | { 35 | "labId": "coding-201-parsing-xml", 36 | "title": "Coding 201: Parsing XML with Python" 37 | }, 38 | { 39 | "labId": "coding-202-parsing-json", 40 | "title": "Coding 202: Parsing JSON with Python" 41 | }, 42 | { 43 | "labId": "coding-203-getting-input", 44 | "title": "Coding 203: Getting input from a user using Python" 45 | }, 46 | { 47 | "labId": "coding-204-reading-a-file", 48 | "title": "Coding 204: Reading from a file using Python" 49 | }, 50 | { 51 | "labId": "coding-205-writing-file-ga", 52 | "title": "Coding 205: Writing data to a file using Python" 53 | }, 54 | { 55 | "labId": "coding-206-logging", 56 | "title": "Coding 206: How to use the logging module in Python" 57 | } 58 | ], 59 | "authors": [ 60 | {"name": "brtiller", "email": "brtiller@cisco.com"} 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/1.md: -------------------------------------------------------------------------------- 1 | # Coding 210: Parsing JSON using C++ 2 | 3 | In this Learning Lab, you learn the basics of parsing JSON content using C++. You will use the [Connected Mobile Experiences (CMX) Mobility Services](https://developer.cisco.com/site/cmx-mobility-services/ "CMX Mobility Services") to query the names of available access points and put them into a simple list for display. To learn more about CMX, review the [Mobility Services Engine (MSE) Learning Lab](# /labs/cmx/step/1). 4 | 5 | 6 | ## Objectives 7 | 8 | * Create a basic C\+\+ application. 9 | * Understand the basics of reading and parsing HTTP content using C\+\+. 10 | * Save JSON content to file using C\+\+. 11 | * Learn how to use C\+\+ to extract only the JSON data you want using the libcurl and the JSONcpp library. 12 | 13 | ## Prerequisites 14 | 15 | * A text editor. 16 | * Complete the [Coding Fundamentals](https://developer.cisco.com/learning/modules/programming-fundamentals) and [REST API Fundamentals](https://developer.cisco.com/learning/modules/rest-api-fundamentals) Learning Lab modules. if you are unfamiliar with Python and retrieving results from a RESTful service and the [Parsing XML using Python Lab](lab/coding-201-parsing-xml/step/1 "Parsing XML using Python Lab") for a similar approach to retrieving data using XML. 17 | 18 | ##### On Windows 19 | Install Cygwin with the gcc compiler and libcurl libraries. 20 | 21 | You should also have a basic familiarity with JSON. Otherwise, consider visiting the [W3Schools JSON Tutorial](https://www.w3schools.com/js/js_json_intro.asp "W3Schools JSON Tutorial"). 22 | 23 | For this lab, use the GNU C Compiler (g\+\+) version 4.9.+ tailored for C\+\+. If you have g\+\+ already installed, verify your version entering the following command: 24 | ``` 25 | g++ --version 26 | ``` 27 | If you are on a DevNet Learning Lab computer, the correct version of g\+\+ should already be installed. 28 | 29 | ## Step 1: Create an executable in C++ 30 | 31 | C and C++ are compiled languages. This means that you need to compile your program into object files and then link them into an executable file using a linker. 32 | 33 | To get started, create a simple C++ file that outputs "Hello World!" to the command line. 34 | 35 | 1. Create a folder on the computer called `Coding210`. 36 | 2. Open a text editor and create a file named `hello.cpp`. 37 | 3. Save `hello.cpp` to the `Coding210` folder on computer. 38 | 4. Within the text editor, add the following lines to `hello.cpp`: 39 | 40 | ``` 41 | # Include 42 | using namespace std; 43 | int main() { 44 | cout << "Hello World!" << endl; 45 | } 46 | ``` 47 | This snippet: 48 | - Includes the `iostream` header required for using the standard input/output stream objects. 49 | - Declaring that it is using the standard library namespace: `std` 50 | - Defining a `main()` function which will be called by default. 51 | - Outputting the string "Hello World!" using `cout`, the standard output stream. 52 | 53 | To download or review the current code, you can get it from Cisco DevNet GitHub: hello.cpp. 54 | 55 | Next, compile the file you created. 56 | 4. Save the `hello.cpp` file with the code added. 57 | 5. Open a Cygwin command prompt and navigate to the `Coding210` directory on the Desktop: 58 | ``` 59 | cd ~/Desktop/Coding210 60 | ``` 61 | 6. When your are in the local `Coding210` directory, in the command prompt window, enter the following command to compile your application: 62 | ``` 63 | g++ -o hello hello.cpp 64 | ``` 65 | 7. After you run the command, you should see a `hello.exe` file in the directory. You can list files and folders in your current directory by entering the following command: 66 | ``` 67 | ls 68 | ``` 69 | **If there are any errors, correct them and retry the compilation.**

70 | 8. If the compilation was successful, enter the following command to run your new executable: 71 | ``` 72 | ./hello.exe 73 | ``` 74 | 75 | ---------- 76 | 77 | If everything went according to plan, you should see 'Hello World!' output to the screen. Compiling and running this basic application verifies that your software build toolchain is working. Now, move on and add more functionality in the next step. 78 | 79 | **Next step:** 80 | 81 | Step 2: Adding cURL library support into the C++ application. 82 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Adding cURL library support into the C++ application 2 | 3 | ### Adding support for getting HTTP 4 | 5 | C and C++ do not come with a native library to access HTML content on the Internet using HTTP. However, you can add libraries that provide this capability. One of the more popular tools is cURL, a command-line utility for accessing web content. cURL also provides a library, `libcurl`, that you can use to simplify the complex task of asking for web content. The following instructions show you how to add support for libcurl to any application you are developing. 6 | 7 | ---------- 8 | 9 | To enable support for libcurl, complete the following steps. 10 | 11 | 1. Download the libcurl library. 12 | ##### On Windows using Cygwin 13 | Cygwin enables you to add libcurl support by installing it through the Cygwin package support. This should already be set up on the DevNet Learning Lab for the Cygwin instance. However, you are doing this on your computer, make sure the libcurl libraries are installed. 14 | 15 | 2. Modify your code to include the Headers needed to use the functionality provided by libcurl.
16 | To use the functionality provided by libcurl, include the programmatic definitions into your source code and use them as prescribed by the [cURL documentation](https://curl.haxx.se/libcurl/). To simplify things even further, use the cURL "Easy" options for setting up a connection. 17 | 18 | 3. Change how you compile the application to include the required libraries.
19 | Now that you've installed libcurl, you append the `-lcurl` flag to your compilation command. 20 | 21 | ---------- 22 | 23 | Now, now create a sample application that can reach out to the Internet. 24 | 1. Create a new file named `main-http.cpp`. 25 | 3. Save `main-http.cpp` to the `Coding210` folder on computer. 26 | 4. Within the text editor, add the following lines to `main-http.cpp`: 27 | 28 | ``` 29 | # Include 30 | # Include "curl/curl.h" 31 | # Include "curl/easy.h" 32 | 33 | using namespace std; 34 | 35 | int main() { 36 | 37 | string uri = "https://www.cisco.com"; 38 | 39 | CURLcode res; 40 | CURL *curl = curl_easy_init(); 41 | if(curl) { 42 | 43 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); 44 | res = curl_easy_perform(curl); 45 | 46 | if(res != CURLE_OK) 47 | cerr << "ERROR: " << curl_easy_strerror(res) << endl; 48 | else { 49 | // You should have received data from the URI 50 | } 51 | 52 | curl_easy_cleanup(curl); 53 | } 54 | 55 | return 0; 56 | } 57 | ``` 58 | 59 | This snippet: 60 | - Includes the `iostream` and `curl` headers required for using the standard input/output stream objects and curl\_easy\_* functions. 61 | - Declares that it is using the standard library namespace: `std` 62 | - Defines a `main()` function, which will be called by default. 63 | - Declares a URI that you want to get from the Internet. 64 | - Instantiates a curl object and calls `curl_easy_perform` to get data from the URI. 65 | - Cleans up the resources by calling `curl_easy_cleanup` on the curl object it initialized. 66 | 67 | To download or review the current code, you can get it from Cisco DevNet GitHub: main-http.cpp. 68 | 69 | Next, compile the file you created. 70 | 1. When your are in the local `Coding210` directory, in the command prompt window, enter the following command to compile your application: 71 | ``` 72 | g++ -o main-http main-http.cpp -lcurl 73 | ``` 74 | Notice that this is very similar to how you compiled in Step 1. The main difference is including a `-l` flag to indicate that you are including the cURL library.

75 | 2. When you run the command, you should see a `main-http.exe` file in the directory. If there are any errors, correct them and retry the compilation. 76 | 3. If the compilation was successful, enter the following command to run your new executable: 77 | ``` 78 | ./main-http.exe 79 | ``` 80 | 81 | ---------- 82 | 83 | If everything went according to plan, you should see HTML content output to the screen. This is a step closer your final goal and verifies that you can pull content from the Internet. Now, move on and add get some JSON content in the next step. 84 | 85 | **Next step:** 86 | 87 | Proceed to Step 3: Getting JSON content. 88 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Getting JSON content 2 | 3 | ### Connecting to a JSON URI 4 | 5 | In the previous step, you downloaded HTML content from the Internet. In this step, you would like to get JSON content instead. To do this, go to a URI that provides JSON content and also modify your request to accept JSON content from the server. 6 | 7 | ---------- 8 | 9 | Now, modify your sample application to get JSON content from the Internet. 10 | 1. Create a new file named `main-json.cpp`. 11 | 3. Save `main-json.cpp` to the `Coding210` folder on computer. 12 | 4. Within the text editor, add the following lines to `main-json.cpp`: 13 | 14 | ``` 15 | # Include 16 | # Include "curl/curl.h" 17 | # Include "curl/easy.h" 18 | 19 | using namespace std; 20 | 21 | int main() { 22 | 23 | string uri = "https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone"; 24 | string header_authorization = "Authorization: Basic bGVhcm5pbmc6bGVhcm5pbmc="; 25 | string header_accept = "Accept: application/json"; 26 | 27 | struct curl_slist *headers = NULL; 28 | headers = curl_slist_append(headers, header_authorization.c_str()); 29 | headers = curl_slist_append(headers, header_accept.c_str()); 30 | 31 | CURLcode res; 32 | CURL *curl = curl_easy_init(); 33 | if(curl) { 34 | 35 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); 36 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 37 | res = curl_easy_perform(curl); 38 | 39 | if(res != CURLE_OK) 40 | cerr << "ERROR: " << curl_easy_strerror(res) << endl; 41 | else { 42 | // You should have received data from the URI 43 | } 44 | 45 | curl_easy_cleanup(curl); 46 | } 47 | 48 | return 0; 49 | } 50 | ``` 51 | 52 | This snippet: 53 | - Does everything the snippet in Step 2 did, but goes to another CMX URI at msesandbox.cisco.com to get JSON content. 54 | - Adds an Authorization header that does "Basic" authorization with a Base64 encoded user:password of "learning:learning" 55 | - Adds an Accept header that is telling the server it would like to accept JSON content 56 | - Adds these headers into a curl_slist called 'headers' 57 | - Before calling `curl_easy_perform`, it sets the headers for the call using `curl_easy_setopt` with the `headers` passed in. 58 | 59 | To download or review the current code, you can get it from Cisco DevNet GitHub: main-json.cpp. 60 | 61 | Next, compile the file you created. 62 | 1. When your are in the local `Coding210` directory, in the command prompt window, enter the following command to compile your application: 63 | ``` 64 | g++ -o main-json main-json.cpp -lcurl 65 | ``` 66 | 2. When you run the command, you should see a `main-http.exe` file in the `Coding210` directory. If there are any errors, correct them and retry the compilation. 67 | 3. If the compilation was successful, enter the following command to run your new executable: 68 | ``` 69 | ./main-json.exe 70 | ``` 71 | 72 | ---------- 73 | 74 | If everything went according to plan, you should see a blob of JSON content output to the screen. In the next step parse that returned content using a JSON libarary to make it a bit more human-readable. 75 | 76 | **Next step:** 77 | 78 | Proceed to Step 4. Adding JSON library support into the C++ application. 79 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/5.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Extract specific fields from JSON 2 | 3 | In the previous step you parsed and returned _all_ the JSON content using RapidJSON. In this step, you extract the pieces of information you are looking for: Access Point names. 4 | 5 | ---------- 6 | 7 | To get the Access Point names, modify your sample application to print out specific elements of the JSON you requested in the last step. 8 | 1. Create a new file named **main.cpp**. 9 | 3. Save **main.cpp** to the `Coding210` folder on computer. 10 | 4. Within the text editor add (copy & paste) the following lines to **main.cpp**: 11 | 12 | ``` 13 | # Include 14 | # Include 15 | # Include "curl/curl.h" 16 | # Include "curl/easy.h" 17 | # Include "rapidjson/document.h" 18 | # Include "rapidjson/writer.h" 19 | # Include "rapidjson/stringbuffer.h" 20 | 21 | using namespace std; 22 | using namespace rapidjson; 23 | 24 | struct JSONDATA 25 | { 26 | fstream *file; 27 | string *str; 28 | }; 29 | 30 | size_t write_data(void *ptr, size_t size, size_t nmemb, JSONDATA *data) { 31 | 32 | size_t numBytes = size * nmemb; 33 | 34 | if (data->file) 35 | data->file->write((char*)ptr, numBytes); 36 | 37 | if (data->str) 38 | *(data->str) += std::string((char*)ptr, numBytes); 39 | 40 | return numBytes; 41 | } 42 | 43 | int main() { 44 | 45 | CURL *curl; 46 | CURLcode res; 47 | 48 | string uri = "https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone"; 49 | string header_authorization = "Authorization: Basic bGVhcm5pbmc6bGVhcm5pbmc="; 50 | string header_accept = "Accept: application/json"; 51 | 52 | struct curl_slist *headers = NULL; 53 | headers = curl_slist_append(headers, header_authorization.c_str()); 54 | headers = curl_slist_append(headers, header_accept.c_str()); 55 | 56 | curl = curl_easy_init(); 57 | 58 | fstream file("content.json", ios_base::out | ios_base::ate); 59 | string json; 60 | 61 | JSONDATA data; 62 | data.file = &file; 63 | data.str = &json; 64 | 65 | if(curl) { 66 | 67 | curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); 68 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 69 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 70 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); 71 | 72 | res = curl_easy_perform(curl); 73 | 74 | if(res != CURLE_OK) 75 | cerr << "ERROR: " << curl_easy_strerror(res) << endl; 76 | else { 77 | 78 | Document document; 79 | document.Parse(json.c_str()); 80 | 81 | Value& accessPoint = document["Floor"]["AccessPoint"]; 82 | assert(accessPoint.IsArray()); 83 | 84 | // Iterate through the Access Points 85 | for (SizeType i = 0; i < accessPoint.Size(); i++) 86 | printf("accessPoint: %s\n", accessPoint[i]["name"].GetString()); 87 | } 88 | 89 | curl_easy_cleanup(curl); 90 | } 91 | 92 | return 0; 93 | } 94 | ``` 95 | This snippet: 96 | - Doing everything you had done in the previous step 97 | - When the cURL call is successful, you attempt to parse the RapidJSON Document to get an Array of AccessPoint values from the Floor element 98 | 99 | To download or review the current code, you can get it from Cisco DevNet GitHub: main.cpp. 100 | 101 | To review the annotated version of the application that includes comments inline, you can get it from Cisco DevNet GitHub: main-annotated.cpp. 102 | 103 | Next, compile the file you created. 104 | 1. When your are in the local `Coding210` directory, in the command prompt window, enter the following command to compile your application: 105 | ``` 106 | g++ -o get_aps main.cpp -Irapidjson/include -lcurl 107 | ``` 108 | Notice that you are changing the output application name to 'get_aps' by modifiying your compliation command and specifying what you would like to name the application.
109 | 110 | 3. When you run the command, you should see a `get_aps.exe` file in the directory. If there are any errors, correct them and retry the compilation. 111 | 3. If the compilation was successful, enter the following command to run your new executable: 112 | ``` 113 | ./get_aps.exe 114 | ``` 115 | 116 | ---------- 117 | 118 | When you run this application you should see a list of extracted Access Point names. With this approach, you could format or do further extraction based on the returned results. 119 | 120 | **Next step:** 121 | 122 | Proceed to Step 6: Find additional resources. 123 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/6.md: -------------------------------------------------------------------------------- 1 | ## Step 6: Find additional resources 2 | 3 | For more information on the topics in this lab, visit one of the following resources. 4 | 5 | ### JavaScript Object Notation (JSON) 6 | 7 | For more information on JavaScript Object Notation (JSON) visit: [https://www.json.org/](https://www.json.org/ "JSON.org") 8 | 9 | Also consider visiting the JavaScript Object Notation (JSON) tutorials: [https://www.w3schools.com/js/js_json_intro.asp](https://www.w3schools.com/js/js_json_intro.asp "W3Schools JSON") 10 | 11 | 12 | ### C++ 13 | 14 | C/C\+\+ is a powerful Object Oriented programming language. It is not for the faint of heart but the capabilities and performance make it a great choice for many projects. If you are interested in learning more, look to the C++ tutorial at [http://www.cplusplus.com/doc/tutorial/](http://www.cplusplus.com/doc/tutorial/ "C\+\+ Tutorial") to get started. 15 | 16 | **C/C++ JSON Libraries**
17 | The documentation for the RapidJSON library can be found at [https://miloyip.github.io/rapidjson/](https://miloyip.github.io/rapidjson/ "RapidJSON Documentation"). 18 | 19 | Other libraries are popular as well. For example, JsonCPP is a C++ library that can be found at [https://github.com/open-source-parsers/jsoncpp](https://github.com/open-source-parsers/jsoncpp "JsonCPP"). 20 | 21 | For a full list of C++ parsers, you refer to the JSON.org site at [https://www.json.org](https://www.json.org "JSON.org") 22 | 23 | 24 | ### Connected Mobile Experiences 25 | 26 | If you are interested in more information about Cisco Connected Mobile Experiences, look to the following information. 27 | 28 | **Product Information**
29 | [https://www.cisco.com/c/en/us/solutions/enterprise-networks/connected-mobile-experiences/index.html](https://www.cisco.com/c/en/us/solutions/enterprise-networks/connected-mobile-experiences/index.html "Connected Mobile Experiences Product Site") 30 | 31 | **Developer Resources**
32 | [https://developer.cisco.com/site/cmx-mobility-services/](https://developer.cisco.com/site/cmx-mobility-services/ "Connected Mobile Experiences Developer Site") 33 | 34 | **Mobility Services Engine (MSE) API Documentation**
35 | [https://developer.cisco.com/site/cmx-mobility-services/documents/api-reference-manual/](https://developer.cisco.com/site/cmx-mobility-services/documents/api-reference-manual/ "MSE API Documentation") 36 |
37 |
38 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/byod.html: -------------------------------------------------------------------------------- 1 |
2 | For this lab we will be using the Gnu C Compiler (gcc) version 4.9.2. If you have gcc already installed, you can verify your version by running the following command in a terminal window: 3 | 4 | gcc --version 5 | 6 |
-------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/coding-210-parsing-json-c++.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "coding-210-parsing-json-c++", 3 | "title": "Coding 210: Parsing JSON with C++", 4 | "byod": false, 5 | "slug": "Learn how to parse and work with JSON data in the C++ language.", 6 | "time": "20", 7 | "files": [ 8 | {"title": "Step 1: Create an executable in C++", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Adding cURL library support into the C++ application", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Getting JSON content", 13 | "file": "3.md"}, 14 | {"title": "Step 4. Adding JSON library support into the C++ application", 15 | "file": "4.md"}, 16 | {"title": "Step 5: Extract specific fields from JSON", 17 | "file": "5.md"}, 18 | {"title": "Step 6: Find additional resources", 19 | "file": "6.md"} 20 | ], 21 | "tags": [ 22 | {"title": "Coding"}, 23 | {"title": "C++"}, 24 | {"title": "JSON"}, 25 | {"title": "DNA Center"}, 26 | {"title": "REST"}, 27 | {"title": "Sandbox"} 28 | ], 29 | "related": [ 30 | { 31 | "labId": "coding-101-rest-basics", 32 | "title": "Coding 101: REST API Basics" 33 | }, 34 | { 35 | "labId": "coding-102-rest-python", 36 | "title": "Coding 102: Calling REST APIs from Python" 37 | }, 38 | { 39 | "labId": "coding-202-parsing-json", 40 | "title": "Coding 202: Parsing JSON with Python" 41 | }, 42 | { 43 | "labId": "coding-203-getting-input", 44 | "title": "Coding 203: Getting input from a user using Python" 45 | }, 46 | { 47 | "labId": "coding-204-reading-a-file", 48 | "title": "Coding 204: Reading from a file using Python" 49 | }, 50 | { 51 | "labId": "coding-205-writing-file", 52 | "title": "Coding 205: Writing data to a file using Python" 53 | }, 54 | { 55 | "labId": "coding-206-logging", 56 | "title": "Coding 206: How to use the logging module in Python" 57 | }, 58 | { 59 | "labId": "coding-207-putting-it-together", 60 | "title": "Coding 207:Python - Putting it all together" 61 | } 62 | ], 63 | "authors": [ 64 | {"name": "brtiller", "email": "brtiller@cisco.com"} 65 | ], 66 | "active": false 67 | } 68 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/command-compile.txt: -------------------------------------------------------------------------------- 1 | g++ -o jsonParse main.cpp -Irapidjson/include -lcurl 2 | 3 | 4 | -------------------------------------------------------------------------------- /labs/coding-210-parsing-json-c++/setup-cygwin-select-libcurl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/coding-210-parsing-json-c++/setup-cygwin-select-libcurl.png -------------------------------------------------------------------------------- /labs/parsing-json/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Use the JSON Python library 2 | 3 | ### Use Python's JSON object 4 | 5 | The large JSON result you got in the previous step is a string. It has no special properties beyond that. To parse it, you would parse it as a string. However, Python comes with a standard `json` library for encoding/decoding and accessing JSON content. This library uses patterns that are familiar to Python developers. When you load a string using the `json` decoder, it converts JSON objects into Python [dictionaries](https://docs.python.org/3.4/reference/expressions.html#dictionary-displays) and JSON arrays into Python [lists](https://docs.python.org/3.4/reference/expressions.html#list-displays). This is useful because it then enables you to access and iterate through JSON as Python data. 6 | 7 | Another useful tool of the JSON library is it's ability to "pretty print" the JSON output into a hierarchical structure. This makes it easier to see the overall structure of the data. Now, use that capability to print the data into a more human-readable output. 8 | 9 | > **Note**: The `requests` library has the ability to return the data from the query in JSON without any additional lines of code, however, in this lab we will not be using this ability in order to understand how the `json` library works within Python. 10 | 11 | 1. Normally, we'd need to odify the second line of `get-tenant-json.py` to import the JSON library, however, due to the construct of the ACI authentication, we've already imported it. You can verify that this line is present in the file: 12 | 13 | ``` 14 | import json 15 | ``` 16 | 17 | 2. Comment out the `print(tenants.text)` line by putting a pound or hash sign at the front of the line: 18 | 19 | ``` 20 | # print(tenants.text) 21 | ``` 22 | You are commenting out this line because you are going to use the `json` library to pretty print your output. 23 | 24 | 3. Update `get-tenant-json.py` by adding the following line below `#print(tenants.text)`: 25 | 26 | ``` 27 | json_response = json.loads(tenants.text) 28 | ``` 29 | 30 | The `json.loads()` method loads the `tenants.text` into a JSON object. If it is successful, you can use square brackets to get a particular element from `json_response`. 31 | 32 | 4. Add the following line just below the previous line you added: 33 | 34 | ``` 35 | print(json.dumps(json_response, sort_keys=True, indent=4)) 36 | ``` 37 | 38 | This line prints the elements `dumps()` method returns from the `json_response`. The arguments control how the output is displayed. 39 | 40 | 5. Save the `get-tenant-json.py` file. To download or review the current code, you can get it from GitHub [here](https://github.com/CiscoDevNet/coding-skills-sample-code/blob/master/coding202-parsing-json/get-tenant-json-2.py). 41 | 42 | 6. To run your newly created file, enter: 43 | 44 | ``` 45 | python get-tenant-json.py 46 | ``` 47 | 48 | 7. The Python script gets and displays the following JSON data. 49 | 50 | ![](assets/images/json-output-pretty-new.png) 51 | 52 | -------------------------------------------------------------------------------- 53 | 54 | The content and structure of this data is easier for you to read and understand. 55 | 56 | ### Understanding the returned JSON data 57 | 58 | Because you are getting JSON data, the content you get back has a particular order or schema. Elements of the returned 'fv-Tenant' ACI Managed Object (MO) class parsed in JSON data have sub-objects and even sub-dictionaries and sub-lists. For this exercise, you are interested in the **name**, **dn**, and **health** of each of the tenants configured within the fabric. This approach returns the desired information, as well as additional bits returned as part of the query to the `fv-Tenant` class. 59 | 60 | ``` 61 | {fvTenant} 62 | {attributes} 63 | annotation 64 | childAction 65 | descr 66 | dn 67 | extMngdBy 68 | lcOwn 69 | modTs 70 | monPolDn 71 | name 72 | nameAlias 73 | ownerKey 74 | ownerTag 75 | status 76 | uid 77 | {children} 78 | {healthInst} 79 | {attributes} 80 | ... 81 | ... 82 | ... 83 | ``` 84 | 85 | In the example shown, `fvTenant` is dictionary of multiple tenant objects - each with their `name`, `dn`, and other attributes. 86 | 87 | Now that you have seen this structure, go to the next step and learn how to get only the data you care about. 88 | 89 | **Next step:** 90 | 91 | Proceed to Step 3: Iterate through a JSON dictionary in Python. 92 | -------------------------------------------------------------------------------- /labs/parsing-json/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Iterate through a JSON dictionary in Python 2 | 3 | ### Loop through a Python dictionary 4 | 5 | In the previous step, you decoded the JSON content into a `json_response` variable. This conversion allows a developer to easily access the information contained within using loops to iterate through the data. Using this method, we will loop through the tenants, print their name, DN, and their health score. 6 | 7 | To loop through the tenants within a dictionary, first get the tenants using the `json` library. Then, use a Python `for` loop to go through each element of the list. A second loop won't be required, as the list contained within the `children` element returned only contains a single value, `healthInst`. 8 | 9 | Keep in mind that you may need to reference the pretty-print JSON that we created in the previous section, focusing on a single tenant within the output, in order to iterate through the object correctly. You can also run the script from the previous section in "interactive" mode using `python -i`, which will allow you to interact with the stored variables to determine what the nested types are and how to access different elements to get to the desired key-value pairs in the JSON. 10 | 11 | > **Note**: this looks like a lot of manipulation and parsing, but it will provide a very good testbed to understand how to iterate through JSON 12 | 13 | 1. Preserving the indentation, comment out the previous print statement (wherein we printed the "pretty" JSON) and add the following lines: 14 | 15 | ```python 16 | json_tenants = json_response['imdata'] 17 | for tenant in json_tenants: 18 | tenant_name = tenant['fvTenant']['attributes']['name'] 19 | tenant_dn = tenant['fvTenant']['attributes']['dn'] 20 | tenant_health = tenant['fvTenant']['children'][0]['healthInst']['attributes']['cur'] 21 | output = "Tenant: " + tenant_name + "\t Health Score: " + tenant_health + "\n DN: " + tenant_dn 22 | print(output.expandtabs(40)) 23 | ``` 24 | 25 | This snippet: 26 | 27 | - Starts the initial entry point inside of the `imdata` dictionary 28 | - Creates a `for` loop to iterate through the list of `fvTenant` objects sequentially 29 | - Gathers the `name` and `dn` values within the `attributes` dictionary contained within the `fvTenant` dictionary 30 | - Gathers the current health score by pulling the value from the `children` dictionary. This is pulled from the list of child objects (there's only a single item, which is why this can be safely set to `0`), and then moving through the `healthInst` dictionary, followed by the `attributes` dictionary and pulling the value from `cur` 31 | - Prints the resulting data with nice formatting, using the `expandtabs` method. If the resulting printed data is not aligned, increase this value to 50 or so (results will vary due to length of configured tenant names on the fabric at any one time) 32 | 33 | 2. Save the `get-tenant-json.py` file. To download or review the current code, you can get it from GitHub [here](https://github.com/CiscoDevNet/coding-skills-sample-code/blob/master/coding202-parsing-json/get-tenant-json-3.py) 34 | 35 | 3. Enter the following command to run your file. 36 | 37 | ``` 38 | python get-tenant-json.py 39 | ``` 40 | 41 | 4. When you run the Python script, at the end of the output, you should get the JSON data values returned for each tenant in a format that looks similar to this: 42 | 43 | ![](assets/images/json-output-parse-001-new.png) 44 | 45 | -------------------------------------------------------------------------------- 46 | 47 | This is a very direct way to use Python to get data from a REST service using JSON and parse out only the information you care about. Depending on the capabilities of the REST API, you can also sometimes pass in query parameters or other information to reduce the scope of returned data or search for a single or group of specific items. 48 | 49 | For a summary of resources, continue on to the last step. 50 | 51 | **Next step:** 52 | 53 | Proceed to Step 4: Find additional resources. 54 | -------------------------------------------------------------------------------- /labs/parsing-json/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Find additional resources 2 | 3 | For more information on the topics covered, visit the following resources. 4 | 5 | ### JavaScript Object Notation (JSON) 6 | 7 | For more information on JavaScript Object Notation (JSON), visit [https://www.json.org/](https://www.json.org/ "JSON.org"). 8 | 9 | Also consider visiting the JavaScript Object Notation (JSON) tutorials at [https://www.w3schools.com/js/js_json_intro.asp](https://www.w3schools.com/js/js_json_intro.asp "W3Schools JSON") 10 | 11 | ### Python 12 | 13 | Python is a powerful tool. To learn more, visit [https://docs.python.org/3.4/tutorial/](https://docs.python.org/3.4/tutorial/ "Python Tutorial"). 14 | 15 | **Python JSON Libraries**
16 | The documentation for the JSON Python library can be found at [https://docs.python.org/3.4/library/json.html](https://docs.python.org/3.4/library/json.html "Python JSON"). 17 | 18 | ### Application Centric Infrastructure 19 | 20 | **Product Information**
21 | [https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html](https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html "Application Centric Infrastructure (ACI) Product Site") 22 | 23 | **Developer Resources**
24 | [https://developer.cisco.com/site/aci/](https://developer.cisco.com/site/aci/ "Application Centric Infrastructure Developer Site") 25 | 26 | **Application Centric Infrastructure (ACI) API Documentation**
27 | [https://developer.cisco.com/docs/aci/](https://developer.cisco.com/docs/aci/ "ACI API Documentation") 28 | -------------------------------------------------------------------------------- /labs/parsing-json/assets/images/json-output-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-json/assets/images/json-output-new.png -------------------------------------------------------------------------------- /labs/parsing-json/assets/images/json-output-parse-001-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-json/assets/images/json-output-parse-001-new.png -------------------------------------------------------------------------------- /labs/parsing-json/assets/images/json-output-parse-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-json/assets/images/json-output-parse-001.png -------------------------------------------------------------------------------- /labs/parsing-json/assets/images/json-output-pretty-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-json/assets/images/json-output-pretty-new.png -------------------------------------------------------------------------------- /labs/parsing-json/assets/images/json-output-pretty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-json/assets/images/json-output-pretty.png -------------------------------------------------------------------------------- /labs/parsing-json/assets/images/json-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-json/assets/images/json-output.png -------------------------------------------------------------------------------- /labs/parsing-json/byod.html: -------------------------------------------------------------------------------- 1 |
2 | For this lab we will be using Python 3.4+. To verify your version run the following command in a terminal window: 3 | 4 | python --version 5 | 6 |
-------------------------------------------------------------------------------- /labs/parsing-json/get-ap-json.py: -------------------------------------------------------------------------------- 1 | from urllib.request import Request, urlopen 2 | import json 3 | 4 | # Let's construct a request with headers 5 | req = Request('https://devnetapi.cisco.com/sandbox/mse/api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone') 6 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc=') 7 | req.add_header('Accept', 'application/json') 8 | 9 | # Actually open the request 10 | response = urlopen(req) 11 | 12 | # Read the response into a JSON String 13 | responseString = response.read().decode("utf-8") 14 | 15 | #res = json.dump(obj, out, sort_keys=True, indent=4, separators=(',', ': ')) 16 | # Print out the response string 17 | #print(responseString) 18 | 19 | # Load the JSON string into a JSON object 20 | json_object = json.loads(response_string) 21 | #print(json_object) 22 | print(json.dumps(json_object, sort_keys=True, indent=4)) 23 | 24 | # Only output what we are interested in - the AP name and IP address 25 | #access_points = json_object['accessPoints'] 26 | #for ap in access_points: 27 | # print('Access Point: ' + ap['name'] + '\t mac: ' + ap['radioMacAddress']) 28 | 29 | # Let's close the response we opened 30 | response.close() 31 | -------------------------------------------------------------------------------- /labs/parsing-json/parsing-json.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "parsing-json", 3 | "title": "Parsing JSON", 4 | "slug": "Learn the basics of how to use parse JSON results using Python.", 5 | "byod": true, 6 | "time": "15", 7 | "files": [ 8 | {"title": "Step 1: Make an HTTP REST call with Python", 9 | "file": "1.md"}, 10 | {"title": "Step 2: Use the JSON Python library", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Iterate through a JSON dictionary in Python", 13 | "file":"3.md"}, 14 | {"title": "Step 4: Find additional resources", 15 | "file": "4.md"} 16 | ], 17 | "tags": [ 18 | {"title" : "Cloud"}, 19 | {"title" : "Coding"}, 20 | {"title": "Parsing"}, 21 | {"title": "JSON"}, 22 | {"title": "Python"}, 23 | {"title": "ACI"}, 24 | {"title" : "Sandbox" } 25 | ], 26 | "related": [ 27 | { 28 | "labId": "rest-basics", 29 | "title": "REST API Basics" 30 | }, 31 | { 32 | "labId": "rest-python", 33 | "title": "Calling REST APIs from Python" 34 | }, 35 | { 36 | "labId": "parsing-xml", 37 | "title": "Parsing XML with Python" 38 | }, 39 | { 40 | "labId": "parsing-json", 41 | "title": "Parsing JSON with Python" 42 | }, 43 | { 44 | "labId": "getting-input", 45 | "title": "Getting input from a user using Python" 46 | }, 47 | { 48 | "labId": "reading-a-file", 49 | "title": "Reading from a file using Python" 50 | }, 51 | { 52 | "labId": "writing-file", 53 | "title": "Writing data to a file using Python" 54 | }, 55 | { 56 | "labId": "logging", 57 | "title": "How to use the logging module in Python" 58 | }, 59 | { 60 | "labId": "putting-it-together", 61 | "title": "Python - Putting it all together" 62 | } 63 | ], 64 | "authors": [ 65 | {"name": "brtiller", "email": "brtiller@cisco.com"}, 66 | {"name": "qsnyder", "email": "qsnyder@cisco.com"} 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /labs/parsing-xml/2.md: -------------------------------------------------------------------------------- 1 | ## Step 2. Understand the returned XML data 2 | 3 | Before parsing the returned XML, take a moment to understand the structure and contents of the XML. It is difficult to see what an unformatted blob of text represents. So, the next step is to format the returned data so you can see its structure. 4 | 5 | ### Using Python's Minidom Library 6 | 7 | The large XML result that the script returns is a string. Thankfully, Python comes with a library that provides a Minimal DOM implementation called *Minidom*. Mindom can "pretty print" XML in a more human-readable format. 8 | 9 | 1. To use this functionality, modify `get-tenants-xml.py` and insert this import statement on the second line, which imports the Minidom library: 10 | ```python 11 | import xml.dom.minidom 12 | ``` 13 | 2. Replace the `print(tenants.text)` line with the following: 14 | ```python 15 | dom = xml.dom.minidom.parseString(tenants.text) 16 | xml = dom.toprettyxml() 17 | print(xml) 18 | ``` 19 | This snippet: 20 | - parses `response.text` as Document Object Model (DOM) 21 | - calls a method off of Minidom that returns a string as formatted XML 22 | - printing the formatted XML 23 | 3. Save the `get-tenants-xml.py` file. To download or review the current code, you can get it from GitHub here. 24 | 25 | 4. Run your `get-tenants-xml.py` file using Python: 26 | ``` 27 | python get-tenants-xml.py 28 | ``` 29 | > **Note**: Ensure that the Python version in use is greater than 3.4. If you get errors, verify the version of Python and double-check the code. 30 | 31 | The response is still a formidable amount of text, but you can see some of the structure of the XML document itself. 32 | 33 | ![](assets/images/xml-output-pretty-new.png) 34 | 35 | ---------- 36 | 37 | A key point to notice is the hierarchical structure of the returned data. Notably, the XML element with the tag name `fvTenant` has sub-objects which can have objects (depending on how we filter our query for data against the APIC). For this exercise, we are interested in the returned tenants (`fvTenant`), their names, and their current health scores. Because the `healthInst` object is a sub-object of the `fvTenant`, we have to move between different levels of the returned XML to get the information we want, in thie case the `name` inside of `fvTenant` and `cur` inside of `healthInst`. 38 | 39 | Structurally, the XML elements have the following order: 40 | 41 | <fvTenant>
42 |     <healthInst/>
43 | </fvTenant>
44 | 45 | It may not look interesting, but inside of each of the tags, we can see that multiple values are stored for different properties of that element. 46 | 47 | In the description shown, the elements tagged as `fvTenant` have sub-elements of `dn` and `modTS` and `name` (there are more, but they will likely be blank), which detail the "Distinguished Name" of the object, its modification time, and its "Relative Name (name)" A full `fvTenant` element from the data can look like this (you'll see the `healthInst` tag nested inside of the `fvTenant`): 48 | ``` 49 | 50 | 51 | 52 | ``` 53 | Where the tag is "fvTenant" and the attributes follow after the tag. You can also see the health tag and its subsequent attributes. 54 | 55 | Now, you have a better understanding of what the structure looks like. Next, you'll parse the data. 56 | 57 | **Next step:** 58 | 59 | Proceed to Step 3: Get XML elements in Python. 60 | -------------------------------------------------------------------------------- /labs/parsing-xml/3.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Get XML elements in Python 2 | 3 | ### Iterate through elements in XML 4 | 5 | Because you know the structure of the returned XML, the first approach could be to get the first element and sift through that elements children looking for the ones that match what you are looking for. This could be the tag name of the element, a particular value of an attribute, whether or not a child has sub-elements, or even the element's position in the hierarchy of the XML document. For example, you may want to get only the 3rd-level children from the root of the document. Another example might be that you want to get all of the child nodes with a particular attribute whose value is `100`. 6 | 7 | To understand how this might work, modify your script to include some code that loops through the children looking for the information you want to collect, keeping in mind that we'll need to loop through two tiers of tags and store the variables accordingly. Here, find the `fvTenant` elements, output the name of the tenant (`name`), then find the `healthInst` element within each `fvTenant` and print the current health score (`cur`). 8 | 9 | 1. In `get-tenats.py`, insert the following after the `print(xml)` line. Keep the spaces because Python is sensitive to indentation. 10 | ```python 11 | tenant_objects = dom.firstChild 12 | if tenant_objects.hasChildNodes: 13 | tenant_element = tenant_objects.firstChild 14 | while tenant_element is not None: 15 | if tenant_element.tagName == 'fvTenant': 16 | health_element = tenant_element.firstChild 17 | output = "Tenant: " + tenant_element.getAttribute('name') + '\t Health Score: ' + health_element.getAttribute('cur') 18 | print(output.expandtabs(40)) 19 | tenant_element = tenant_element.nextSibling 20 | ``` 21 | This snippet: 22 | - Gets the first element from the Document Object Model (DOM). 23 | - Determines if the first element has children. 24 | - If the first element has children, it begins iterating through them. 25 | - As it iterates through the first elements children, it stores the second element's children as variables for access of information 26 | - For each child, if its tag name is `fvTenant`, print out its `name` and current health score (stored in the `cur` attribute of the `healthInst` tag for a given `fvTenant`). 27 | - The `expandtabs(40)` at the end of `print` statement allows for an easy view of returned data, as the name of each tenant could be of diffent length. If the columns are not aligned, increase the value to something larger (50 or so). 28 | 29 | 1. Save the `get-tenants-xml.py` file. To download or review the current code, you can get it from GitHub here. 30 | 31 | 2. Enter the following command to run your file. 32 | ``` 33 | python get-tenants-xml.py 34 | ``` 35 | > **Note**: Ensure that the Python version in use is greater than 3.4. If you get errors, verify the version of Python and double-check the code. 36 | 37 | When you run the Python script, you should get an output at the end of the data values extracted from the XML returned for each tenant. 38 | 39 | ![](assets/images/xml-output-parse-001-new.png) 40 | 41 | ---------- 42 | 43 | Using Python and Minidom, you have extracted specific information from ACI using the `fvTenant` and nested `healthInst` elements and retrived values defined by the element's attributes. However, what if you want to quickly get the `fvTenant` name and you don't care about anything else in the document? Next, look at how you could parse that out quickly. 44 | 45 | **Next step:** 46 | 47 | Proceed to Step 4: Get XML elements in Python. 48 | -------------------------------------------------------------------------------- /labs/parsing-xml/4.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Get XML elements in Python 2 | 3 | ### Retrieve Elements by Tag Name 4 | 5 | Rather than manually evaluate each child in a series of nodes, Minidom offers functionality to extract a collection of elements by their tag name. You can use the `getElementsByTagName()` method to return an array of elements. 6 | 7 | 1. In `get-tenants-xml.py`, replace the code you inserted in Step 3 (everything after the `print(xml)` line) with the following code. (Be careful to maintain the indentation.) 8 | 9 | ```python 10 | tenant_list = dom.getElementsByTagName('fvTenant') 11 | for tenants in tenant_list: 12 | tenant_name = tenants.getAttribute('name') 13 | tenant_dn = tenants.getAttribute('dn') 14 | health_score = tenants.firstChild.getAttribute('cur') 15 | output = "Tenant: " + tenant_name + "\t Health Score: " + health_score + "\n DN: " + tenant_dn 16 | print(output.expandtabs(40)) 17 | ``` 18 | 19 | This snippet: 20 | - Gets elements whose tag is `fvTenant`. 21 | - Iterates through those elements. 22 | - Stores the healthscore by looking at the `firstChild` of the tenant, which is `healthInst`, then gets the `cur` health score attribute 23 | - For each child, prints out its `name`, `cur` health score, and the tenant `dn` with appropriate formatting 24 | 25 | 1. Save the `get-tenants-xml.py` file. To download or review the current code, you can get it from GitHub here. 26 | 27 | 2. Enter the following command to run your file. 28 | ``` 29 | python get-tenants-xml.py 30 | ``` 31 | > **Note**: Ensure that the Python version in use is greater than 3.4. If you get errors, verify the version of Python and double-check the code. 32 | 33 | When you run the Python script, it should return output that is similar to what you saw before, with the addition of the tenant distinguished name below the tenant name. 34 | 35 | ![](assets/images/xml-output-parse-002-new.png) 36 | 37 | ---------- 38 | 39 | Using Python and Minidom, you have extracted and displayed specific information from ACI. 40 | 41 | Next, in the last step, see which resources you can use to learn more about parsing XML with Python. 42 | 43 | **Next step:**: 44 | 45 | Proceed to Step 5: Find additional resources. 46 | -------------------------------------------------------------------------------- /labs/parsing-xml/5.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Find additional resources 2 | 3 | The following sections provide additional resources for learning about the topics that were covered by this lab. 4 | 5 | ### Extensible Markup Language (XML) 6 | 7 | If some of the XML terminology is still confusing, a good next step would be to visit: [https://www.w3schools.com/xml/](https://www.w3schools.com/xml/ "W3Schools XML"). 8 | 9 | To learn more about XML, you can also review the XML standard at [https://www.w3.org/TR/REC-xml/](https://www.w3.org/TR/REC-xml/ "Extensible Markup Language (XML) 1.0 (Fifth Edition)"). 10 | 11 | ### Python 12 | 13 | Python is a powerful tool. To learn more, use the [https://docs.python.org/3.4/tutorial/](https://docs.python.org/3.4/tutorial/ "Python Tutorial"). 14 | 15 | **Python XML Libraries**
16 | There are several libraries and approaches for parsing XML content. The Minidom library you used in this lab is one tool. Another popular Python library is [ElementTree](https://docs.python.org/3.4/library/xml.etree.elementtree.html "ElementTree XML API"). 17 | 18 | You can find a good summary of the major standard and external libraries at [https://wiki.python.org/moin/PythonXml](https://wiki.python.org/moin/PythonXml "PythonXML"). 19 | 20 | Additionally, for an overview of the Python modules for Stream and Document Object Model parsing, see [https://docs.python.org/3.4/whatsnew/2.0.html#xml-modules](https://docs.python.org/3.4/whatsnew/2.0.html#xml-modules "XML-Modules"). 21 | 22 | ### Application Centric Infrastructure 23 | 24 | **Product Information**
25 | [https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html](https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html "Application Centric Infrastructure (ACI) Product Site") 26 | 27 | **Developer Resources**
28 | [https://developer.cisco.com/site/aci/](https://developer.cisco.com/site/aci/ "Application Centric Infrastructure Developer Site") 29 | 30 | **Application Centric Infrastructure (ACI) API Documentation**
31 | [https://developer.cisco.com/docs/aci/](https://developer.cisco.com/docs/aci/ "ACI API Documentation") 32 | -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-new.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-parse-001-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-parse-001-new.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-parse-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-parse-001.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-parse-002-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-parse-002-new.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-parse-002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-parse-002.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-pretty-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-pretty-new.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output-pretty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output-pretty.png -------------------------------------------------------------------------------- /labs/parsing-xml/assets/images/xml-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/coding-series-learning-labs/720a10cf7343d848f76548ee85efcd8a3e821421/labs/parsing-xml/assets/images/xml-output.png -------------------------------------------------------------------------------- /labs/parsing-xml/byod.html: -------------------------------------------------------------------------------- 1 |
2 | For this lab we will be using Python 3.4+. To verify your version run the following command in a terminal window: 3 | 4 | python --version 5 | 6 |
-------------------------------------------------------------------------------- /labs/parsing-xml/get-ap-xml.py: -------------------------------------------------------------------------------- 1 | from urllib.request import Request, urlopen 2 | import xml.dom.minidom 3 | 4 | # Let's construct a request with headers 5 | req = Request('https://msesandbox.cisco.com/api/contextaware/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone') 6 | req.add_header('Authorization', 'Basic bGVhcm5pbmc6bGVhcm5pbmc==') 7 | 8 | # Actually open the request 9 | response = urlopen(req) 10 | 11 | # Read the response into a String 12 | responseString = response.read().decode("utf-8") 13 | 14 | # Parse the string into an XML Document Object Model 15 | dom = xml.dom.minidom.parseString(responseString) 16 | xml = dom.toprettyxml() 17 | 18 | # Print out the formatted response string 19 | print(xml) 20 | 21 | # Get the first object of the document 'Floor' 22 | floor_element = dom.firstChild 23 | if floor_element.hasChildNodes : 24 | child = floor_element.firstChild 25 | while child is not None: 26 | if child.tagName == 'AccessPoint' : 27 | output = child.tagName + ": " + child.getAttribute('name') + '\t eth: ' + child.getAttribute('ethMacAddress') 28 | print(output) 29 | child = child.nextSibling 30 | 31 | # Load the XML into a collection of Access Point information 32 | access_points = dom.getElementsByTagName('AccessPoint') 33 | for access_point in access_points: 34 | ap_name = access_point.getAttribute('name') 35 | ap_eth_addr = access_point.getAttribute('ethMacAddress') 36 | ap_ip_addr = access_point.getAttribute('ipAddress') 37 | print(access_point.tagName + ": " + ap_name + '\t eth: ' + ap_eth_addr + '\t ip: ' + ap_ip_addr) 38 | 39 | # Let's close the response we opened 40 | response.close() 41 | -------------------------------------------------------------------------------- /labs/parsing-xml/get-tenants-xml.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) 35 | 36 | # Now lets use DOM to clean up the XML from its completely raw format 37 | dom = xml.dom.minidom.parseString(tenants.text) 38 | xml = dom.toprettyxml() 39 | print(xml) 40 | 41 | # 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 42 | #tenant_objects = dom.firstChild 43 | #if tenant_objects.hasChildNodes: 44 | # tenant_element = tenant_objects.firstChild 45 | # while tenant_element is not None: 46 | # if tenant_element.tagName == 'fvTenant': 47 | # health_element = tenant_element.firstChild 48 | # output = "Tenant: " + tenant_element.getAttribute('name') + '\t Health Score: ' + health_element.getAttribute('cur') 49 | # print(output.expandtabs(40)) 50 | # tenant_element = tenant_element.nextSibling 51 | 52 | # Now we'll do something similar, but done using a direct access method of the data, rather than interation and loops 53 | tenant_list = dom.getElementsByTagName('fvTenant') 54 | for tenants in tenant_list: 55 | tenant_name = tenants.getAttribute('name') 56 | tenant_dn = tenants.getAttribute('dn') 57 | health_score = tenants.firstChild.getAttribute('cur') 58 | output = "Tenant: " + tenant_name + "\t Health Score: " + health_score + "\n DN: " + tenant_dn 59 | print(output.expandtabs(40)) -------------------------------------------------------------------------------- /labs/parsing-xml/parsing-xml.json: -------------------------------------------------------------------------------- 1 | { 2 | "labId": "parsing-xml", 3 | "title": "Parsing XML", 4 | "slug": "Learn the basics of how to use parse XML results using Python.", 5 | "byod": true, 6 | "time": "20", 7 | "files": [ 8 | {"title": "Step 1: Make an HTTP REST call with Python", 9 | "file": "1.md"}, 10 | {"title": "Step 2. Understand the returned XML data", 11 | "file": "2.md"}, 12 | {"title": "Step 3: Get XML elements in Python", 13 | "file": "3.md"}, 14 | {"title": "Step 4: Get XML elements in Python", 15 | "file": "4.md"}, 16 | {"title": "Step 5: Find additional resources", 17 | "file": "5.md"} 18 | ], 19 | "tags": [ 20 | {"title": "Cloud"}, 21 | {"title": "Coding"}, 22 | {"title": "Parsing"}, 23 | {"title": "XML"}, 24 | {"title": "Python"}, 25 | {"title": "ACI"}, 26 | {"title": "Sandbox" } 27 | ], 28 | "related": [ 29 | { 30 | "labId": "rest-basics", 31 | "title": "REST API Basics" 32 | }, 33 | { 34 | "labId": "rest-python", 35 | "title": "Calling REST APIs from Python" 36 | }, 37 | { 38 | "labId": "parsing-xml", 39 | "title": "Parsing XML with Python" 40 | }, 41 | { 42 | "labId": "parsing-json", 43 | "title": "Parsing JSON with Python" 44 | }, 45 | { 46 | "labId": "getting-input", 47 | "title": "Getting input from a user using Python" 48 | }, 49 | { 50 | "labId": "reading-a-file", 51 | "title": "Reading from a file using Python" 52 | }, 53 | { 54 | "labId": "writing-file", 55 | "title": "Writing data to a file using Python" 56 | }, 57 | { 58 | "labId": "logging", 59 | "title": "How to use the logging module in Python" 60 | }, 61 | { 62 | "labId": "putting-it-together", 63 | "title": "Python - Putting it all together" 64 | } 65 | ], 66 | "authors": [ 67 | {"name": "brtiller", "email": "brtiller@cisco.com"}, 68 | {"name": "qsnyder", "email": "qsnyder@cisco.com"} 69 | ] 70 | } 71 | --------------------------------------------------------------------------------