The Go Client for eAPI provides a native Go implementation for programming Arista EOS network devices using Golang. The Go client provides the ability to build native applications in Go that can communicate with EOS remotely over a HTTP/S transport (off-box). It uses a standard INI-style configuration file to specifiy one or more connection profiles.
The goeapi implemenation also provides an API layer for building native Go objects that allow for configuration and state extraction of EOS nodes. The API layer provides a consistent implementation for working with EOS configuration resources. The implementation of the API layer is highly extensible and can be used as a foundation for building custom data models.
The libray is freely provided to the open source community for building robust applications using Arista EOS eAPI. Support is provided as best effort through Github iusses.
First, it is assumed you have and are working in a standard Go workspace, as described in http://golang.org/doc/code.html, with proper GOPATH set. Go 1.5+ is what's recommended for using goeapi. To download and install goeapi:
$ go get github.com/aristanetworks/goeapi
After setting up Go and installing goeapi, any required build tools can be installed by bootstrapping your environment via:
$ make bootstrap
$ go get -u github.com/aristanetworks/goeapi
The following steps need to be followed to assure successful configuration of goeapi.
EOS Command API must be enabled
To enable EOS Command API from configuration mode, configure proper protocol under management api, and then verify:
Switch# configure terminal
Switch(config)# management api http-commands
Switch(config-mgmt-api-http-cmds)# protocol ?
http Configure HTTP server options
https Configure HTTPS server options
unix-socket Configure Unix Domain Socket
Switch(config-mgmt-api-http-cmds)# protocol http
Switch(config-mgmt-api-http-cmds)# end
Switch# show management api http-commands
Enabled: Yes
HTTPS server: running, set to use port 443
HTTP server: running, set to use port 80
Local HTTP server: shutdown, no authentication, set to use port 8080
Unix Socket server: shutdown, no authentication
...
Create configuration file with proper node properties. (See eapi.conf file examples below)
Note: The default search path for the conf file is ~/.eapi.conf
followed by /mnt/flash/eapi.conf
. This can be overridden by setting
EAPI_CONF=<path file conf file>
in your environment.
Below is an example of an eAPI conf file. The conf file can contain more than one node. Each node section must be prefaced by connection:\<name> where \<name> is the name of the connection.
The following configuration options are available for defining node entries:
Note: See the EOS User Manual found at arista.com for more details on configuring eAPI values.
Once goeapi has been installed and your .eapi.config file is setup correctly, you are now ready to try it out. Here is a working example of .eapi.config file and go program:
$ cat ~/.eapi.config
[connection:arista1]
host=arista1
username=admin
password=root
enablepwd=passwd
transport=https
$ cat example1.go
package main
import (
"fmt"
"github.com/aristanetworks/goeapi"
"github.com/aristanetworks/goeapi/module"
)
func main() {
// connect to our device
node, err := goeapi.ConnectTo("Arista1")
if err != nil {
panic(err)
}
// get the running config and print it
conf := node.RunningConfig()
fmt.Printf("Running Config:\n%s\n", conf)
// get api system module
sys := module.System(node)
// change the host name to "Ladie"
if ok := sys.SetHostname("Ladie"); !ok {
fmt.Printf("SetHostname Failed\n")
}
// get system info
sysInfo := sys.Get()
fmt.Printf("\nSysinfo: %#v\n", sysInfo.HostName())
}
goeapi provides a way for users to directly couple a command with a predefined response. The underlying api will issue the command and the response stored in the defined type. For example, lets say the configured vlan ports are needed for some form of processing. If we know the JSON response for the command composed like the following: (from Arista Command API Explorer):
{
"jsonrpc": "2.0",
"result": [
{
"sourceDetail": "",
"vlans": {
"2": {
"status": "active",
"name": "VLAN0002",
"interfaces": {
"Port-Channel10": {
"privatePromoted": false
},
"Ethernet2": {
"privatePromoted": false
},
"Ethernet1": {
"privatePromoted": false
},
"Port-Channel5": {
"privatePromoted": false
}
},
"dynamic": false
},
}
}
],
"id": "CapiExplorer-123"
}
We can then build our Go structures based on the response format and couple our show command with the type:
type MyShowVlan struct {
SourceDetail string `json:"sourceDetail"`
Vlans map[string]Vlan `json:"vlans"`
}
type Vlan struct {
Status string `json:"status"`
Name string `json:"name"`
Interfaces map[string]Interface `json:"interfaces"`
Dynamic bool `json:"dynamic"`
}
type Interface struct {
Annotation string `json:"annotation"`
PrivatePromoted bool `json:"privatePromoted"`
}
func (s *MyShowVlan) GetCmd() string {
return "show vlan configured-ports"
}
Since the command show vlan configured-ports
is coupled with the response structure, the underlying api knows to issue the command and the response needs to be filled in. The resulting code looks like:
package main
import (
"fmt"
"github.com/aristanetworks/goeapi"
)
type MyShowVlan struct {
SourceDetail string `json:"sourceDetail"`
Vlans map[string]Vlan `json:"vlans"`
}
type Vlan struct {
Status string `json:"status"`
Name string `json:"name"`
Interfaces map[string]Interface `json:"interfaces"`
Dynamic bool `json:"dynamic"`
}
type Interface struct {
Annotation string `json:"annotation"`
PrivatePromoted bool `json:"privatePromoted"`
}
func (s *MyShowVlan) GetCmd() string {
return "show vlan configured-ports"
}
func main() {
node, err := goeapi.ConnectTo("dut")
if err != nil {
panic(err)
}
sv := &MyShowVlan{}
handle, _ := node.GetHandle("json")
handle.AddCommand(sv)
if err := handle.Call(); err != nil {
panic(err)
}
for k, v := range sv.Vlans {
fmt.Printf("Vlan:%s\n", k)
fmt.Printf(" Name : %s\n", v.Name)
fmt.Printf(" Status: %s\n", v.Status)
}
}
Also, if several commands/responses have been defined, goeapi supports command stacking to batch issue all at once:
...
handle, _ := node.GetHandle("json")
handle.AddCommand(showVersion)
handle.AddCommand(showVlan)
handle.AddCommand(showHostname)
handle.AddCommand(showIp)
if err := handle.Call(); err != nil {
panic(err)
}
fmt.Printf("Version : %s\n", showVersion.Version)
fnt.Printf("Hostname : %s\n", showHostname.Hostname)
...
There are several go example's using goeapi (as well as example .eapi.config file) provided in the examples directory.
Documentation can be generated locally in plain text via:
$ godoc github.com/aristanetworks/goeapi
Or you can run the local godoc server and view the html version of the documentation by pointing your browser at http://localhost:6060
$ make doc
or
$ godoc -http=:6060 -index
The goeapi library provides various tests. To run System specific tests, you will need to
update the dut.conf
file (found in testutils/fixtures) to include the device level specifics
for your setup. The switch used for testing should have at least interfaces Ethernet1-7.
$ make systest
or
$ go test ./... -run SystemTest$
$ make unittest
or
$ go test ./... -run UnitTest$
Verbose mode can be specified as a flag to provide additional information:
$ make GOTEST_FLAGS=-v test
Note: Test cases for XXX.go files live in respective XXX_test.go files and have the following function signature:
TestXXX_UnitTest(t *testing.T){...
TestXXX_SystemTest(t *testing.T){...
Any tests written must conform to this standard.
Contributing pull requests are gladly welcomed for this repository. Please note that all contributions that modify the library behavior require corresponding test cases otherwise the pull request will be rejected.
Copyright (c) 2015-2016, Arista Networks Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Arista Networks nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.