USE OCI OBJECT STORAGE TO STORE TERRAFORM STATE FILES

download.png

Introduction

Terraform allows you to deploy infrastructure very quickly, and you can find thousands of script/modules/snippets on the web to get you started in a snap.

Once you move from the “Let’s try this at home” phase to a more “Let’s do this for a real environment” oriented phase you will have to make a lot of decisions about how you are going to maintain your infrastructure and how you are going to manage change, possibly in a non destructive way.

Nothing like dropping a production environment on a Friday evening while you are testing a small change in your dev environment will make you realise how badly you need this when moving past the Terraform learning phase.

One important decision during this transition to real world use of terraform is the location where you are going to store a Terraform project state file.

In this tutorial you will learn how to configure OCI Object storage as a remote backend for a sample terraform project, this will allow you to replicate the setup for your projects.

What is a terraform state file?

Terraform must store state information about your managed infrastructure and configuration. This state is used by Terraform to map real world resources to your configuration, keep track of metadata, and to improve performance for large infrastructures.

This state is stored by default in a local file named “terraform.tfstate”, but it can also be stored remotely, which is essential when more than one person is working on the same project. With remote state, Terraform writes the state data to a remote data store, which can then be shared between all members of a team, encrypted, versioned and secured. Terraform supports storing state in Terraform CloudHashiCorp Consul, Amazon S3, Alibaba Cloud OSS, and other providers.

If you want to dig deeper into why Terraform needs a state file to work you can have a look here: https://www.terraform.io/docs/state/purpose.html

Terraform remote state file and OCI support

OCI object storage is not supported natively for storing state files, but since it has an AWS S3 compatibility layer we can use it all the same

Requirements

An Active Oracle Cloud Tenancy

If you do not have one, you can enroll here for a trial subscription that includes $300 of free credits

An Oracle Cloud Shell Instance

The OCI Cloud Shell is a web browser-based terminal accessible from the Oracle Cloud Console. Cloud Shell is free to use (within monthly tenancy limits), and provides access to a Linux shell, with a pre-authenticated Oracle Cloud Infrastructure CLI and other useful tools for following Oracle Cloud Infrastructure service tutorials and labs. Cloud Shell is a feature available to all OCI users, accessible from the Console. Your Cloud Shell will appear in the Oracle Cloud Console as a persistent frame of the Console and will stay active as you navigate to different pages of the Console. You can find detailed instructions on how to get started with the OCI Cloud Shell here

cloudshell-1.png

Create an initial working dir:

mkdir fk-terraform-objectstorage
cd fk-terraform-objectstorage/

A test terraform project

git clone https://github.com/mattiarossi/terraform-oci-default-vcn/


Cloning into 'terraform-oci-default-vcn'...
remote: Enumerating objects: 61, done.
remote: Counting objects: 100% (61/61), done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 75 (delta 27), reused 44 (delta 14), pack-reused 14
Unpacking objects: 100% (75/75), done.


cd terraform-oci-default-vcn/examples/vcn_default/

The test project will deploy a simple VCN in a compartment of your choice, configurable in the project variables, and will store the state file in an OCI Object storage Bucket that needs to be created in advance

An OCI Object Storage Bucket

The bucket needs to be created in the Compartment that is designated on OCI to be the target for the AWS S3 compatibility layer. You can check the active S3 compartment by using the following command:

oci os ns  get-metadata --output=table
+-------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+-----------+
| default-s3-compartment-id                                                           | default-swift-compartment-id                                                        | namespace |
+-------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+-----------+
| ocid1.compartment.oc1..aaaaaaa...4nxhlvbbbbbbb3kpmffof6vba                          | ocid1.compartment.oc1..aaaaaaa...hlvbbbbbbbbpmffof6vba                              | mytenancy |
+-------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+-----------+

We will be using a bucket named tf-fk-test-01

This command will create a bucket named tf-fk-test-01 in the AWS s3 compatibility layer compartment:

oci os bucket create --compartment-id ocid1.compartment.oc1..aaaaaaa...4nxhlvb3luoh3kpmffof6vba --name tf-fk-test-01

A properly configured AWS S3 compatibility environment

