This is an old revision of the document!
DOCUMENTATION: To see the resources/data-sources and their parameters go to : “https://www.terraform.io/docs/providers/oci/” > Core > Resources
PROVIDER: for terraform is a driver for tf code to translate into oci api calls. Configure the provider External Link
# This is the bare minimum to setup the provider
provider "oci" {
tenancy_ocid = "${var.tenancy_ocid}"
user_ocid = "${var.user_ocid}"
fingerprint = "${var.fingerprint}"
private_key_path = "${var.private_key_path}"
region = "${var.region}"
}
terraform state list # lists all resources in the state file terraform show # human readable format terraform init # initializes the modules and calls the provider. Once, when we change project/lapto, see [[https://www.terraform.io/docs/ commands/get.html|link] terraform get # downloads all required modules terraform fmt -recursive # fixes syntax. Tabs are important terraform plan -out example1.tfplan # like a dry test terraform apply example1.tfplan # actual push
DATA SOURCES (RO) : Are more like to grab info. from existing, read-only stuff ( you can't always (actually, far from it) have the complete infrastructure in your tf templates, resources already exist and you don't have much control over them but you still need to use them inside your Terraform templates).
data "oci_identity_availability_domains" "test_availability_domains" {
compartment_id = var.tenancy_ocid
}
# needs the output below to show the datasource pulled from the cloud when doing the 'tf apply'
# syntax : data.TYPE.VALUE.ATTRIBUTE
output {
value = data.oci_identity_availability_domain.test_availability_domains.availability_domains
}
Syntax:
resource "oci_core_instance" "instance" { # << "provider_resource" "name of this specific resource"
VARIABLES: There are called with var.. They need to be defined before used (only in the same folder, not in subfolders).
variable.tfvar vs. variable.tf
Local variables - LOCALS 'alias' to be used when many repeated values are used in the module. Hello to keep your code DRY. Names are scoped to the module.
# defind like this:
locals {
http_port = 80
...
# then called like this:
resource "aws_lb_listener" "http" {
port = local.http_port
...
TBD
data “aws_region” “current” {
name = local.region }
ENVIRONMENTAL VARIABLES:
MODULE: Is a reusable piece of code. Any set of Terraform configuration files in a folder is a module. The main one, where we work, is called root module
File structure (example):
(d)modules main.tf outputs.tf variables.tf provider.tf backend.tf bootstrap.sh
FILES:
main.tf :
variables (in general)
‘id’ attribute
The syntax is TYPE.NAME.ATTRIBUTE. For example, ${aws_instance.web.id} will interpolate the ID attribute from the aws_instance resource named web. If the resource has a count attribute set, you can access individual attributes with a zero-based index, such as ${aws_instance.web.0.id}. You can also use the splat syntax to get a list of all the attributes: ${aws_instance.web.*.id}.
FILES:
PASSING VARIABLES TO MODULES:
! In the module folder, we have resources.
! also a variable.tf where we Declare the vars (we can also give them a default value) : variable "cluster_name" {..
! Inside the module's resources, we refer the variables like this : name = "${var.cluster_name}-alb"
!
!In the root main,tf (the one calling the modules (aka root module) we call the modules as below and Set the veriables like this:
module "lb-docservers-01" { # we call (instantiate) the module
source = "./modules/lb" # this is the location of the module
lb_display_name = "docservers-lb01"
[...]
# To:
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
cluster_name = "webservers-stage" # <<<<
[...]
In terraform there are no global variables. Either they’re specified in the resource/module itself (or in the local variable.tf) or passed as indicated above.
Ways of feeding lists of values to a module:
note: toset to convert it to a set, which will remove any duplicate elements and disregard the order of the elements.
module "tcp_8443__ocna_sources_tpdlb-be-internet_nsg_lhr" {
source = "./modules"
for_each = toset(var.ocna_sources) # then ocna_sources is defined in the variables.tf
nsg_near_side_id = oci_core_network_security_group.tpdlb-be-internet_nsg_lhr.id
traffic_source = each.value
Or
module "udp_53_cc-be-internet_nsg_lhr" {
for_each = toset(["216.146.35.35/32", "216.146.36.36/32", "8.8.8.8/32"])
source = "./modules"
nsg_near_side_id = oci_core_network_security_group.cc-be-internet_nsg_lhr.id
protocol = "17"
traffic_destination = each.key
Or (this is for aws, as the plugin accepts list directly in the 'cidr_blocks' attribute:
'module.common' is the folder path, then 'mycompany_ranges' is a list inside the outputs.tf file
resource "aws_security_group_rule" "allow_ssh_from_allowlist" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = concat(module.common.mycompany_ranges, module.common.vpn1_egress_ranges)
OUTPUTS:
Example1: If you wanted to output the arn of the following resource in a module:
resource "aws_lb" "test" {
# ...
}
You would use:
output "blah-es-asg" {
value = "${aws_lb.test.arn}" }
Then you access the value with:
module.name-of-mudule.blah-es-asg
Example2:
module "tpd-lb01" {
source = "./modules/lb"
backends = (
[for ip in module.tpd01.only_private_ips : {
ip = "${ip}"
}])
# That module tpd01 has a source folder.
# The folder has a whole structure with main, vars.. and outputs.tf.
# By adding .only_private_ips at the end, we make Can Grab the Output of the module (like an output of a functiomn in py) to use it somewhere else.
# it Use Like an Output generator 'module' contained in outputs.tf :
output "only_private_ips" {
value = [
for instance in oci_core_instance.instance : instance.private_ip
]
}
You cannot simply reference resources that belong to a module but from outside the module. You need to use outputs.
In an output, you define which data you want to be returned by the module
In ./modules/application/application.tf file:
output "hostname" {
value = "${aws_instance.app-server.private_dns}"
}
# Now you can use this output inside the template.tf like this:
module "crazy_foods" {
source = "./modules/application"
vpc_id = "${aws_vpc.my_vpc.id}"
subnet_id = "${aws_subnet.public.id}"
name = "CrazyFoods ${module.mighty_trousers.hostname}"
}
INTERPOLATION: allows us to reference any other resource it manages using the following syntax: ${RESOURCE_TYPE.RESOURCE_NAME.ATTRIBUTE_NAME}.
resource "aws_subnet" "public" {
vpc_id = "${aws_vpc.my_vpc.id}"
cidr_block = "10.0.1.0/24"
}
#
resource "aws_s3_bucket" "bucket2" {
bucket = "${data.aws_caller_identity.current.account_id}-bucket2"
}
CONDITIONALS AND THE 'COUNT' PROPERTY
See example
HLC is declarative so cannot have explicit if.. then..else. Instead it has this:
condition ? true_val : false_val
var.a != "" ? var.a : "default-a"
!
locals {
minimum_number_of_buckets = 5
number_of_buckets = var.bucket_count > 0 ? var.bucket_count : local.minimum_number_of_buckets
}
—-
Install tf:
TO BE SORTED: