An experimental Crossplane provider for Terraform. Use this provider to define new Crossplane Composite Resources (XRs) that are composed of a mix of 'native' Crossplane managed resources and your existing Terraform modules.
The Terraform provider adds support for a Workspace
managed resource that
represents a Terraform workspace. The configuration of each workspace may be
either fetched from a remote source (e.g. git), or simply specified inline.
apiVersion: tf.crossplane.io/v1alpha1
kind: Workspace
metadata:
name: example-inline
annotations:
# The terraform workspace will be named 'coolbucket'. If you omitted this
# annotation it would be derived from metadata.name - i.e. 'example-inline'.
crossplane.io/external-name: coolbucket
spec:
forProvider:
# For simple cases you can use an inline source to specify the content of
# main.tf as opaque, inline HCL.
source: Inline
module: |
// All outputs are written to the connection secret. Non-sensitive outputs
// are stored as string values in the status.atProvider.outputs object.
output "url" {
value = google_storage_bucket.example.self_link
}
resource "random_id" "example" {
byte_length = 4
}
// The google provider and remote state are configured by the provider
// config - see examples/providerconfig.yaml.
resource "google_storage_bucket" "example" {
name = "crossplane-example-${terraform.workspace}-${random_id.example.hex}"
}
writeConnectionSecretToRef:
namespace: default
name: terraform-workspace-example-inline
apiVersion: tf.crossplane.io/v1alpha1
kind: Workspace
metadata:
name: example-remote
annotations:
crossplane.io/external-name: myworkspace
spec:
forProvider:
# Use any module source supported by terraform init -from-module.
source: Remote
module: https://github.com/crossplane/tf
# Variables can be specified inline, or loaded from a ConfigMap or Secret.
vars:
- key: region
value: us-west-1
varFiles:
- source: SecretKey
secretKeyRef:
namespace: default
name: terraform
key: example.tfvar.json
# All Terraform outputs are written to the connection secret.
writeConnectionSecretToRef:
namespace: default
name: terraform-workspace-example-inline
We highly encourage to use a declarative way of provider installation:
kubectl apply -f examples/install.yaml
Notice that in this example Provider resource is referencing ControllerConfig with debug enabled.
To securely propagate git credentials create a git-credentials
secret in git credentials store format.
cat .git-credentials
https://<user>:<token>@github.com
kubectl create secret generic git-credentials --from-file=.git-credentials
Reference it in ProviderConfig.
apiVersion: tf.crossplane.io/v1alpha1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
- filename: .git-credentials # use exactly this filename
source: Secret
secretRef:
namespace: crossplane-system
name: git-credentials
key: .git-credentials
...
Standard .git-credentials
filename is important to keep so provider-terraform
controller will be able to automatically pick it up.
Non-sensitive outputs are mapped to the status.atProvider.outputs section as strings so they can be referenced by the Composition. Strings, numbers and booleans can be referenced directly in Compositions and can be used in the convert transform if type conversion is needed. Tuple and object outputs will be available in the corresponding JSON form. This is required because undefined object attributes are not specified in the Workspace CRD and so will be sanitized before the status is stored in the database.
That means that any output values required for use in the Composition must be published explicitly and individually, and they cannot be referenced inside a tuple or object.
For example, the following terraform outputs:
output "string" {
value = "bar"
sensitive = false
}
output "number" {
value = 1.9
sensitive = false
}
output "object" {
// This will be a JSON string - the key/value pairs are not accessible
value = {"a": 3, "b": 2}
sensitive = false
}
output "tuple" {
// This will be a JSON string - the elements will not be accessible
value = ["foo", "bar"]
sensitive = false
}
output "bool" {
value = false
sensitive = false
}
output "sensitive" {
value = "SENSITIVE"
sensitive = true
}
Appear in the corresponding outputs section as:
status:
atProvider:
outputs:
bool: "false"
number: "1.9"
object: '{"a":3,"b":2}'
string: bar
tuple: '["foo", "bar"]'
Note that the "sensitive" output is not included in status.atProvider.outputs
Additional arguments can be passed to the Terraform plan, apply, and destroy commands by specifying the planArgs, applyArgs and destroyArgs options.
For example:
apiVersion: tf.crossplane.io/v1alpha1
kind: Workspace
metadata:
name: example-args
spec:
forProvider:
# Run the terraform init command with -upgrade=true to upgrade any stored providers
initArgs:
- -upgrade=true
# Run the terraform plan command with the -parallelism=2 argument
planArgs:
- -parallelism=2
# Run the terraform apply command with the -target=specificresource argument
applyArgs:
- -target=specificresource
# Run the terraform destroy command with the -refresh=false argument
destroyArgs:
- -refresh=false
# Use any module source supported by terraform init -from-module.
source: Remote
module: https://github.com/crossplane/tf
# All Terraform outputs are written to the connection secret.
writeConnectionSecretToRef:
namespace: default
name: terraform-workspace-example-inline
This will cause the terraform init command to be run with the "-upgrade=true" argument, the terraform plan command to be run with the -parallelism=2 argument, the terraform apply command to be run with the -target=specificresource argument, and the terraform destroy command to be run with the -refresh=false argument.
Note that by default the terraform init command is run with the "-input=false", and "-no-color" arguments, the terraform apply and destroy commands are run with the "-no-color", "-auto-approve", and "-input=false" arguments, and the terraform plan command is run with the "-no-color", "-input=false", and "-detailed-exitcode" arguments. Arguments specified in applyArgs, destroyArgs and planArgs will be added to these default arguments.
- You must either use remote state or ensure the provider container's
/tf
directory is not lost.provider-terraform
does not persist state; consider using the Kubernetes remote state backend. - If the module takes longer than the supplied
--timeout
to apply the underlyingterraform
process will be killed. You will potentially lose state and leak resources. - The provider won't emit an event until after it has successfully applied the Terraform module, which can take a long time.