I'm a huge fan of the Go programming language, and it has quickly become my "go to" for pretty much everything related to scripting/programming. I'm also a big fan of the Junos network operating system, from Juniper Networks.

There are a lot of Python, Ruby modules out there that are extremely helpful when automation Junos devices. I decided to write on in Go to try to accomplish the same things. It's very much a work in progress still, but is quite functional at this time.

So let's get started with a basic tutorial of how to use it!

The go-junos Module

This article assumes that you have basic knowledge of Go and writing Go programs.

The go-junos module is one I created to interact with and automate Junos devices. Please visit the GoDoc page for complete documentation on it.

If you don't already have Go installed, download it from their website. I highly recommend taking a look at the following resources as well, to better familiarize yourself with Go:

For the start of our program, we'll need to import the go-junos module. We can easily do this within our script by having the following line under our imports section:

"github.com/scottdware/go-junos"

Next, we will need to connect to our Junos device:

jnpr, err := junos.NewSession(host, user, password) if err != nil { fmt.Println(err) } defer jnpr.Close()

Once we have made the connection, let's take a look at what we can do. Say you want to view only the routing-instances section of the configuration, and in text format:

routing, _ := jnpr.GetConfig("text", "routing-instances") fmt.Println(routing)

Your output will then be similar to this:

## Last changed: 2015-01-01 13:00:00 EST routing-instances { srx-vr { instance-type virtual-router; interface lo0.0; interface reth0.500; interface reth0.525; interface st0.1; routing-options { static { route 192.168.3.5/32 { next-hop 10.2.2.2; install; passive; } } autonomous-system 88881; } protocols { bgp { group vpn { type external; peer-as 99992; local-as 88881; neighbor 10.1.1.1 { import VPN-Import-Policy; export VPN-Export-Policy; } } } } } }

If you use the keyword "full" instead of a configuration section, you will get the entire config back. Output format can be either "text" or "xml."

Let's say you want to compare your current (active) configuration to a given rollback one, then we can do that by using the ConfigDiff() function:

diff, _ := jnpr.ConfigDiff(5) fmt.Println(diff)

This will compare to the rollback 5 configuration, and the output will be just like it is if you were issuing the command on the CLI:

[edit system] + name-server { + 192.168.1.2; + } [edit security address-book global] address company.com { ... } + address pc1 192.168.20.2/32; + address pc2 192.168.20.3/32;

Now that we have compared a couple of configurations, let's delete our old "rescue" config and create a new one based off of the current configuration:

jnpr.Rescue("delete") jnpr.Rescue("save")

Ok, now that we have our rescue configuration set, let's rollback our configuration to a different one:

err := jnpr.RollbackConfig(5) if err != nil { fmt.Println(err) }

We can also rollback to our rescue configuration that we created earlier:

err := jnpr.RollbackConfig("rescue") if err != nil { fmt.Println(err) }

Now that we've worked with rolling back our configuration, let's configure our Junos device with a config file we have saved.

In this example, we'll have our config files commands in set format. You can set it to text or xml as well.

err := jnpr.LoadConfig("C:/Configs/juniper.txt", "set", true) if err != nil { fmt.Println(err) }

If you don't have (or want) your configuration commands in a file, and just want to run them from the script...then we can accomplish that as well:

config := []string{ "set interfaces ge-0/0/10 vlan-tagging", "set interfaces ge-0/0/10.1138 description \"Remember to escape double-quotes if you use this format!\"", "set interfaces ge-0/0/10.1138 vlan-id 1138 family inet address 192.168.1.1/24", "set routing-instances srx-vr interface ge-0/0/10.1138", "set security zones security-zone trust interface ge-0/0/10.1138", } // Or config := ` set interfaces ge-0/0/10 vlan-tagging set interfaces ge-0/0/10.1138 description "This style works better as you don't have to escape double-quotes" set interfaces ge-0/0/10.1138 vlan-id 1138 family inet address 192.168.1.1/24 set routing-instances srx-vr interface ge-0/0/10.1138 set security zones security-zone trust interface ge-0/0/10.1138 ` err := jnpr.Config(config, "set", true) if err != nil { fmt.Println(err) }

The "true" option tells the function that we want to commit our configuration after it is loaded. If you set it to "false," then you will have to issue a commit afterwards, like so:

jnpr.Commit()

There are a few different commit options we have. All of the following will work:

// Normal commit jnpr.Commit() // Check our syntax/config jnpr.CommitCheck() // Commit at a specific time jnpr.CommitAt("23:30:00") // Commit confirm after 5 minutes jnpr.CommitConfirm(5)

You can also load a configuration from an FTP or HTTP server:

err := jnpr.Config("ftp://<username>:<password>@hostname/pathname/file-name", "set", true) if err != nil { fmt.Println(err) }

This is very basic usage, but I hope you can see how helpful this module might be when you are coding in Go, and wanting to interact with Junos devices.

I will be continually adding to this module, and if you see something that you might want, just drop me a line or head over to my Github repo and open an issue/pull request.