In order to be able to access the Object Storage bucket using the S3 compatibility layer, you need to generate a set of access credentials, and the oci cli command needed for creating these needs to know the current user ocid:

export ME=mattia.rossi@myemail.com (my tenancy username)
oci iam user list --query "data[?\"name\"=='$ME']".{"name:\"name\",id:\"id\""} --output table

+------------------------------------------------------------------------------+--------------------------+
| id                                                                           | name                     |
+------------------------------------------------------------------------------+--------------------------+
| ocid1.user.oc1..aaaaaaa..................................tojgy2qybdkcayvnxsq | mattia.rossi@myemail.com |
+------------------------------------------------------------------------------+--------------------------+

export OCIUID=ocid1.user.oc1..aaaaaaa..................................tojgy2qybdkcayvnxsq

The following command will reuse the ocid variable to create the credentials needed to setup the AWS compatibility layer (please note that these are examples only and you will need to insert the proper secrets generated by the oci cli in the export command

oci iam customer-secret-key create --user-id $OCIUID --display-name 'key-tf-test' --query "data".{"AWS_ACCESS_KEY_ID:\"id\",AWS_SECRET_ACCESS_KEY:\"key\""} --output=table

+------------------------------------------+----------------------------------------------+
| AWS_ACCESS_KEY_ID                        | AWS_SECRET_ACCESS_KEY                        |
+------------------------------------------+----------------------------------------------+
| fd9bcbb0.........................93e7139 | kS/...............................PRDoGX1NY= |
+------------------------------------------+----------------------------------------------+

export AWS_ACCESS_KEY_ID=fd9bcbb0.........................93e7139
export AWS_SECRET_ACCESS_KEY=kS/...............................PRDoGX1NY=

Environment variables

The only other environment variable needed by the project for authenticating is the tenancy ocid, that can be set up using this command:

export TF_VAR_tenancy_ocid=`cat /etc/oci/config  | grep tenancy | uniq | cut -d '=' -f 2`

Terraform project config

Prepare one variable file named “terraform.tfvars” with the configuration information. The content of “terraform.tfvars” should look something like the following:

$ cat terraform.tfvars
# Region
region = "eu-frankfurt-1"

# Compartment
compartment_ocid = ""

# VCN Configurations
vcn_display_name = "testVCN"
vcn_cidr = "10.0.0.0/16"

Use the following script to retrieve the ocid of the compartment where you want to deploy the test VCN:

export COMPARTMENT=my-compartment
oci iam compartment list --query "data[?\"name\"=='$COMPARTMENT']".{"name:\"name\",id:\"id\""} --output=table
+-------------------------------------------------------------------------------------+-----------------------+
| id                                                                                  | name                  |
+-------------------------------------------------------------------------------------+-----------------------+
| ocid1.compartment.oc1..aaaaaaaabmc54lgslm..........................3hygseg6qeh5pvwq | my-compartment        |
+-------------------------------------------------------------------------------------+-----------------------+

Edit the file vcn_default.tf, and update the terraform backend section to match your OCI setup:

terraform {
  backend "s3" {
    endpoint                    = "https://__mytenancy__.compat.objectstorage.__region__.oraclecloud.com"
    skip_metadata_api_check     = true
    skip_region_validation      = true
    force_path_style            = true
    skip_credentials_validation = true
    bucket                      = "__mybucket__"
    key                         = "__key__"
    region                      = "__region__"
  }
}

where:

  • __mytenancy__ is your tenancy name
  • __region__ is the region where you created the Object Storage bucket
  • __mybucket__ is the name of the bucket you created
  • key is the name of the bucket entry that will hold your terraform state file (for example: terraform/state/oci/vcn/testVCN/terraform.tfstate)

Then apply the example using the following commands:

terraform init
terraform plan
terraform apply

Init:

mattia_ros@cloudshell:vcn_default (eu-frankfurt-1)$ terraform init
Initializing modules...
- vcn in ../..

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "oci" (hashicorp/oci) 3.74.0...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.oci: version = "~> 3.74"

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.

Plan:

mattia_ros@cloudshell:vcn_default (eu-frankfurt-1)$ 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.

module.vcn.data.oci_identity_availability_domains.this: Refreshing state...

------------------------------------------------------------------------

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:

# module.vcn.oci_core_default_route_table.this will be created
+ resource "oci_core_default_route_table" "this" {
+ defined_tags = (known after apply)
+ display_name = (known after apply)
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ manage_default_resource_id = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)

+ route_rules {
+ cidr_block = (known after apply)
+ description = (known after apply)
+ destination = "0.0.0.0/0"
+ destination_type = (known after apply)
+ network_entity_id = (known after apply)
}
}

