Standing up infrastructure requires building networks, servers and storage entailing complex build and configuration management processes. Traditionally done with scripts or even manually, Terraform gives you a new alternative. Using Terraform you can write a declarative description of your infrastructure. Using the Terraform "compiler" the declaration is converted to a build plan and then the Terraform "builder" connects to your OCI tenancy and executes the plan. It is actually a bit more sophisticated than just doing the initial build. The builder connects to your tenancy and synchronizes it with the plan. Anything that already exists is left as-is, anything new is created and anything not in the plan is deleted. This allows you to edit your infrastructure by simply editing the Terraform code. Version control becomes only a matter of version control on the Terraform code.
In this example we'll take the shortest path to creating a simple resource in an OCI tenancy using Terraform code to demonstrate the steps involved in getting started with Terraform. To try it out you will need the following.
Of course you will also need a personal computer to run Terraform. Pretty much anything will do; Linux, Mac or Windows it just needs a bash shell. Easy enough on Linux and Mac, on Windows I've found MobaXterm or Git Bash to be reasonable choices.
Login to the OCI console for your tenancy and collect the following identifying information
These identifiers are all OCID's (pronounced O-sid) that look like ocid1.tenancy.oc1..aaaaaaaawpqblfemtluwxipipubxhioptheej2r32gvf7em7iftkr3vd2r3a<_span> and can be found on the tenancy and user information pages of the OCI console.
You will need an SSL key pair to enable Terraform to connect to the OCI API under your identity. Start by generating a key
user@computer$ openssl genrsa -out oci_api_key.pem 2048
set file access to owner only read and write
user@computer$ chmod 600 oci_api_key.pem
generate the public half of the key pair
user@computer$ openssl rsa -pubout -in oci_api_key.pem -out oci_api_key_public.pem
The public key needs to be added to your user account in the OCI console. Open the account page for your user and select the "Add Public Key" button. Copy and paste the contents of the oci_api_key_public.pem file in the box of the "Add Public Key" dialog as shown below.
Notice that after the public key is added the fingerprint is listed in the "API Keys" list. Copy the fingerprint for later use.
The Terraform executable is available at terraform.io Available for Linux, Mac Windows etc. pick the binary that matches your PC.
The download contains a single executable file. Unzip it to a directory that is on your PATH for example _home_me_bin. In order to update the executable when a new version is released simply download the new version, unzip and replace the executable.
As a basic example we'll put together Terraform code to make a VCN (Virtual Cloud Network) in OCI. There are a number of ways to get the identifier information we collected into the code but the most common is by using environment variables. The top of our code sample will reference the environment variables as shown. Create a development directory and add the following to a file called vcn.tf.
variable "tenancy_ocid" {} variable "user_ocid" {} variable "fingerprint" {} variable "private_key_path" {} variable "compartment_ocid" {} variable "region" {} provider "oci" { version = ">= 3.0.0" tenancy_ocid = "${var.tenancy_ocid}" user_ocid = "${var.user_ocid}" fingerprint = "${var.fingerprint}" private_key_path = "${var.private_key_path}" region = "${var.region}" }<_pre>
The corresponding environment variables have the form TF_VAR_* and hold the identity and connection information to the tenancy, user and compartment we collected earlier. Typically, put the following statements in a .sh file and source the file to set the environment values.
export TF_VAR_tenancy_ocid=ocid1.tenancy.oc1..aaaaaaaawpqblfe ... export TF_VAR_user_ocid=ocid1.user.oc1..aaaaaaaacwmzc7bt ... export TF_VAR_fingerprint=43:7b:50:07: ... export TF_VAR_private_key_path=oci_api_key.pem ### Region export TF_VAR_region=uk-london-1 ### Compartment export TF_VAR_compartment_ocid=ocid1.compartment.oc1..aaaaaaaaxxj ...<_pre>
Now add the following Terraform code that declares a VCN to the bottom of the vcn.tf file.
resource "oci_core_virtual_network" "simple-vcn" { cidr_block = "10.0.0.0_16" dns_label = "vcn1" compartment_id = "${var.compartment_ocid}" display_name = "simple-vcn" }<_pre>
The code declares a VCN resource named simple-vcn in the compartment identified from the compartment OCID environment variable.
The OCI provider is registered at Hashicorp and Terraform will download and update the plugin automatically as needed. In the directory containing the vcn.tf file run the init command as follows.
user@computer$ terraform init<_pre>
You should see something like the following showing that the provider has been downloaded and installed in the working directory.
user@computer$ terraform init Initializing provider plugins... - Checking for available provider plugins on https:__releases.hashicorp.com... - Downloading plugin for provider "oci" (3.5.0)... 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.<_pre>
Executing terraform -version<_span> will confirm the Terraform version and the provider version.
user@computer$ terraform -version Terraform v0.11.10 + provider.oci v3.5.0<_pre>
To create the build plan execute terraform plan<_span> in the working directory.
user@computer$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + oci_core_virtual_network.simple-vcn id: <computed> cidr_block: "10.0.0.0_16" compartment_id: "ocid1.compartment.oc1..aaaaaaaaxxjdxgyjxqxoiiv7yyb2zgez4pxaubsee4oguejnggwzhokqzhwa" default_dhcp_options_id: <computed> default_route_table_id: <computed> default_security_list_id: <computed> display_name: "simple-vcn" dns_label: "vcn1" freeform_tags.%: <computed> state: <computed> time_created: <computed> vcn_domain_name: <computed> Plan: 1 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.<_pre>
To create the resource execute terraform apply<_span> in the working directory.
user@computer$ terraform apply An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + oci_core_virtual_network.simple-vcn id: <computed> cidr_block: "10.0.0.0_16" compartment_id: "ocid1.compartment.oc1..aaaaaaaaxxjdxgyjxqxoiiv7yyb2zgez4pxaubsee4oguejnggwzhokqzhwa" default_dhcp_options_id: <computed> default_route_table_id: <computed> default_security_list_id: <computed> display_name: "simple-vcn" dns_label: "vcn1" freeform_tags.%: <computed> state: <computed> time_created: <computed> vcn_domain_name: <computed> Plan: 1 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 oci_core_virtual_network.simple-vcn: Creating... cidr_block: "" => "10.0.0.0_16" compartment_id: "" => "ocid1.compartment.oc1..aaaaaaaaxxjdxgyjxqxoiiv7yyb2zgez4pxaubsee4oguejnggwzhokqzhwa" default_dhcp_options_id: "" => "<computed>" default_route_table_id: "" => "<computed>" default_security_list_id: "" => "<computed>" display_name: "" => "simple-vcn" dns_label: "" => "vcn1" freeform_tags.%: "" => "<computed>" state: "" => "<computed>" time_created: "" => "<computed>" vcn_domain_name: "" => "<computed>" oci_core_virtual_network.simple-vcn: Creation complete after 1s (ID: ocid1.vcn.oc1.uk-london-1.aaaaaaaajnknx...aa3tnnzvkxutb7urmrygugvvfnr77jcg6zy5pa) Apply complete! Resources: 1 added, 0 changed, 0 destroyed.<_pre>
Checking the network resources in the console we see the VNC has been created.
Execute terraform destroy<_span> to terminate the resource.
user@computer$ terraform destroy oci_core_virtual_network.simple-vcn: Refreshing state... (ID: ocid1.vcn.oc1.uk-london-1.aaaaaaaajnknx...aa3tnnzvkxutb7urmrygugvvfnr77jcg6zy5pa) An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: - oci_core_virtual_network.simple-vcn Plan: 0 to add, 0 to change, 1 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 oci_core_virtual_network.simple-vcn: Destroying... (ID: ocid1.vcn.oc1.uk-london-1.aaaaaaaajnknx...aa3tnnzvkxutb7urmrygugvvfnr77jcg6zy5pa) oci_core_virtual_network.simple-vcn: Destruction complete after 1s Destroy complete! Resources: 1 destroyed.<_pre>
Terraform provides a powerful tool to create and manage infrastructure as code. Future additions to the tool set will likely include visual layout designers that will produce Terraform code from infrastructure diagrams and spreadsheets. Infrastructure as code is also a great option to rebuild environments in disaster recovery scenarios.
Previous Post