Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Network Automation with Go

You're reading from   Network Automation with Go Learn how to automate network operations and build applications using the Go programming language

Arrow left icon
Product type Paperback
Published in Jan 2023
Publisher Packt
ISBN-13 9781800560925
Length 442 pages
Edition 1st Edition
Languages
Arrow right icon
Authors (2):
Arrow left icon
Michael Kashin Michael Kashin
Author Profile Icon Michael Kashin
Michael Kashin
Nicolas Leiva Nicolas Leiva
Author Profile Icon Nicolas Leiva
Nicolas Leiva
Arrow right icon
View More author details
Toc

Table of Contents (18) Chapters Close

Preface 1. Part 1: The Go Programming Language
2. Chapter 1: Introduction FREE CHAPTER 3. Chapter 2: Go Basics 4. Chapter 3: Getting Started with Go 5. Chapter 4: Networking (TCP/IP) with Go 6. Part 2: Common Tools and Frameworks
7. Chapter 5: Network Automation 8. Chapter 6: Configuration Management 9. Chapter 7: Automation Frameworks 10. Part 3: Interacting with APIs
11. Chapter 8: Network APIs 12. Chapter 9: OpenConfig 13. Chapter 10: Network Monitoring 14. Chapter 11: Expert Insights 15. Chapter 12: Appendix : Building a Testing Environment 16. Index 17. Other Books You May Enjoy

State validation

In the last three sections of this chapter, we pushed device configs without verifying that the configuration changes had the desired effect. This is because we need all devices configured before we can validate the resulting converged operational state. Now, with all the code examples from the OpenAPI, JSON-RPC, and RESTCONF sections executed against the lab topology, we can verify whether we achieved our configuration intent—establish end-to-end reachability between loopback IP addresses of all three devices.

In this section, we’ll use the same protocols and modeling language we used earlier in this chapter to validate that each lab device can see the loopback IP address of the other two lab devices in its Forwarding Information Base (FIB) table. You can find the complete code for this section in the ch08/state directory (refer to the Further reading section) of this book’s GitHub repository. Next, we’ll examine a single example of how you can do this with Arista’s cEOS (ceos) lab device.

Operational state modeling

One thing we need to be mindful of when talking about the operational state of a network element is the difference between the applied and the derived state, as described by the YANG operational state IETF draft (refer to the Further reading section). The former refers to the currently active device configuration and should reflect what an operator has already applied. The latter is a set of read-only values that result from the device’s internal operations, such as CPU or memory utilization, and interaction with external elements, such as packet counters or BGP neighbor state. Although we aren’t explicitly mentioning it when we’re talking about an operational state, assume we’re referring to the derived state unless we state otherwise.

Historically, there’ve been different ways to model the device’s operational state in YANG:

  • You could either enclose everything in a top-level container or read from a separate state datastore, completely distinct from the config container/datastore we use for configuration management.
  • Another way is to create a separate state container for every YANG sub-tree alongside the config container. This is what the YANG operational state IETF draft (refer to the Further reading section) describes.

Depending on which approach you use, you may need to adjust how you construct your RPC request. For example, the srl device needs an explicit reference to the state datastore. What we show in the next code example is the alternative approach, where you retrieve a part of the YANG sub-tree and extract the relevant state information from it.

It’s worth noting that OpenAPI is less strict about the structure and composition of its models and the state may come from a different part of a tree or require a specific query parameter to reference the operational datastore, depending on the implementation.

Operational state processing

Configuration management workflows typically involve the processing of some input data to generate a device-specific configuration. This is a common workflow that we often use to show the capabilities of an API. But there is an equally important workflow that involves operators retrieving state data from a network device, which they process and verify. In that case, the information flows in the opposite direction—from a network device to a client application.

At the beginning of this chapter, we discussed the configuration management workflow, so now we want to give a high-level overview of the state retrieval workflow:

  1. We start by querying a remote API endpoint, represented by a set of URL and HTTP query parameters.
  2. We receive an HTTP response, which has a binary payload attached to it.
  3. We unmarshal this payload into a Go struct that follows the device’s data model.
  4. Inside this struct, we look at the relevant parts of the state we can extract and evaluate.

The following code snippet from the ch08/state program (refer to the Further reading section) is a concrete example of this workflow. The program structure follows the same pattern we described in the State validation section of Chapter 6, Configuration Management. Hence, in this chapter, we’ll only zoom in on the most relevant part—the GetRoutes function, which connects to the ceos device and retrieves the content of its routing table.

It starts by building an HTTP request with the device-specific login information:

func (r CEOS) GetRoutes(wg *sync.WaitGroup) {
  client := resty.NewWithClient(&http.Client{
    Transport: &http.Transport{
      TLSClientConfig: &tls.Config{
        InsecureSkipVerify: true},
    },
  })
  client.SetBaseURL("https://" + r.Hostname + ":6020")
  client.SetBasicAuth(r.Username, r.Password)
  resp, err := client.R().
    SetHeader("Accept", "application/yang-data+json").
    Get(fmt.Sprintf("/restconf/data/network-instances/network-instance=%s/afts", "default"))
  /* ... <continues next > ... */
}

The Abstract Forwarding Table (AFT) in the code example is an OpenConfig representation of the FIB (routing) table and the GET API call retrieves a JSON representation of the default Virtual Routing and Forwarding (VRF) routing table.

Next, we create an instance of the Go struct corresponding to the part of the YANG tree we queried and pass it to the Unmarshal function for deserialization. The resulting Go struct now has one Ipv4Entry value for each entry in the default FIB and we store that list of prefixes in the out slice:

import eosAPI "restconf/pkg/eos"
func (r CEOS) GetRoutes(wg *sync.WaitGroup) {
  /* ... <continues from before > ... */
  response := &eosAPI.NetworkInstance_Afts{}
  err := eosAPI.Unmarshal(resp.Body(), response)
  // process error
  out := []string{}
  for key := range response.Ipv4Entry {
    out = append(out, key)
  }
  /* ... <omitted for brevity > ... */
  go checkRoutes(r.Hostname, out, expectedRoutes, wg)
}

In this example, we import the eos package (restconf/pkg/eos) we auto-generated in the RESTCONF section of this chapter, which lives outside the root directory of this program. To do this, we add the replace restconf => ../restconf/ instruction to this program’s go.mod file (ch08/state/go.mod; refer to the Further reading section).

For the remaining lab devices, we follow a similar state retrieval workflow. The only difference is in the YANG paths and the model-based Go structs we use for deserialization. You can find the full program code in the ch08/state directory (refer to the Further reading section) of this book’s GitHub repository.

In this chapter, we have covered network APIs based on HTTP version 1.1 that use common encoding formats, such as JSON. Although HTTP is still very popular and this is unlikely to change soon, it has its own limitations that may manifest themselves in large-scale deployments. HTTP 1.1 is a text-based protocol, which means it’s not efficient on the wire and its client-server origins make it difficult to adapt it for bi-directional streaming. The next version of this protocol, HTTP/2, overcomes these shortcomings. HTTP/2 is the transport protocol of the gRPC framework, which is what we’ll examine in the next section.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image