# module.vcn.oci_core_internet_gateway.this will be created
+ resource "oci_core_internet_gateway" "this" {
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ display_name = (known after apply)
+ enabled = true
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
}

# module.vcn.oci_core_subnet.this[0] will be created
+ resource "oci_core_subnet" "this" {
+ availability_domain = "okVf:EU-FRANKFURT-1-AD-1"
+ cidr_block = "192.168.0.0/28"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ dhcp_options_id = (known after apply)
+ display_name = "Default Subnet okVf:EU-FRANKFURT-1-AD-1"
+ dns_label = "subnet1"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ ipv6virtual_router_ip = (known after apply)
+ prohibit_public_ip_on_vnic = (known after apply)
+ route_table_id = (known after apply)
+ security_list_ids = (known after apply)
+ state = (known after apply)
+ subnet_domain_name = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
+ virtual_router_ip = (known after apply)
+ virtual_router_mac = (known after apply)
}

# module.vcn.oci_core_subnet.this[1] will be created
+ resource "oci_core_subnet" "this" {
+ availability_domain = "okVf:EU-FRANKFURT-1-AD-2"
+ cidr_block = "192.168.0.16/28"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ dhcp_options_id = (known after apply)
+ display_name = "Default Subnet okVf:EU-FRANKFURT-1-AD-2"
+ dns_label = "subnet2"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ ipv6virtual_router_ip = (known after apply)
+ prohibit_public_ip_on_vnic = (known after apply)
+ route_table_id = (known after apply)
+ security_list_ids = (known after apply)
+ state = (known after apply)
+ subnet_domain_name = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
+ virtual_router_ip = (known after apply)
+ virtual_router_mac = (known after apply)
}

# module.vcn.oci_core_subnet.this[2] will be created
+ resource "oci_core_subnet" "this" {
+ availability_domain = "okVf:EU-FRANKFURT-1-AD-3"
+ cidr_block = "192.168.0.32/28"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ dhcp_options_id = (known after apply)
+ display_name = "Default Subnet okVf:EU-FRANKFURT-1-AD-3"
+ dns_label = "subnet3"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ ipv6virtual_router_ip = (known after apply)
+ prohibit_public_ip_on_vnic = (known after apply)
+ route_table_id = (known after apply)
+ security_list_ids = (known after apply)
+ state = (known after apply)
+ subnet_domain_name = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
+ virtual_router_ip = (known after apply)
+ virtual_router_mac = (known after apply)
}

# module.vcn.oci_core_vcn.this will be created
+ resource "oci_core_vcn" "this" {
+ cidr_block = "192.168.0.0/25"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ default_dhcp_options_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_list_id = (known after apply)
+ defined_tags = (known after apply)
+ display_name = "TEST-FK-VCN"
+ dns_label = "vcn"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ is_ipv6enabled = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ vcn_domain_name = (known after apply)
}

Plan: 6 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.

Apply:

mattia_ros@cloudshell:vcn_default (eu-frankfurt-1)$ terraform apply
module.vcn.data.oci_identity_availability_domains.this: Refreshing state...

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:

# module.vcn.oci_core_default_route_table.this will be created
+ resource "oci_core_default_route_table" "this" {
+ defined_tags = (known after apply)
+ display_name = (known after apply)
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ manage_default_resource_id = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)

+ route_rules {
+ cidr_block = (known after apply)
+ description = (known after apply)
+ destination = "0.0.0.0/0"
+ destination_type = (known after apply)
+ network_entity_id = (known after apply)
}
}

# module.vcn.oci_core_internet_gateway.this will be created
+ resource "oci_core_internet_gateway" "this" {
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ display_name = (known after apply)
+ enabled = true
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
}

