User Tools

Site Tools


virtualization:cloud:terraform

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

  • This is the idea but not always strictly true:
    • Modules is what i write, building blocks, reusable.
    • But eventually, what is implemented is a Resource. It refers to a oci_core resource that can be found in the page above

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).

  • terraform.tfvars : tfvars file extension is in the root folder of an environment to define values to variables. So we use a *.tfvar file to load in defaults as they are automatically loaded without any additional command line option.
  • variables.tf : the .tf uses modules to declare them

variable.tfvar vs. variable.tf

  • resource-specific parameters
  • meta-parameters
  • provisioners

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:

  1. Terraform looks for environment variables with a special prefix of “TF_VAR_variablename . note that TF_VAR_variablenam overrides the default value of variablename defined inside a tf file

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

  • Check this Example of an extremely simple module
    • when we call the module, the name is unrelated to the resources themselves.
    • Source points to the moudule's location
    • main.tf in that location is the module's entry point!

File structure (example):

(d)modules 
main.tf
outputs.tf
variables.tf 
provider.tf
backend.tf
bootstrap.sh

FILES:

  • main.tf : is where the execution starts
  • provider.tf :
  • variables.tf : where we define the parameters
  • outputs.tf : from the user's pow is more an input data. ocna_ranges we put here is consumed by a module by means of a statement like “cidr_blocks = module.common.ocna_ranges” ; note 'common' is the folder hosting the outputs.tf file where ocna_ranges is defined!)
  • data.tf :
    • data source is not really related to data.tf. A data source is accessed via a special kind of resource known as a data resource, declared using a data block. See this LINK
  • backend.tf : for the state file key
  • 'key' is no more than the name of the state file in the block storage – GUI: Phoenix > block storage > compartment Context_Slingshot > ‘ContextTerraformState’ bucket > then we select the file, which can be easily downloaded « is just a json file


main.tf :

  • You normally create an 'object' module from the 'class' module defined in the modules folder
  • count : is a reserved variable and defines how many times it goes via that set of instructions


variables (in general)

  • var -from→ variable.tf like in compartment_id = “${var.server_compartment_ocid}”
    • vars can be passed also module-to-resource (see below 'passing variables')
  • module -from→ data.tf
  • modules group resources (normally in the data.tf ): see link


‘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:

  • setup.sh
  • userdata.sh : for the ldap authenticatio
  • bootstrap.sh : from gavin (includes userdata.sh )

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"
}

LOOPS:

  • for (see above)
  • for_each = var.db_instances

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:

  • download something like this in Downloads folder: terraform_0.11.11_linux_amd64.zip
  • unzip it and place it in /bin/terraform

TO BE SORTED:

  • vars defined in variables.tf or hardcoded in the resource's module
virtualization/cloud/terraform.1695999349.txt.gz · Last modified: (external edit)