Juniper Apstra Terraform Provider — Functions
Juniper Apstra Terraform Provider — Functions
The Terraform language includes a number of built-in functions that you can call from within expressions to transform and combine values. The general syntax for function calls is a function name followed by comma-separated arguments in parentheses.
The Terraform language does not support user-defined functions, and so only the functions built in to the language are available for use. We can experiment with the behavior of Terraform’s built-in functions from the Terraform expression console, by running the terraform console
command.
Terraform Console
> help
The Terraform console allows you to experiment with Terraform interpolations.
You may access resources in the state (if you have one) just as you would
from a configuration. For example: "aws_instance.foo.id" would evaluate
to the ID of "aws_instance.foo" if it exists in your state.
Type in the interpolation to test and hit <enter> to see the result.
To exit the console, type "exit" and hit <enter>, or use Control-C or
Control-D.
>
String Functions
upper
converts all cased letters in the given string to uppercase.
> upper("Juniper Apstra")
"JUNIPER APSTRA"
>
lower
converts all cased letters in the given string to lowercase.
> lower("Terraform")
"terraform"
>
sort
takes a list of strings and returns a new list with those strings sorted lexicographically.
> sort(["j","u","n","i","p","e","r"])
tolist([
"e",
"i",
"j",
"n",
"p",
"r",
"u",
])
>
slice
extracts some consecutive elements from within a list. Here is the syntax slice(list, startindex, endindex)
. startindex
is inclusive, while endindex
is exclusive.
> slice(["j","u","n","i","p","e","r"],1,3)
[
"u",
"n",
]
>
distinct
takes a list and returns a new list with any duplicate elements removed.
The first occurrence of each value is retained and the relative ordering of these elements is preserved.
> distinct(["r","a","c","e","c","a","r"])
tolist([
"r",
"a",
"c",
"e",
])
>
split
produces a list by dividing a given string at all occurrences of a given separator.
> split(".", "192.168.1.1")
tolist([
"192",
"168",
"1",
"1",
])
>
join
produces a string by concatenating all of the elements of the specified list of strings with the specified separator.
> join("-", ["Juniper", "Apstra", "Terraform"])
"Juniper-Apstra-Terraform"
>
Numeric Functions
min
takes one or more numbers and returns the smallest number from the set.
max
takes one or more numbers and returns the greatest number from the set.
> min(1,2,3)
1
>
> max(5,6,7)
7
>
floor
returns the closest whole number that is less than or equal to the given value, which may be a fraction.
> floor(3.13)
3
> floor(5)
5
> floor(1.89)
1
>
IP Network Functions
cidrnetmask
converts an IPv4 address prefix given in CIDR notation into a subnet mask address.
> cidrnetmask("172.16.0.0/12")
"255.240.0.0"
> cidrnetmask("192.168.1.0/24")
"255.255.255.0"
> cidrnetmask("192.168.1.0/27")
"255.255.255.224"
>
cidrhost
calculates a full host IP address for a given host number within a given IP network address prefix.
> cidrhost("192.168.0.0/16", 300)
"192.168.1.44"
> cidrhost("192.168.0.0/16", 200)
"192.168.0.200"
> cidrhost("192.168.0.0/16", 512)
"192.168.2.0"
> cidrhost("192.168.0.0/16", 1024)
"192.168.4.0"
>
Type Conversion Functions
tonumber
converts its argument to a number value.
> tonumber("1")
1
> tonumber(9)
9
> tonumber("900")
900
>
For Expression
> [for s in ["a","b"] : upper(s)]
[
"A",
"B",
]
>
A for
expression’s input (given after the in
keyword) can be a list, a set, a tuple, a map, or an object.
The type of brackets around the for
expression decide what type of result it produces.
The above example uses [
and ]
, which produces a tuple. If you use {
and }
instead, the result is an object and you must provide two result expressions that are separated by the =>
symbol:
> {for s in ["a","b"] : s => upper(s)}
{
"a" = "A"
"b" = "B"
}
>
Splat Expression
A splat expression provides a more concise way to express a common operation that could otherwise be performed with a for
expression.
The special [*]
symbol iterates over all of the elements of the list given to its left and accesses from each one the attribute name given on its right.
> ["a","b"][*]
[
"a",
"b",
]
> ["a","b"][0]
"a"
> ["a","b"][1]
"b"
>
Let’s put all these together and create a VNI pool in Juniper Apstra.
pradeep@juniper apstra-terraform-8 % cat main.tf
terraform {
required_providers {
apstra = {
source = "Juniper/apstra"
version = ">= 0.28.0"
}
}
required_version = ">= 1.1"
}
provider "apstra" {
url = "https://admin:password@10.210.40.194:443"
tls_validation_disabled = true
blueprint_mutex_enabled = true
}
# This example creates a VNI pool consisting of 5 ranges with random
# begin/end values. Because the ranges must not overlap, the randomly
# selected begin/end values are sorted (as text!) before being used
# in a VNI pool range. If we randomly select the same value more than
# once, we'll wind up with fewer than 5 ranges.
locals {
vni_min = 4096
vni_max = 16777214
ranges_desired = 5
}
# generate 10 random values
resource "random_integer" "range_limits" {
count = local.ranges_desired * 2
min = local.vni_min
max = local.vni_max
}
# unique-ify, count pairs, and sort
locals {
unique_values = distinct(random_integer.range_limits[*].result)
pair_count = floor(length(local.unique_values) / 2)
unsorted_strings = formatlist("%08d", slice(local.unique_values, 0, local.pair_count * 2))
sorted_strings = sort(local.unsorted_strings)
sorted_numbers = [for s in local.sorted_strings : tonumber(s)]
}
# generate a VNI pool with ranges equal to the number
# of begin/end pairs available.
resource "apstra_vni_pool" "five_random_ranges" {
name = "five random ranges"
ranges = [for i in range(local.pair_count) : {
first = local.sorted_numbers[i * 2]
last = local.sorted_numbers[(i * 2) + 1]
}]
}
pradeep@juniper apstra-terraform-8
Terraform Init
pradeep@juniper apstra-terraform-8 % terraform init
Initializing the backend...
Initializing provider plugins...
- Finding juniper/apstra versions matching ">= 0.28.0"...
- Finding latest version of hashicorp/random...
- Installing juniper/apstra v0.42.0...
- Installed juniper/apstra v0.42.0 (signed by a HashiCorp partner, key ID CB9C922903A66F3F)
- Installing hashicorp/random v3.5.1...
- Installed hashicorp/random v3.5.1 (signed by HashiCorp)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
pradeep@juniper apstra-terraform-8 %
Terraform Apply
pradeep@juniper apstra-terraform-8 % terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# apstra_vni_pool.five_random_ranges will be created
+ resource "apstra_vni_pool" "five_random_ranges" {
+ id = (known after apply)
+ name = "five random ranges"
+ ranges = (known after apply)
+ status = (known after apply)
+ total = (known after apply)
+ used = (known after apply)
+ used_percentage = (known after apply)
}
# random_integer.range_limits[0] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[1] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[2] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[3] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[4] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[5] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[6] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[7] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[8] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
# random_integer.range_limits[9] will be created
+ resource "random_integer" "range_limits" {
+ id = (known after apply)
+ max = 16777214
+ min = 4096
+ result = (known after apply)
}
Plan: 11 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
random_integer.range_limits[7]: Creating...
random_integer.range_limits[8]: Creating...
random_integer.range_limits[1]: Creating...
random_integer.range_limits[2]: Creating...
random_integer.range_limits[5]: Creating...
random_integer.range_limits[7]: Creation complete after 0s [id=701768]
random_integer.range_limits[6]: Creating...
random_integer.range_limits[9]: Creating...
random_integer.range_limits[3]: Creating...
random_integer.range_limits[4]: Creating...
random_integer.range_limits[1]: Creation complete after 0s [id=13773872]
random_integer.range_limits[0]: Creating...
random_integer.range_limits[8]: Creation complete after 0s [id=14349966]
random_integer.range_limits[9]: Creation complete after 0s [id=4782211]
random_integer.range_limits[2]: Creation complete after 0s [id=13501423]
random_integer.range_limits[3]: Creation complete after 0s [id=15658190]
random_integer.range_limits[5]: Creation complete after 0s [id=9377344]
random_integer.range_limits[0]: Creation complete after 0s [id=519737]
random_integer.range_limits[4]: Creation complete after 0s [id=8836472]
random_integer.range_limits[6]: Creation complete after 0s [id=15079159]
apstra_vni_pool.five_random_ranges: Creating...
apstra_vni_pool.five_random_ranges: Creation complete after 2s [id=25f63957-679b-4f45-b094-56c46ad3f9b4]
Apply complete! Resources: 11 added, 0 changed, 0 destroyed.
pradeep@juniper apstra-terraform-8 %
Go to Apstra UI and verify the VNI pools.
pradeep@juniper apstra-terraform-8 % terraform show
# apstra_vni_pool.five_random_ranges:
resource "apstra_vni_pool" "five_random_ranges" {
id = "25f63957-679b-4f45-b094-56c46ad3f9b4"
name = "five random ranges"
ranges = [
{
first = 13773872
last = 14349966
status = "pool_element_available"
total = 576095
used = 0
used_percentage = 0
},
{
first = 15079159
last = 15658190
status = "pool_element_available"
total = 579032
used = 0
used_percentage = 0
},
{
first = 4782211
last = 8836472
status = "pool_element_available"
total = 4054262
used = 0
used_percentage = 0
},
{
first = 519737
last = 701768
status = "pool_element_available"
total = 182032
used = 0
used_percentage = 0
},
{
first = 9377344
last = 13501423
status = "pool_element_available"
total = 4124080
used = 0
used_percentage = 0
},
]
status = "not_in_use"
total = 9515501
used = 0
used_percentage = 0
}
# random_integer.range_limits[0]:
resource "random_integer" "range_limits" {
id = "519737"
max = 16777214
min = 4096
result = 519737
}
# random_integer.range_limits[1]:
resource "random_integer" "range_limits" {
id = "13773872"
max = 16777214
min = 4096
result = 13773872
}
# random_integer.range_limits[2]:
resource "random_integer" "range_limits" {
id = "13501423"
max = 16777214
min = 4096
result = 13501423
}
# random_integer.range_limits[3]:
resource "random_integer" "range_limits" {
id = "15658190"
max = 16777214
min = 4096
result = 15658190
}
# random_integer.range_limits[4]:
resource "random_integer" "range_limits" {
id = "8836472"
max = 16777214
min = 4096
result = 8836472
}
# random_integer.range_limits[5]:
resource "random_integer" "range_limits" {
id = "9377344"
max = 16777214
min = 4096
result = 9377344
}
# random_integer.range_limits[6]:
resource "random_integer" "range_limits" {
id = "15079159"
max = 16777214
min = 4096
result = 15079159
}
# random_integer.range_limits[7]:
resource "random_integer" "range_limits" {
id = "701768"
max = 16777214
min = 4096
result = 701768
}
# random_integer.range_limits[8]:
resource "random_integer" "range_limits" {
id = "14349966"
max = 16777214
min = 4096
result = 14349966
}
# random_integer.range_limits[9]:
resource "random_integer" "range_limits" {
id = "4782211"
max = 16777214
min = 4096
result = 4782211
}
pradeep@juniper apstra-terraform-8 %
Terraform Destroy
pradeep@juniper apstra-terraform-8 % terraform apply -destroy
random_integer.range_limits[1]: Refreshing state... [id=13773872]
random_integer.range_limits[2]: Refreshing state... [id=13501423]
random_integer.range_limits[4]: Refreshing state... [id=8836472]
random_integer.range_limits[6]: Refreshing state... [id=15079159]
random_integer.range_limits[9]: Refreshing state... [id=4782211]
random_integer.range_limits[5]: Refreshing state... [id=9377344]
random_integer.range_limits[3]: Refreshing state... [id=15658190]
random_integer.range_limits[7]: Refreshing state... [id=701768]
random_integer.range_limits[0]: Refreshing state... [id=519737]
random_integer.range_limits[8]: Refreshing state... [id=14349966]
apstra_vni_pool.five_random_ranges: Refreshing state... [id=25f63957-679b-4f45-b094-56c46ad3f9b4]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# apstra_vni_pool.five_random_ranges will be destroyed
- resource "apstra_vni_pool" "five_random_ranges" {
- id = "25f63957-679b-4f45-b094-56c46ad3f9b4" -> null
- name = "five random ranges" -> null
- ranges = [
- {
- first = 13773872 -> null
- last = 14349966 -> null
- status = "pool_element_available" -> null
- total = 576095 -> null
- used = 0 -> null
- used_percentage = 0 -> null
},
- {
- first = 15079159 -> null
- last = 15658190 -> null
- status = "pool_element_available" -> null
- total = 579032 -> null
- used = 0 -> null
- used_percentage = 0 -> null
},
- {
- first = 4782211 -> null
- last = 8836472 -> null
- status = "pool_element_available" -> null
- total = 4054262 -> null
- used = 0 -> null
- used_percentage = 0 -> null
},
- {
- first = 519737 -> null
- last = 701768 -> null
- status = "pool_element_available" -> null
- total = 182032 -> null
- used = 0 -> null
- used_percentage = 0 -> null
},
- {
- first = 9377344 -> null
- last = 13501423 -> null
- status = "pool_element_available" -> null
- total = 4124080 -> null
- used = 0 -> null
- used_percentage = 0 -> null
},
] -> null
- status = "not_in_use" -> null
- total = 9515501 -> null
- used = 0 -> null
- used_percentage = 0 -> null
}
# random_integer.range_limits[0] will be destroyed
- resource "random_integer" "range_limits" {
- id = "519737" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 519737 -> null
}
# random_integer.range_limits[1] will be destroyed
- resource "random_integer" "range_limits" {
- id = "13773872" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 13773872 -> null
}
# random_integer.range_limits[2] will be destroyed
- resource "random_integer" "range_limits" {
- id = "13501423" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 13501423 -> null
}
# random_integer.range_limits[3] will be destroyed
- resource "random_integer" "range_limits" {
- id = "15658190" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 15658190 -> null
}
# random_integer.range_limits[4] will be destroyed
- resource "random_integer" "range_limits" {
- id = "8836472" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 8836472 -> null
}
# random_integer.range_limits[5] will be destroyed
- resource "random_integer" "range_limits" {
- id = "9377344" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 9377344 -> null
}
# random_integer.range_limits[6] will be destroyed
- resource "random_integer" "range_limits" {
- id = "15079159" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 15079159 -> null
}
# random_integer.range_limits[7] will be destroyed
- resource "random_integer" "range_limits" {
- id = "701768" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 701768 -> null
}
# random_integer.range_limits[8] will be destroyed
- resource "random_integer" "range_limits" {
- id = "14349966" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 14349966 -> null
}
# random_integer.range_limits[9] will be destroyed
- resource "random_integer" "range_limits" {
- id = "4782211" -> null
- max = 16777214 -> null
- min = 4096 -> null
- result = 4782211 -> null
}
Plan: 0 to add, 0 to change, 11 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
apstra_vni_pool.five_random_ranges: Destroying... [id=25f63957-679b-4f45-b094-56c46ad3f9b4]
apstra_vni_pool.five_random_ranges: Destruction complete after 1s
random_integer.range_limits[7]: Destroying... [id=701768]
random_integer.range_limits[0]: Destroying... [id=519737]
random_integer.range_limits[5]: Destroying... [id=9377344]
random_integer.range_limits[6]: Destroying... [id=15079159]
random_integer.range_limits[2]: Destroying... [id=13501423]
random_integer.range_limits[9]: Destroying... [id=4782211]
random_integer.range_limits[3]: Destroying... [id=15658190]
random_integer.range_limits[4]: Destroying... [id=8836472]
random_integer.range_limits[1]: Destroying... [id=13773872]
random_integer.range_limits[8]: Destroying... [id=14349966]
random_integer.range_limits[3]: Destruction complete after 0s
random_integer.range_limits[4]: Destruction complete after 0s
random_integer.range_limits[8]: Destruction complete after 0s
random_integer.range_limits[1]: Destruction complete after 0s
random_integer.range_limits[0]: Destruction complete after 0s
random_integer.range_limits[9]: Destruction complete after 0s
random_integer.range_limits[7]: Destruction complete after 0s
random_integer.range_limits[2]: Destruction complete after 0s
random_integer.range_limits[6]: Destruction complete after 0s
random_integer.range_limits[5]: Destruction complete after 0s
Apply complete! Resources: 0 added, 0 changed, 11 destroyed.
pradeep@juniper apstra-terraform-8 %
Go back to Apstra UI and verify that the VNI pools are no longer present