Skip to content

Using Functions

Provider functions enable custom transformations and computations in your Terraform configurations. This guide shows how to use functions effectively.

๐Ÿค– AI-Generated Content

This documentation was generated with AI assistance and is still being audited. Some, or potentially a lot, of this information may be inaccurate. Learn more.

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