# module.vcn.oci_core_subnet.this[0] will be created
+ resource "oci_core_subnet" "this" {
+ availability_domain = "okVf:EU-FRANKFURT-1-AD-1"
+ cidr_block = "192.168.0.0/28"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ dhcp_options_id = (known after apply)
+ display_name = "Default Subnet okVf:EU-FRANKFURT-1-AD-1"
+ dns_label = "subnet1"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ ipv6virtual_router_ip = (known after apply)
+ prohibit_public_ip_on_vnic = (known after apply)
+ route_table_id = (known after apply)
+ security_list_ids = (known after apply)
+ state = (known after apply)
+ subnet_domain_name = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
+ virtual_router_ip = (known after apply)
+ virtual_router_mac = (known after apply)
}

# module.vcn.oci_core_subnet.this[1] will be created
+ resource "oci_core_subnet" "this" {
+ availability_domain = "okVf:EU-FRANKFURT-1-AD-2"
+ cidr_block = "192.168.0.16/28"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ dhcp_options_id = (known after apply)
+ display_name = "Default Subnet okVf:EU-FRANKFURT-1-AD-2"
+ dns_label = "subnet2"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ ipv6virtual_router_ip = (known after apply)
+ prohibit_public_ip_on_vnic = (known after apply)
+ route_table_id = (known after apply)
+ security_list_ids = (known after apply)
+ state = (known after apply)
+ subnet_domain_name = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
+ virtual_router_ip = (known after apply)
+ virtual_router_mac = (known after apply)
}

# module.vcn.oci_core_subnet.this[2] will be created
+ resource "oci_core_subnet" "this" {
+ availability_domain = "okVf:EU-FRANKFURT-1-AD-3"
+ cidr_block = "192.168.0.32/28"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ defined_tags = (known after apply)
+ dhcp_options_id = (known after apply)
+ display_name = "Default Subnet okVf:EU-FRANKFURT-1-AD-3"
+ dns_label = "subnet3"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ ipv6virtual_router_ip = (known after apply)
+ prohibit_public_ip_on_vnic = (known after apply)
+ route_table_id = (known after apply)
+ security_list_ids = (known after apply)
+ state = (known after apply)
+ subnet_domain_name = (known after apply)
+ time_created = (known after apply)
+ vcn_id = (known after apply)
+ virtual_router_ip = (known after apply)
+ virtual_router_mac = (known after apply)
}

# module.vcn.oci_core_vcn.this will be created
+ resource "oci_core_vcn" "this" {
+ cidr_block = "192.168.0.0/25"
+ compartment_id = "ocid1.compartment.oc1..aaaaaaaan2lhk5eqy2hvum45ahjsvgs2sz7x72ur5kw4euwe6my2226mk5ia"
+ default_dhcp_options_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_list_id = (known after apply)
+ defined_tags = (known after apply)
+ display_name = "TEST-FK-VCN"
+ dns_label = "vcn"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_block = (known after apply)
+ ipv6public_cidr_block = (known after apply)
+ is_ipv6enabled = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ vcn_domain_name = (known after apply)
}

Plan: 6 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

module.vcn.oci_core_vcn.this: Creating...
module.vcn.oci_core_vcn.this: Creation complete after 0s [id=ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaavyxeuaqaavuidjkp2un5v7fgodw63pytlkaxvrfs5coucgfqmgfa]
module.vcn.oci_core_internet_gateway.this: Creating...
module.vcn.oci_core_subnet.this[2]: Creating...
module.vcn.oci_core_subnet.this[1]: Creating...
module.vcn.oci_core_subnet.this[0]: Creating...
module.vcn.oci_core_subnet.this[0]: Creation complete after 0s [id=ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaa2feksp66yxjrj2twxypjbuk5blefju2ghkk34z4hvex57obkxzqa]
module.vcn.oci_core_subnet.this[2]: Creation complete after 1s [id=ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaadqbslze7krqigudqg6ajhxhxddpmhvaottievimyk6jdxz754pta]
module.vcn.oci_core_subnet.this[1]: Creation complete after 1s [id=ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaaoqrhcrv743sdt6norse7wql7rmin3ca6amoigqonvsejuoavnjtq]
module.vcn.oci_core_internet_gateway.this: Creation complete after 2s [id=ocid1.internetgateway.oc1.eu-frankfurt-1.aaaaaaaau4sdjijm4b3miu2hwf5lcbkyb7eaea62qg7dpaar2udn4u4zhfnq]
module.vcn.oci_core_default_route_table.this: Creating...
module.vcn.oci_core_default_route_table.this: Creation complete after 0s [id=ocid1.routetable.oc1.eu-frankfurt-1.aaaaaaaa5ag3j4kbkb763c3qorcowy5r3swyileytlyhagkv7mqragxysgma]

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

