Terraform and OpenTofu provider for Apache Paimon

Clone this repo:
  1. 87020ce Bump golang.org/x/crypto from 0.51.0 to 0.52.0 (#15) by dependabot[bot] · 6 days ago main
  2. fcf3117 Bump zizmorcore/zizmor-action from 0.6.2 to 0.6.3 (#22) by dependabot[bot] · 6 days ago
  3. 2f72281 Bump apache/infrastructure-actions/allowlist-check from 69afc125e535c4c41e7f1b7470f583087e0f344b to 70a0d87acc3b1103c9377ed325b82b482e08b56f (#18) by dependabot[bot] · 6 days ago
  4. 0cd3f38 Align Paimon API contracts and harden provider recovery (#17) by Jingsong Lee · 6 days ago
  5. 0646712 Harden provider lifecycle and release readiness (#14) by Jingsong Lee · 12 days ago

Paimon Terraform Provider

This project integrates Terraform and OpenTofu with an Apache Paimon REST Catalog. It follows the provider shape established by apache/terraform-provider-iceberg, but talks directly to Paimon's language-neutral REST Catalog API instead of embedding a JVM client.

Releases use signed Apache release candidates. See the release guide for the source-vote and Registry workflow, including verification of a published version before installation.

Supported objects

Resources:

  • paimon_database creates, reads, updates, imports, and drops databases.
  • paimon_table creates, reads, imports, evolves supported table fields, updates options/comments, and drops managed tables.
  • paimon_permission grants, reads, imports, replaces mutable assignment content, and revokes direct catalog permissions.
  • paimon_row_filter manages one principal's row filter on a table.
  • paimon_column_mask manages one principal's mask on a table column.

Data sources:

  • paimon_database reads a database and its server metadata.
  • paimon_table reads a table schema, keys, options, and server metadata.

Example

terraform {
  required_providers {
    paimon = {
      source = "apache/paimon"
    }
  }
}

provider "paimon" {
  uri       = "http://localhost:8080"
  warehouse = "default"

  token_provider = "bear"
  token          = var.paimon_token
}

resource "paimon_database" "analytics" {
  name = "analytics"
  options = {
    owner = "data-platform"
  }
}

resource "paimon_table" "events" {
  database = paimon_database.analytics.name
  name     = "events"

  fields = [
    {
      name     = "event_id"
      type     = "BIGINT"
      nullable = false
    },
    {
      name = "event_time"
      type = "TIMESTAMP(3)"
    },
    {
      name = "payload"
      type = "STRING"
    }
  ]

  partition_keys = []
  options = {
    "primary-key" = "event_id"
    "bucket"      = "4"
  }
  comment = "Events managed by Terraform"
}

resource "paimon_permission" "analyst_read" {
  resource_type = "TABLE"
  database      = paimon_table.events.database
  table         = paimon_table.events.name
  access        = "SELECT"
  principal     = "role:analyst"
}

Lifecycle and safety

Only the REST metastore is in scope. Filesystem, Hive, and JDBC catalogs are not accessed directly because Terraform needs a stable remote control-plane contract; Paimon's REST OpenAPI provides that contract.

Permission, row-filter, and column-mask resources use Paimon's experimental REST management API. Principal lifecycle and group or role membership remain server responsibilities.

Table replacements are blocked unless allow_replacement = true. Protect retained production data with Terraform's prevent_destroy lifecycle rule as shown in the production example. Row-filter and column-mask content updates require allow_non_atomic_update = true during a maintenance window because the REST API cannot update a policy atomically. Import existing policies explicitly.

The production validation guide distinguishes local protocol coverage from real REST/DLF and query-engine validation.

Import

terraform import paimon_database.analytics analytics
terraform import paimon_table.events analytics.events
terraform import paimon_permission.analyst_read \
  'resource_type=TABLE&database=analytics&table=events&access=SELECT&principal=role%3Aanalyst'

Development

Use the Go version specified in go.mod or a newer compatible version.

make check
make check-docs
make test-acceptance

make check includes the documentation schema check. make check-docs runs it on its own: every registered provider, resource, and data-source field must have a reference entry with its actual type, required/optional/computed mode, and sensitive flag. Update the reference descriptions when changing defaults, validation, or lifecycle behavior; those semantics still require review.

See docs/index.md for the provider configuration and links to the complete resource and data-source field references.

See the API contract for the current resource model and experimental management boundary. Primary keys use options["primary-key"]; primary_keys is a computed output.