ARTIFACTORY: How to configure Terraform repositories in Artifactory

Tatarao Vana
2023-01-22 11:07

JFrog provides a fully-fledged Terraform repository solution giving you full control of your deployment and resolution process of Terraform Modules, Providers, and Backend packages from Artifactory 7.38.4 version onwards. 

In this knowledge base article, we will discuss the following topics. 

  1. Deploying modules and providers to the Terraform repository and resolving them.
  2. Troubleshooting the Terraform issues

Deploying modules and providers to the Terraform repository and resolving them

Deploying modules to Artifactory:
1. Create a new Terraform module by adding your contents to the tf file. Below is a sample of a 
new directory followed by a “terraform init” command. $ cat main.tf
terraform {
 required_version = ">= 0.12.26"
}
output "hello_world" {
 value = "Hello, World!"
}

2. Navigate to the newly created directory and perform the following command to pack its contents into a zip file and name it according to the module version:$ zip -r 1.0.0.zip .  
  adding: main.tf (deflated 9%)

3. Deploy the module using the cURL command found in the “Set Me Up” page as seen below:
Please note that my virtual repository name is test-terraform which consists of the local repository test-terraform-modules-local. 
$ curl -utestuser:testpassword -XPUT "https://jpd.local/artifactory/test-terraform/myns/mymodule/myprovider/1.0.0.zip" -T 1.0.0.zip{
  "repo" : "test-terraform-modules-local",
  "path" : "/myns/mymodule/myprovider/1.0.0.zip",
  "created" : "2022-09-29T07:06:57.015Z",
  "createdBy" : "testuser",
  "downloadUri" : "https://jpd.local/artifactory/test-terraform-modules-local/myns/mymodule/myprovider/1.0.0.zip",
  "mimeType" : "application/zip",
  "size" : "253",
  "checksums" : {
    "sha1" : "a1f8d4026ddad3026278b072b3d476e4b50bf5de",
    "md5" : "5f7fb91cd0849148a15ebffe48958dcf",
    "sha256" : "a2bc2961618ab39dc18a559e7dccf58f2b83ebc70446dcdd5cc7dcc0f9f2f9a5"
  },
  "originalChecksums" : {
    "sha256" : "a2bc2961618ab39dc18a559e7dccf58f2b83ebc70446dcdd5cc7dcc0f9f2f9a5"
  },
  "uri" : "https://jpd.local/artifactory/test-terraform-modules-local/myns/mymodule/myprovider/1.0.0.zip"
}

4. In other Terraform project (client machine for example), consume the published module using the following snippet:$ cat main.tf 
module "mymodule" {
    source  = "jpd.local/test-terraform__myns/mymodule/myprovider"
}

5. Execute Terraform login command.$ terraform login jfrog.local
6. Execute the Terraform init command to resolve it.$ terraform init
Initializing modules...
Downloading jpd.local/test-terraform__myns/mymodule/myprovider 1.0.0 for mymodule...
- mymodule in .terraform/modules/mymodule
Initializing the backend...
Initializing provider plugins...
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.

Deploying Terraform provider artifact to Artifactory:

      Create a Terraform provider repository. According to our set-me-up instructions, we have to upload a Terraform provider artifact to Artifactory.$ curl -u<USERNAME>:<PASSWORD> -XPUT "https://jfrog.local/artifactory/test-terraform-provider-local/<NAMESPACE>/<PROVIDER-NAME>/<VERSION>/terraform-provider-<PROVIDER-NAME>_<VERSION>_<OS>_<ARCH>.zip" -T <PATH_TO_FILE>
Example:$curl -utestuser:testpass -XPUT "https://jfrog.local/artifactory/test-terraform-provider-local/testnamespace/testprovider/1.1.0/terraform-provider-testprovider_1.1.0_darwin_amd64.zip" -T  ~/Downloads/terraform-provider-hashicups.zip
{
  "repo" : "test-terraform-provider-local",
  "path" : "/testnamespace/testprovider/1.1.0/terraform-provider-testprovider_1.1.0_darwin_amd64.zip",
  "created" : "2022-10-25T06:14:36.099Z",
  "createdBy" : "testuser",
  "downloadUri" : "https://jfrog.local/artifactory/test-terraform-provider-local/testnamespace/testprovider/1.1.0/terraform-provider-testprovider_1.1.0_darwin_amd64.zip",
  "mimeType" : "application/zip",
  "size" : "10498660",
  "checksums" : {
    "sha1" : "c691c8add753ed1ce71d52cb8c613b97088766bd",
    "md5" : "3c56559e8a51d6669ae59f5fa8cb107b",
    "sha256" : "d7658715b589545a0ebccf26fadb6f6be85d739e329de8e61d5ef4bff0692299"
  },
  "originalChecksums" : {
    "sha256" : "d7658715b589545a0ebccf26fadb6f6be85d739e329de8e61d5ef4bff0692299"
  },
  "uri" : "https://jfrog.local/artifactory/test-terraform-provider-local/testnamespace/testprovider/1.1.0/terraform-provider-testprovider_1.1.0_darwin_amd64.zip"
}

Later, create the following main.tf file as follows. cat main.tf 
terraform {
  required_providers {
    testprovider = {
      version = "1.1.0"
      source = "testnamespace/testprovider"
    }
  }
}

Here is the terraform.rc file content. cat ~/.terraformrc 
provider_installation {
    direct {
        exclude = ["registry.terraform.io/*/*"]
    }
    network_mirror {
        url = "https://jfrog.local/artifactory/api/terraform/test-terraform-provider-local/providers/"
    }
}

Execute the Terraform login.$ terraform login jfrog.local
Execute the terraform init$ TF_LOG=DEBUG terraform init
2022-10-25T11:45:12.389+0530 [INFO]  Terraform version: 1.3.1
2022-10-25T11:45:12.389+0530 [INFO]  Go runtime version: go1.19.1
2022-10-25T11:45:12.389+0530 [INFO]  CLI args: []string{"terraform", "init"}
2022-10-25T11:45:12.389+0530 [INFO]  Loading CLI configuration from /Users/testuserraov/.terraformrc
2022-10-25T11:45:12.390+0530 [INFO]  Loading CLI configuration from /Users/testuserraov/.terraform.d/credentials.tfrc.json
2022-10-25T11:45:12.392+0530 [INFO]  CLI command args: []string{"init"}
Initializing the backend...
Initializing provider plugins...
- Finding testnamespace/testprovider versions matching "1.1.0"...
- Installing testnamespace/testprovider v1.1.0...

Troubleshooting the Terraform issues

Kindly enable the debugger logger in the$JFROG_HOME/artifactory/var/etc/artifactory/logback.xmlfile and does not require a restart for log changes to take effect:
 <appender name="terraform" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.dir}/artifactory-terraform.log</File>
<rollingPolicy class="org.jfrog.common.logging.logback.rolling.FixedWindowWithDateRollingPolicy">
<FileNamePattern>${log.dir.archived}/artifactory-terraform.%i.log.gz</FileNamePattern>
<maxIndex>10</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>25MB</MaxFileSize>
</triggeringPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.jfrog.common.logging.logback.layout.BackTracePatternLayout">
<pattern>%date{yyyy-MM-ddTHH:mm:ss.SSS, UTC}Z [jfrt ] [%-5p] [%-16X{uber-trace-id}] [%-30.30(%c{3}:%L)] [%-20.20thread] - %m%n</pattern>
</layout>
</encoder>
</appender>
<logger name="org.artifactory.addon.terraform" additivity="false">
<level value="debug"/>
<appender-ref ref="terraform"/>
</logger>

Please note that the loggers are resource-intensive. Hence, remove them once the issue is reproduced. 

On the client side, enable Terraform client debug using the command:export TF_LOG=TRACE