Outputs:

default_dhcp_options_id = ocid1.dhcpoptions.oc1.eu-frankfurt-1.aaaaaaaabzs2tgdpnq6jrd2p67lks44qovk272uxuoi3kgciib62fyflgyja
default_route_table_id = ocid1.routetable.oc1.eu-frankfurt-1.aaaaaaaa5ag3j4kbkb763c3qorcowy5r3swyileytlyhagkv7mqragxysgma
default_security_list_id = ocid1.securitylist.oc1.eu-frankfurt-1.aaaaaaaadm7oi73fwjx2kiiqbc7ucsuvqcmxfjis27at4p3tyhuopod5tqoq
internet_gateway_id = ocid1.internetgateway.oc1.eu-frankfurt-1.aaaaaaaau4sdjijm4b3miu2hwf5lcbkyb7eaea62qg7dpaar2udn4u4zhfnq
subnet_ids = [
"ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaa2feksp66yxjrj2twxypjbuk5blefju2ghkk34z4hvex57obkxzqa",
"ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaaoqrhcrv743sdt6norse7wql7rmin3ca6amoigqonvsejuoavnjtq",
"ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaadqbslze7krqigudqg6ajhxhxddpmhvaottievimyk6jdxz754pta",
]
vcn_id = ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaavyxeuaqaavuidjkp2un5v7fgodw63pytlkaxvrfs5coucgfqmgfa

Now let’s check the local terraform state file:

mattia_ros@cloudshell:vcn_default (eu-frankfurt-1)$ cat .terraform/terraform.tfstate 
{
"version": 3,
"serial": 1,
"lineage": "1250a1d2-3e20-124b-7c25-524f67566052",
"backend": {
"type": "s3",
"config": {
"access_key": null,
"acl": null,
"assume_role_policy": null,
"bucket": "tf-fk-test-01",
"dynamodb_endpoint": null,
"dynamodb_table": null,
"encrypt": null,
"endpoint": "https://mytenancy.compat.objectstorage.eu-frankfurt-1.oraclecloud.com",
"external_id": null,
"force_path_style": true,
"iam_endpoint": null,
"key": "terraform/state/oci/vcn/testVCN/terraform.tfstate",
"kms_key_id": null,
"lock_table": null,
"max_retries": null,
"profile": null,
"region": "eu-frankfurt-1",
"role_arn": null,
"secret_key": null,
"session_name": null,
"shared_credentials_file": null,
"skip_credentials_validation": true,
"skip_get_ec2_platforms": null,
"skip_metadata_api_check": true,
"skip_region_validation": true,
"skip_requesting_account_id": null,
"sse_customer_key": null,
"sts_endpoint": null,
"token": null,
"workspace_key_prefix": null
},
"hash": 1758364997
},
"modules": [
{
"path": [
"root"
],
"outputs": {},
"resources": {},
"depends_on": []
}
]
}

And let’s check the Object storage bucket:

oci os object list -bn tf-fk-test-01 --output=table
+------+--------------------------+---------------------------------------------------+-------+----------------------------------+---------------+
| etag | md5 | name | size | time-created | time-modified |
+------+--------------------------+---------------------------------------------------+-------+----------------------------------+---------------+
| None | PRXsobIN......efUorHfg== | terraform/state/oci/vcn/testVCN/terraform.tfstate | 14161 | 2020-05-08T18:43:19.428000+00:00 | None |
+------+--------------------------+---------------------------------------------------+-------+----------------------------------+---------------+
prefixes: []

.. and we’re done, you have configured terraform to store state files remotely on OCI.

If you want to use the same pattern outside the OCI cloud shell you will need to configure the oci provider to use the usual API key/fingerprint combo

Have Fun!

Mattia

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s