Skip to content

Use TF-controller with GitOps dependency management

TF-controller supports GitOps dependency management. The GitOps dependency management feature is based on the similar technique implemented in the Kustomization controller of Flux.

This means that you can use TF-controller to provision resources that depend on other resources at the GitOps level. For example, you can use TF-controller to provision an S3 bucket, and then use TF-controller to provision another resource to configure ACL for that bucket.

GitOps dependency management is different from Terraform's HCL dependency management in the way that it is not based on Terraform's mechanism, which is controlled by the Terraform binary. Instead, it is implemented at the controller level, which means that each Terraform module is reconciled and can be managed independently, while still being able to depend on other modules.

Create a Terraform object

Similar to the same feature in the Kustomization controller, the dependency management feature is enabled by setting the dependsOn field in the Terraform object. The dependsOn field is a list of Terraform objects.

When the dependency is not satisfied, the Terraform object will be in the Unknown state, and it will be retry again every spec.retryInterval. The retry interval is same as the spec.interval by default, and it can be configured separately by setting the spec.retryInterval field.

First, create a Terraform object to provision the S3 bucket, name it aws-s3-bucket. The S3 bucket is provisioned by the Terraform module aws_s3_bucket in the OCI image aws-package. It is configured to use the auto-apply mode, and write outputs to the secret aws-s3-bucket-outputs.

---
apiVersion: infra.contrib.fluxcd.io/v1alpha2
kind: Terraform
metadata:
  name: aws-s3-bucket
  namespace: flux-system
spec:
  path: aws_s3_bucket
  values:
    bucket: my-tf-controller-test-bucket
    tags:
      Environment: Dev
      Name: My bucket
  sourceRef:
    kind: OCIRepository
    name: aws-package
  approvePlan: auto
  interval: 2m
  destroyResourcesOnDeletion: true
  writeOutputsToSecret:
    name: aws-s3-bucket-outputs
    outputs:
    - arn
    - bucket
  runnerPodTemplate:
    spec:
      envFrom:
      - secretRef:
          name: aws-credentials

Second, create a Terraform object to configure ACL for the S3 bucket, name it aws-s3-bucket-acl. The ACL is provisioned by the Terraform module aws_s3_bucket_acl, also from the OCI image aws-package-v4.33.0.

In the dependsOn field, specify the Terraform object that provisions the S3 bucket. This means that the ACL will be configured only after the S3 bucket is provisioned, and has its outputs Secret written. We can read the outputs of the S3 bucket from the Secret aws-s3-bucket-outputs, by specifying the spec.readInputsFromSecrets field. The spec.readInputsFromSecrets field is a list of Secret objects. Its name field is the name of the Secret, and its as field is the name of variable that can be used in the spec.values block.

For example, the spec.values.bucket field in the aws-s3-bucket-acl Terraform object is set to ${{ .aws_s3_bucket.bucket }}.

Please note that we use ${{ and }} as the delimiters for the variable name, instead of the Helm default ones, {{ and }}.

---
apiVersion: infra.contrib.fluxcd.io/v1alpha2
kind: Terraform
metadata:
  name: aws-s3-bucket-acl
  namespace: flux-system
spec:
  path: aws_s3_bucket_acl
  values:
    acl: private
    bucket: ${{ .aws_s3_bucket.bucket }}
  sourceRef:
    kind: OCIRepository
    name: aws-package
  approvePlan: auto
  interval: 3m
  dependsOn:
  - name: aws-s3-bucket
  readInputsFromSecrets:
  - name: aws-s3-bucket-outputs
    as: aws_s3_bucket
  runnerPodTemplate:
    spec:
      envFrom:
      - secretRef:
          name: aws-credentials

Avoid Kustomization controller's variable substitution

The Kustomization controller will substitute variables in the Terraform object, which will cause conflicts with the variable substitution in the GitOps dependency management feature. To avoid this, we need to add the kustomize.toolkit.fluxcd.io/substitute: disabled annotation to the Terraform object.

---
apiVersion: infra.contrib.fluxcd.io/v1alpha2
kind: Terraform
metadata:
  name: aws-s3-bucket-acl
  namespace: flux-system
  annotations:
    kustomize.toolkit.fluxcd.io/substitute: disabled
spec:
  path: aws_s3_bucket_acl
  values:
    acl: private
    bucket: ${{ .aws_s3_bucket.bucket }}
  sourceRef:
    kind: OCIRepository
    name: aws-package
  approvePlan: auto
  interval: 3m
  dependsOn:
  - name: aws-s3-bucket
  readInputsFromSecrets:
  - name: aws-s3-bucket-outputs
    as: aws_s3_bucket
  runnerPodTemplate:
    spec:
      envFrom:
      - secretRef:
          name: aws-credentials