Using Functions¶
Provider functions enable custom transformations and computations in your Terraform configurations. This guide shows how to use functions effectively.
What are Provider Functions?¶
Functions are callable operations that transform input into output without managing infrastructure. They're useful for: - Data transformation (JSON, strings, numbers) - Hash computation - Encoding/decoding operations - Custom business logic
Basic Usage¶
Call a provider function in Terraform:
terraform {
required_providers {
mycloud = {
source = "example.com/mycloud"
}
}
}
output "hashed_value" {
value = provider::mycloud::hash("hello world")
}
Common Patterns¶
String Transformation¶
locals {
uppercase_name = provider::mycloud::to_upper(var.server_name)
slugified = provider::mycloud::slugify("My Server Name")
}
JSON Manipulation¶
locals {
config_json = jsonencode({
name = "app"
port = 8080
})
transformed = provider::mycloud::jq_transform(
local.config_json,
".name + \"-v2\""
)
}
Hash Generation¶
resource "mycloud_api_key" "app" {
name = "app-key"
secret_hash = provider::mycloud::sha256(var.api_secret)
}
Encoding/Decoding¶
locals {
encoded_data = provider::mycloud::base64_encode("sensitive data")
decoded_data = provider::mycloud::base64_decode(var.encoded_config)
}
Using Functions with Resources¶
Functions integrate seamlessly with resource configuration:
resource "mycloud_server" "app" {
name = provider::mycloud::slugify(var.server_name)
environment = {
CONFIG_HASH = provider::mycloud::md5(file("config.json"))
}
tags = {
fingerprint = provider::mycloud::sha256(var.deployment_id)
}
}
Function Composition¶
Chain functions for complex transformations:
locals {
# Encode JSON, then base64 encode the result
encoded_config = provider::mycloud::base64_encode(
jsonencode(var.config)
)
# Transform JSON with JQ, then hash the result
config_hash = provider::mycloud::sha256(
provider::mycloud::jq_transform(
jsonencode(var.config),
"sort_keys"
)
)
}
Comparison with Built-in Functions¶
| Aspect | Provider Functions | Built-in Functions |
|---|---|---|
| Definition | Defined by providers | Built into Terraform |
| Namespace | provider::name::function |
Direct call (e.g., length()) |
| Scope | Provider-specific logic | General-purpose |
| Examples | provider::mycloud::hash |
length, concat, merge |
Use built-in functions when possible; use provider functions for domain-specific operations.
Best Practices¶
1. Use for Domain Logic¶
Provider functions should encapsulate provider-specific logic:
# Good: Provider-specific validation
resource "mycloud_server" "app" {
name = provider::mycloud::validate_name(var.server_name)
}
# Avoid: Use built-in functions for generic operations
# Bad:
value = provider::mycloud::to_upper(var.name)
# Good:
value = upper(var.name)
2. Keep Functions Pure¶
Functions should be deterministic (same input = same output):
# Good: Pure function
hash = provider::mycloud::sha256("data")
# Avoid: Functions that depend on external state
# (Use data sources for this instead)
3. Document Function Usage¶
Add comments explaining function purpose:
locals {
# Hash server configuration for change detection
# Uses SHA-256 to ensure consistent length
config_fingerprint = provider::mycloud::sha256(
jsonencode(var.server_config)
)
}
Examples from pyvider-components¶
The pyvider-components repository includes function examples:
- String functions (
upper,lower,slugify) - Numeric functions (
add,multiply,round) - JQ transformation functions
- Hash and encoding functions
Real-World Use Cases¶
Configuration Fingerprinting¶
resource "mycloud_deployment" "app" {
name = "app-deployment"
config_hash = provider::mycloud::sha256(
jsonencode({
version = var.app_version
environment = var.environment
replicas = var.replica_count
})
)
# Triggers redeployment when config changes
triggers = {
config = provider::mycloud::sha256(
file("${path.module}/config.yaml")
)
}
}
Data Transformation¶
locals {
# Transform API response using JQ
processed_data = provider::mycloud::jq_transform(
data.http.api_response.body,
".items | map(.name) | sort"
)
}
Name Sanitization¶
resource "mycloud_bucket" "data" {
# Ensure bucket name meets provider requirements
name = provider::mycloud::sanitize_bucket_name(
"${var.project}-${var.environment}-data"
)
}
Debugging Functions¶
Test function output using terraform console:
$ terraform console
> provider::mycloud::hash("test")
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
> provider::mycloud::slugify("My Server Name")
"my-server-name"
Performance Considerations¶
Functions execute during planning:
# Evaluated once during plan
locals {
hash = provider::mycloud::sha256(file("large-file.json"))
}
# All resources use cached value
resource "mycloud_server" "web1" {
config_hash = local.hash
}
resource "mycloud_server" "web2" {
config_hash = local.hash
}
See Also¶
- Creating Functions - How to implement provider functions
- Best Practices - Provider development patterns
- Pyvider Components - Working examples