OpenTofu Plan

The guide here demonstrates the basic concepts around creating and executing an OpenTofu plan service within torero.

Prerequisites

It is a prerequisite that a Git repository be setup with the OpenTofu plan within it. Review the Create Repository command to understand on how to create a repository.

Create

torero create service opentofu-plan will perform a creation of the OpenTofu plan service. A more detailed guide on all creation options is available there but this guide should help get you started.

The command shown below creates an OpenTofu plan service within the torero called simple-tofu. We are leveraging a previously configured repository called torero-resources.

>_ torero create service opentofu-plan simple-tofu --repository torero-resources --working-dir opentofuplans

It is important to stop and understand the structure of torero-resources before moving further.

torero-resources (git repo)

├── README.md
├── ansibleplaybooks
├── pythonscripts
├── opentofuplans
│   └── main.tf

We can specify that we want to use torero-resources via the --repository flag.

Notice that our OpenTofu plan files exist in a directory called opentofuplans. We can denote this using the --working-dir flag.


Verify Creation

We can view details about the previously created OpenTofu plan service by running the describe service command.

>_ torero describe service simple-tofu
Output:

Name:        simple-tofu
Repo Name:   torero-resources
Working Dir: opentofuplans
Vars:        
Var Files:   
Decorator:   
Description: 
Tags:        

Execution

Within an OpenTofu plan service, we can execute either an apply or destroy using the run command.

Apply

When an apply command is executed, torero will run a tofu init and a tofu apply against the plan along with any additional configuration flags that are set as a part of the service.

If we look at our torero-resources example plan's main.tf file, we can see that it is a very simple plan that will create a file on a user's machine.

variable "content" {
  type = string
}

variable "location" {
  type=string
}

resource "local_file" "foo" {
  content  = var.content
  filename = var.location
  file_permission = "0644"
}
The plan requires two variables: content and location. We can supply these values using the --set flag. We can also specify where to save the initial state file using the --state-out flag.

>_ torero run opentofu-plan apply hello-world --set content=hello --set location=/tmp/toreroTest.txt --state-out @tofu.tfstate
Output:

Start Time:   2024-01-01T12:00:00Z
End Time:     2024-01-01T12:00:01Z
Elapsed Time: 1.372672s
Return Code: 0
Stdout:        
Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/local...
- Installing hashicorp/local v2.5.1...
- Installed hashicorp/local v2.5.1 (signed, key ID 0C0AF313E5FD9F80)

Providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://opentofu.org/docs/cli/plugins/signing/

OpenTofu has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.

OpenTofu has been successfully initialized!

You may now begin working with OpenTofu. Try running "tofu plan" to see
any changes that are required for your infrastructure. All OpenTofu commands
should now work.

If you ever set or change modules or backend configuration for OpenTofu,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

OpenTofu used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

OpenTofu will perform the following actions:

  # local_file.foo will be created
  + resource "local_file" "foo" {
      + content              = "hello"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0644"
      + filename             = "/tmp/toreroTest.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
local_file.foo: Creating...
local_file.foo: Creation complete after 0s [id=c3499c2729730a7f807efb8676a92dcb6f8a3f8f]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Stderr:     
State File: {"check_results":null,"lineage":"f48d5e76-b162-ccd2-6670-e1cbc62cfaa6","outputs":{},"resources":[{"instances":[{"attributes":{"content":"example","content_base64":null,"content_base64sha256":"UNhY4JhezH9gQYqvDMWrWH9CwlcKiECVqejMrND2VFw=","content_base64sha512":"O7Eu2jwpjbXeJVl/VNkk8uF+eKJq2JU+2CGO5oLwu76QIeLzAJ0VLJEb8fJexoOpAnFBZnZ6+9jlvQ+wEk7Lig==","content_md5":"1a79a4d60de6718e8e5b326e338ae533","content_sha1":"c3499c2729730a7f807efb8676a92dcb6f8a3f8f","content_sha256":"50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c","content_sha512":"3bb12eda3c298db5de25597f54d924f2e17e78a26ad8953ed8218ee682f0bbbe9021e2f3009d152c911bf1f25ec683a902714166767afbd8e5bd0fb0124ecb8a","directory_permission":"0777","file_permission":"0644","filename":"/tmp/gatewayTest.txt","id":"c3499c2729730a7f807efb8676a92dcb6f8a3f8f","sensitive_content":null,"source":null},"schema_version":0,"sensitive_attributes":[]}],"mode":"managed","name":"foo","provider":"provider[\"registry.opentofu.org/hashicorp/local\"]","type":"local_file"}],"serial":1,"terraform_version":"1.6.2","version":4}

You can now verify that a file has indeed been created at the location specified using the location variable.

Destroy

When a torero run opentofu-plan destroy command is executed, torero will run a tofu init and a tofu destroy against the plan along with any additional configuration flags that are set as a part of the service.

To delete the file that was created as a part of the previously run apply command, we can use the following syntax.

>_ torero run opentofu-plan destroy simple-tofu --set content=hello --set location=/tmp/toreroTest.txt --state @tofu.tfstate

Note that we are now passing in a state file that torero will read from and write to when executing the plan using the --state flag.

We also could have used the following syntax to pass in the state file

>_ torero run opentofu-plan destroy simple-tofu --set content=hello --set location=/tmp/toreroTest.txt --state '{"check_results":null,"lineage":"f48d5e76-b162-ccd2-6670-e1cbc62cfaa6","outputs":{},"resources":[{"instances":[{"attributes":{"content":"example","content_base64":null,"content_base64sha256":"UNhY4JhezH9gQYqvDMWrWH9CwlcKiECVqejMrND2VFw=","content_base64sha512":"O7Eu2jwpjbXeJVl/VNkk8uF+eKJq2JU+2CGO5oLwu76QIeLzAJ0VLJEb8fJexoOpAnFBZnZ6+9jlvQ+wEk7Lig==","content_md5":"1a79a4d60de6718e8e5b326e338ae533","content_sha1":"c3499c2729730a7f807efb8676a92dcb6f8a3f8f","content_sha256":"50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c","content_sha512":"3bb12eda3c298db5de25597f54d924f2e17e78a26ad8953ed8218ee682f0bbbe9021e2f3009d152c911bf1f25ec683a902714166767afbd8e5bd0fb0124ecb8a","directory_permission":"0777","file_permission":"0644","filename":"/tmp/gatewayTest.txt","id":"c3499c2729730a7f807efb8676a92dcb6f8a3f8f","sensitive_content":null,"source":null},"schema_version":0,"sensitive_attributes":[]}],"mode":"managed","name":"foo","provider":"provider[\"registry.opentofu.org/hashicorp/local\"]","type":"local_file"}],"serial":1,"terraform_version":"1.6.2","version":4}'

Decorators

It is possible to put restrictions around the inputs that are accepted by an OpenTofu plan by utilizing decorators. For more information on decorators in general, please refer to this guide.

CLI Reference

OpenTofu Plan Create

OpenTofu Plan Run

Services Get

Service Describe

Service Delete