# Modules

> An overview on how to construct, apply and destroy a Terraform configuration for OneFuse Modules with the OneFuse Terraform Provider

---

Site [llms.txt](/llms.txt)

---

## OneFuse Terraform configuration

Refer to [Getting started](/docs/onefuse/consume/hashicorp-terraform/getting-started/) for prerequisites, resources and more.

After [configuring the OneFuse Provider](/docs/onefuse/consume/hashicorp-terraform/getting-started/#configure-the-onefuse-provider), it is recommended to set up Resource(s), Data Source(s), Variable(s) and Output(s).

- Learn more via Terraform Docs about [Resources](https://www.terraform.io/docs/language/resources/index.html), [Data Sources](https://www.terraform.io/docs/language/data-sources/index.html), [Variables and Outputs](https://www.terraform.io/docs/language/values/index.html)

### Best practices for OneFuse modules

When using OneFuse modules within [Terraform Modules](https://www.terraform.io/docs/language/modules/index.html), it is a best practice to separate configurations into identifiable files.

For example, if you are using OneFuse modules with vSphere in a Terraform Module, the following structure is recommended:

| File name | Description |
| --- | --- |
| `main.tf` | The main file where you define providers, etc. |
| `onefuse.tf` | OneFuse Module configurations. |
| `[filename].tfvars` | `template_properties` for OneFuse Modules |
| `properties.tf` | OneFuse Property Toolkit configurations. |
| `vsphere.tf` | vSphere configurations. |
| `variables.tf` | Terraform inputs. |
| `output.tf` | Terraform outputs. |

### Data source(s)

Call Data Sources for all OneFuse Modules and fetch OneFuse Property Set(s) that are desired.

```hcl
// *********************
// SAMPLE
// *********************

// Data Source for OneFuse Property Set, lookup Property Set ID by name
// - Our example OneFuse Property Set: ps01 has the following properties:
//  {
//    "someKey": "someValue",
//    "parent": {
//      "someNestedKey": "someNestedValue"
//    },
//.   "someTemplateKey": "{{ my_template_var }}"
//  }
data "onefuse_property_set" "ps01" {
    name = "default"
}

// Data Source for rendering OneFuse Templates
data "onefuse_rendered_template" "env" {
    template = "{{env}}"
    template_properties = {"env": "prod"}
}

// Data Source for rendering OneFuse Template within a Property Set
data "onefuse_rendered_template_ps01" "rendered_ps01_template" {
    template = data.onefuse_property_set.ps01.raw
    template_properties = {"my_template_var": "Hello World"}
}

// Data Source for OneFuse Ansible Tower Policy, lookup the Policy ID by name
data "onefuse_ansible_tower_policy" "policy" {
  name = "default"
}

// Data Source for OneFuse DNS Policy, lookup the Policy ID by name
data "onefuse_dns_policy" "policy" {
  name = "default"
}

// Data Source for OneFuse IPAM Policy, lookup the Policy ID by name
data "onefuse_ipam_policy" "policy" {
  name = "default"
}

// Data Source for OneFuse Naming Policy, lookup the Policy ID by name
data "onefuse_naming_policy" "policy" {
  name = "default"
}

// Data Source for OneFuse Microsoft AD Policy, lookup the Policy ID by name
data "onefuse_ad_policy" "policy" {
  name = "default"
}

// Data Source for OneFuse Scripting Policy, lookup the Policy ID by name
data "onefuse_scripting_policy" "policy" {
  name = "default"
}

// Data Source for OneFuse ServiceNow CMDB Policy, lookup the Policy ID by name
data "onefuse_servicenow_cmdb_policy" "policy" {
  name = "default"
}
```

### Resource(s)

Create a Resource for each OneFuse Modules and configure them to work together. The Terraform Resource describes and declares the OneFuse Module's Policy and its settings.

```hcl
// *********************
// SAMPLE
// *********************

// Resource for OneFuse Naming Record
resource "onefuse_naming" "name" {
  naming_policy_id        = data.onefuse_naming_policy.policy.id
  template_properties     = var.template_properties
}


// Resource for OneFuse Microsoft AD Record
resource "onefuse_microsoft_ad_computer_account" "computer" {
    name                = onefuse_naming.name.name          //Use Name Record
    policy_id           = data.onefuse_ad_policy.policy.id
    template_properties = var.template_properties
}


// Resource for OneFuse IPAM Record
resource "onefuse_ipam_record" "ipam-record" {
    hostname            = onefuse_naming.name.name            //Use Name Record
    policy_id           = data.onefuse_ipam_policy.policy.id
    template_properties = var.template_properties

lifecycle {
    ignore_changes = [
      hostname,
      dns_suffix
    ]
  }
}

// Resource for OneFuse DNS Record
resource "onefuse_dns_record" "dns-record" {
    name                = onefuse_naming.name.name                   //Use Name Record
    policy_id           = data.onefuse_dns_policy.policy.id
    zones               = [onefuse_naming.name.dns_suffix]
    value               = onefuse_ipam_record.ipam-record.ip_address //Use IPAM Record
    template_properties = var.template_properties
}

// Resource for OneFuse Ansible Tower
resource "onefuse_ansible_tower_deployment" "at-deployment" {
  policy_id           = data.onefuse_ansible_tower_policy.policy.id
  workspace_url       = var.workspace_url
  limit               = "*"                                          // Ansible Tower Policy Limit
  hosts               = [onefuse_naming.name.name]                   // Hosts to run the policy against, Use Name Record
  template_properties = var.template_properties
  timeouts {
    create = "12m"
    delete = "3m"
  }
}

// Resource for OneFuse Scripting
resource "onefuse_scripting_deployment" "scripting-deployment" {
    policy_id           = data.onefuse_scripting_policy.policy.id
    workspace_url       = var.workspace_url
    template_properties = var.template_properties
}

// Resource for ServiceNow CMDB
resource "onefuse_servicenow_cmdb_deployment" "servicenow-cmdb-deployment" {
  policy_id           = data.onefuse_servicenow_cmdb_policy.policy.id
  workspace_url       = var.workspace_url
  template_properties = var.template_properties
}
```

### Variable(s)

In the Resource samples above, `template_properties` are referring to a Variable. For [best practices](#best-practices-for-onefuse-modules), keep all defined variables in a `variables.tf` file.

```hcl
// *********************
// SAMPLE
// *********************

variable "template_properties" {
  type = map
  default = {
      "nameEnvironment"       = "p"
      "nameOS"                = "w"
      "nameApplication"       = "ap"
      "nameLocation"          = "atl"
      "nameCompliance"        = "pci"
      "ouEnvironment"         = "production"
      "ouApplication"         = "pwordpress"
      "ouLocation"            = "Atlanta"
      "dnsSuffix"             = "company.com"
  }
}
```

### Output(s)

To see outputs from OneFuse Modules, the following declarations are made to the configuration.

In the sample below, see how specific properties are referenced within a OneFuse Property Set.

```hcl
// *********************
// SAMPLE
// *********************

// Property Set
// - Simple key:value pairs can be indexed in the `properties` attribute
output "ps01_someKey_value" {
  value = data.onefuse_property_set.ps01.properties.someKey
}
// - Complex values (key:object or key:list) need to be JSON decoded in Terraform to access the nested properties
output "ps01_someNestedKey_value" {
  value = jsondecode(data.onefuse_property_set.ps01.raw).parent.someNestedKey
}

// Rendered Templates
output "rendered_env" {
  value = data.onefuse_rendered_template.env.value
}

// Rendered OneFuse Template within a Property Set
output "rendered_template" {
  value = data.onefuse_rendered_template_ps01.rendered_ps01_template.value
}

// Naming
output "hostname" {
  value = onefuse_naming.name.name
}
output "fqdn" {
  value = onefuse_naming.name.id
}

// IPAM
output "ip_address" {
  value = onefuse_ipam_record.ipam-record.ip_address
}
output "netmask" {
  value = onefuse_ipam_record.ipam-record.netmask
}
output "gateway" {
  value = onefuse_ipam_record.ipam-record.gateway
}
output "network" {
  value = onefuse_ipam_record.ipam-record.network
}
output "subnet" {
  value = onefuse_ipam_record.ipam-record.subnet
}

// DNS
output "primary_dns" {
  value = onefuse_ipam_record.ipam-record.primary_dns
}
output "secondary_dns" {
  value = onefuse_ipam_record.ipam-record.secondary_dns
}

// Microsoft Active Directory
output "ad_ou" {
  value = onefuse_microsoft_ad_computer_account.computer.final_ou
}
```

---

## Terraform init, plan and apply

After piecing the plan together, perform the following Terraform commands to invoke OneFuse Modules:

1. Complete the plan with Data Source(s), Resource(s) and Variable(s) and Output(s)

   Sample `variables.tf` file:

   ```hcl
   //OneFuse Provider Inputs
   variable "onefuse_scheme" {
     type = string
     default = "https"
   }
   variable "onefuse_address" {
     type = string
   }
   variable "onefuse_port" {
     type = string
     default = 443
   }
   variable "onefuse_user" {
     type = string
   }
   variable "onefuse_password" {
     type = string
   }
   variable "onefuse_verify_ssl" {
     type = bool
     default = false
   }
   variable "workspace_url" {
     type = string
     default = "" // Default
   }


   // OneFuse template_properties
   variable "template_properties" {
     type = map
     default = {
         "nameEnvironment"       = "p"
         "nameOS"                = "w"
         "nameApplication"       = "ap"
         "nameLocation"          = "atl"
         "nameCompliance"        = "pci"
         "ouEnvironment"         = "production"
         "ouApplication"         = "pwordpress"
         "ouLocation"            = "Atlanta"
         "dnsSuffix"             = "company.com"
     }
   }
   ```

   Sample completed plan:

   ```hcl
   // OneFuse Terraform Provider
   terraform {
     required_providers {
       onefuse = {
         source  = "CloudBoltSoftware/onefuse"
         version = ">= 1.40.0"
      }
     }
     required_version = ">= 0.13"
   }

   // Inititalize OneFuse Provider
   provider "onefuse" {

     scheme     = var.onefuse_scheme
     address    = var.onefuse_address
     port       = var.onefuse_port
     user       = var.onefuse_user
     password   = var.onefuse_password
     verify_ssl = var.onefuse_verify_ssl
   }

   // Data Source for OneFuse DNS Policy, lookup the Policy ID by name
   data "onefuse_dns_policy" "policy" {
     name = "default"
   }

   // Data Source for OneFuse IPAM Policy, lookup the Policy ID by name
   data "onefuse_ipam_policy" "policy" {
     name = "default"
   }

   // Data Source for OneFuse Naming Policy, lookup the Policy ID by name
   data "onefuse_naming_policy" "policy" {
     name = "default"
   }

   // Data Source for OneFuse Microsoft AD Policy, lookup the Policy ID by name
   data "onefuse_ad_policy" "policy" {
     name = "default"
   }

   // Resource for OneFuse Naming Record
   resource "onefuse_naming" "name" {
     naming_policy_id        = data.onefuse_naming_policy.policy.id
     template_properties     = var.template_properties
   }


   // Resource for OneFuse Microsoft AD Record
   resource "onefuse_microsoft_ad_computer_account" "computer" {
       name                = onefuse_naming.name.name          //Use Name Record
       policy_id           = data.onefuse_ad_policy.policy.id
       template_properties = var.template_properties
   }


   // Resource for OneFuse IPAM Record
   resource "onefuse_ipam_record" "ipam-record" {
       hostname            = onefuse_naming.name.name            //Use Name Record
       policy_id           = data.onefuse_ipam_policy.policy.id
       template_properties = var.template_properties

   lifecycle {
       ignore_changes = [
         hostname,
         dns_suffix
       ]
     }
   }

   // Resource for OneFuse DNS Record
   resource "onefuse_dns_record" "dns-record" {
       name                = onefuse_naming.name.name                   //Use Name Record
       policy_id           = data.onefuse_dns_policy.policy.id
       zones               = [onefuse_naming.name.dns_suffix]
       value               = onefuse_ipam_record.ipam-record.ip_address //Use IPAM Record
       template_properties = var.template_properties
   }

   // Naming
   output "hostname" {
     value = onefuse_naming.name.name
   }
   output "fqdn" {
     value = onefuse_naming.name.id
   }

   // IPAM
   output "ip_address" {
     value = onefuse_ipam_record.ipam-record.ip_address
   }
   output "netmask" {
     value = onefuse_ipam_record.ipam-record.netmask
   }
   output "gateway" {
     value = onefuse_ipam_record.ipam-record.gateway
   }
   output "network" {
     value = onefuse_ipam_record.ipam-record.network
   }
   output "subnet" {
     value = onefuse_ipam_record.ipam-record.subnet
   }

   // DNS
   output "primary_dns" {
     value = onefuse_ipam_record.ipam-record.primary_dns
   }
   output "secondary_dns" {
     value = onefuse_ipam_record.ipam-record.secondary_dns
   }

   // Microsoft Active Directory
   output "ad_ou" {
     value = onefuse_microsoft_ad_computer_account.computer.final_ou
   }
   ```

1. Initialize the working directory via [Command: init](https://www.terraform.io/docs/cli/commands/init.html)

   ```bash
   terraform init
   ```

1. Create the execution plan via [Command: plan](https://www.terraform.io/docs/cli/commands/plan.html)

   ```bash
   terraform plan
   ```

1. Execute the actions proposed in the Terraform plan via [Command: apply](https://www.terraform.io/docs/cli/commands/apply.html)

   ```bash
   terraform apply
   ```

---

## Terraform destroy

Destroy all of the remote objects managed by the Terraform configuration when no longer needed.

1. Destroy via [Command: destroy](https://www.terraform.io/docs/cli/commands/destroy.html)

   ```bash
   terraform destroy
   ```

## Terraform import

Terraform import is a command used in Terraform to bring existing infrastructure under Terraform's management. This allows you to manage resources that were created outside of Terraform or manually, without having to recreate them.

1. Import via [Command: import](https://developer.hashicorp.com/terraform/cli/commands/import)

   ```bash
   terraform import <resource_type>.<resource_name> <resource_id>
   ```

---

Section pages:

- [Templating and Property Toolkit](/docs/onefuse/consume/hashicorp-terraform/modules/templating-property-toolkit/): Use Templating and Property Toolkit features in Terraform
- [Ansible Tower](/docs/onefuse/consume/hashicorp-terraform/modules/ansible-tower/): Create the Ansible Tower Resource in Terraform to run Ansible Tower Job Templates
- [DNS](/docs/onefuse/consume/hashicorp-terraform/modules/dns/): Create the DNS Resource in Terraform to register and release DNS Records
- [IPAM](/docs/onefuse/consume/hashicorp-terraform/modules/ipam/): Create the IPAM Resource in Terraform to reserve and release IP Addresses
- [Microsoft Active Directory](/docs/onefuse/consume/hashicorp-terraform/modules/microsoft-active-directory/): Create the Microsoft Active Directory Resource in Terraform to create and delete Computer Accounts
- [Naming](/docs/onefuse/consume/hashicorp-terraform/modules/naming/): Create the Naming Resource in Terraform to generate and destroy Names
- [Pluggable modules](/docs/onefuse/consume/hashicorp-terraform/modules/pluggable-modules/): Create the Pluggable Module Resource in Terraform to run Pluggable Module Policies
- [Scripting](/docs/onefuse/consume/hashicorp-terraform/modules/scripting/): Create the Scripting Resource in Terraform to execute Scripts
- [ServiceNow CMDB](/docs/onefuse/consume/hashicorp-terraform/modules/servicenow-cmdb/): Create the ServiceNow CMDB Resource in Terraform to create and consume ServiceNow "CIs-as-a-Service"
- [VMware Aria Automation](/docs/onefuse/consume/hashicorp-terraform/modules/vmware-aria-automation/): Configure and use the OneFuse VMware Aria Automation module with HashiCorp Terraform
