-
Notifications
You must be signed in to change notification settings - Fork 25
JTAF Build Steps
The best way to get familiar with JTAF is to build a provider. Let's go!
Navigate to your /var/tmp
directory and create the jtaf_demo
directory. This is your working directory for running a provider build.
Next, grab the JTAF project, which is written in Go.
go get github.com/Juniper/junos-terraform
Navigate to the junos-terraform directory and build both the cmd/processYang
and cmd/processProviders
binary.
Next, copy the contents of the samples/tf_module_template
directory to your working directory.
# Inside the /junos-terrform directory
cp -rf Samples/tf_module_template /var/tmp/jtaf_demo
One of the first steps is to process the YANG files and create YIN and .txt representations of the YANG contents. For this example, the YANG files are ready to go and you don't have to worry about a thing.
The processing is done via pyang
and we have a requirement to install a Python venv and install Pyang.
Navigate to the processYang
directory.
python -m venv ./venv
source ./venv/bin/activate
pip install pyang
go build
./processYang -config /var/tmp/jtaf_demo/jtaf_config.toml
At this point, the first part of JTAF will kick in and process the YANG files. This can take some time. Each YANG file is being converted into the YIN type (XML) and there is also a .txt file being generated which contains the XPaths, which is effectively an index into each YIN file.
Next, navigate to the cmd/processProviders
directory and execute that program. This shouldn't take too long.
go build
./processProviders -config /var/tmp/jtaf_demo/jtaf_config.toml
If all goes well, you now all have the .go
files in the terraform_providers
directory within your working directory.
Navigate to the terraform_providers
directory. You can now build the provider with:
go mod tidy
go build
Enough data is stored in the go.mod
file to instruct the Go compiler what to do.
Next, move the provider to the default Terraform provider directory with the correct version directory. In this example case, the YANG models are for a 20.3xx vSRX and the specifics for the minor numbers, mirror the version vSRX.
mkdir -p ~/.terraform.d/plugins/juniper/providers/junos-vsrx/20.32.0101/darwin_amd64
mv terraform-provider-junos-vsrx ~/.terraform.d/plugins/juniper/providers/junos-vsrx/20.32.0101/darwin_amd64
It might be a good idea to export an environment variable as a shortcut for this directory!
You're now in a position to run Terraform through it's paces.
Remember, whatever you call the provider in the .toml
config file, is what you'll need to refer to it as in any Terraform module.
Next, let's interact with Terraform with our fancy new module. Navigate to the /module
directory within your working directory. Now, there are some important things you will need to adjust inside the file main.tf
. See the provider
section? By default it will look like this:
provider "junos-vsrx" {
host = "localhost"
port = 8300
username = "root"
password = "juniper123"
sshkey = ""
}
Make sure this data is accurate for the host, port, user, password (or sshkey).
Before we dive in with Terraform, here are some mental notes as to how this example is structured. Here is the entire file.
terraform {
required_providers {
junos-vsrx = {
source = "juniper/providers/junos-vsrx"
version = "20.32.0101"
}
}
}
provider "junos-vsrx" {
host = "localhost"
port = 8300
username = "root"
password = "juniper123"
sshkey = ""
}
module "vsrx_1" {
source = "./vsrx_1"
providers = {junos-vsrx = junos-vsrx}
depends_on = [junos-vsrx_destroycommit.commit-main]
}
resource "junos-vsrx_commit" "commit-main" {
resource_name = "commit"
depends_on = [module.vsrx_1]
}
resource "junos-vsrx_destroycommit" "commit-main" {
resource_name = "destroycommit"
}
Notice that the provider we have just created is now identified in. Secondly we have the provider block with the device details. Then we get to the interesting bits.
module
The module vsrx_1
contains our desired declarative intent (the resources!). The module is a directory with another main.tf
file. Within that second level main.tf
is a list of resources we want Terraform to add to our vSRX. The provider information is passed down (so that the same credentials etc can be used). The most interesting piece however is the depends_on
key. Notice that the module depends on a destroycommit
resource. Also notice that the next resource down in the file is a commit, that depends on the module.
What happens from Terraform's perspective on create is this:
- Terraform applies first a
destroycommit
resource (which does nothing when created). - Terraform applies the resources in the module.
- Terraform after the module resources have been created, applies the top level commit (which is an actual commit).
Because the commits are essentially NETCONF payloads and not data, nothing is stored in local state for commits, so if you look at the source code, you'll notice that the junos-vsrx_commit
resource has the create
function completed but nothing else. If you look at the junos-vsrx_destroycommit
function, you'll notice that the create
function is empty, yet the delete
function has the commit logic.
When Terraform applies destroy
this is what happens:
- Terraform deletes the
commit
(nothing happens, there is no local state and no remote state). - Terraform deletes each resource in the module (resources are deleted one by one without commits).
- Terraform deletes the
destroycommit
resource, in which a commit is issued against Junos.
terraform init
terraform plan
Notice in the output that Terraform gives you a plan of what it's going to do. You an output this as an SVG too if you want a graphic.
Next, let's run the apply. Because this is a greenfield site, let's auto-approve it.
terraform apply -auto-approve
From here, you can check the configuration groups on the vSRX that have been configured. They should all be there. You can also run another plan to make sure Terraform's local declarative desired state reflects the remote (vSRX) based state.
terraform plan
You can also delete a resource inside the module or change one, but if you do this, ensure to run a taint
command on the commit object.
terraform taint junos-vsrx_commit.commit-main
You need this because Terraform thinks the commit object hasn't changed (and it hasn't). In order to push a commit after the update (Junos config group deletion and creation), the taint command tells Junos that the resource needs to be re-created.
terraform apply -auto-approve
Whatever you've adjusted for, will be applied. You can run plan
if you've done a taint, but on the apply
phase, Terraform will pick up on it anyway.
You can now destroy the config entirely on the vSRX with:
terraform destroy -auto-approve
Now, more coolness. When Terraform does a create, it automatically does a read on the configured remote state, which means we do not have to run tests through tools like jSnappy. Parts of your Terraform configuration can be your 'golden configuration' and to do a remote check, you can run a terraform plan
on the resources that form your golden config. Nice eh?
This was tested with Terraform version 0.15.5 on darwin_amd64 (OSX). If you're running on Linux, ensure to change the darwin to linux on the examples above.
If there are any issues with this write-up, please raise an issue on this repository with enough data for us to re-create the scenario and find a fix.