spice-terraform

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Spice.ai Terraform Provider

Spice.ai Terraform Provider

Manage Spice.ai Cloud resources as infrastructure-as-code using the
spiceai/spiceai
Terraform provider. Supports apps, deployments, secrets, org members, and data sources for regions and runtime images.
使用
spiceai/spiceai
Terraform Provider将Spice.ai Cloud资源作为基础设施即代码进行管理。支持应用、部署、密钥、组织成员,以及用于区域和运行时镜像的数据源。

Provider Setup

提供商配置

hcl
terraform {
  required_providers {
    spiceai = {
      source  = "spiceai/spiceai"
      version = "~> 0.1"
    }
  }
}

provider "spiceai" {
  client_id     = var.spiceai_client_id
  client_secret = var.spiceai_client_secret
  # api_endpoint = "https://api.spice.ai"  # optional, this is the default
}
Requirements: Terraform >= 1.0 or OpenTofu >= 1.0
hcl
terraform {
  required_providers {
    spiceai = {
      source  = "spiceai/spiceai"
      version = "~> 0.1"
    }
  }
}

provider "spiceai" {
  client_id     = var.spiceai_client_id
  client_secret = var.spiceai_client_secret
  # api_endpoint = "https://api.spice.ai"  # 可选,默认值为该地址
}
要求: Terraform >= 1.0 或 OpenTofu >= 1.0

Authentication

身份验证

The provider uses OAuth 2.0 Client Credentials. Set credentials via:
  1. Provider block
    client_id
    and
    client_secret
    arguments
  2. Environment variables
    SPICEAI_CLIENT_ID
    and
    SPICEAI_CLIENT_SECRET
Create OAuth clients in the Spice.ai Portal: Settings > OAuth Clients.
bash
export SPICEAI_CLIENT_ID="your-client-id"
export SPICEAI_CLIENT_SECRET="your-client-secret"
terraform plan
该提供商使用OAuth 2.0客户端凭证。可通过以下方式设置凭证:
  1. 提供商块
    client_id
    client_secret
    参数
  2. 环境变量
    SPICEAI_CLIENT_ID
    SPICEAI_CLIENT_SECRET
在Spice.ai门户中创建OAuth客户端:设置 > OAuth客户端
bash
export SPICEAI_CLIENT_ID="your-client-id"
export SPICEAI_CLIENT_SECRET="your-client-secret"
terraform plan

Resources

资源

spiceai_app

spiceai_app

Manages a Spice.ai application.
hcl
data "spiceai_regions" "available" {}

resource "spiceai_app" "analytics" {
  name        = "analytics-app"
  cname       = data.spiceai_regions.available.default
  description = "Production analytics"
  visibility  = "private"
  replicas    = 2
  image_tag   = "1.5.0-models"

  spicepod = yamlencode({
    version = "v1"
    kind    = "Spicepod"
    name    = "analytics-app"
    datasets = [{
      from = "postgres:public.events"
      name = "events"
      params = {
        pg_host = "db.example.com"
        pg_user = "$${secrets:PG_USER}"
        pg_pass = "$${secrets:PG_PASS}"
      }
      acceleration = {
        enabled              = true
        engine               = "duckdb"
        refresh_check_interval = "5m"
      }
    }]
  })
}
Arguments:
ArgumentTypeRequiredNotes
name
stringYesMin 4 chars, alphanumeric + hyphens
cname
stringYesRegion identifier (from
spiceai_regions
)
description
stringNo
visibility
stringNo
public
or
private
(default:
private
)
spicepod
stringNoYAML or JSON spicepod configuration
image_tag
stringNoSpice runtime version tag
replicas
numberNo1-10
region
stringNoAWS region code
production_branch
stringNoGit branch for production deployments
node_group
stringNoKubernetes node group
storage_claim_size_gb
numberNoPersistent volume size in GB
Read-only attributes:
id
,
api_key
(sensitive),
created_at
管理Spice.ai应用。
hcl
data "spiceai_regions" "available" {}

resource "spiceai_app" "analytics" {
  name        = "analytics-app"
  cname       = data.spiceai_regions.available.default
  description = "生产环境分析"
  visibility  = "private"
  replicas    = 2
  image_tag   = "1.5.0-models"

  spicepod = yamlencode({
    version = "v1"
    kind    = "Spicepod"
    name    = "analytics-app"
    datasets = [{
      from = "postgres:public.events"
      name = "events"
      params = {
        pg_host = "db.example.com"
        pg_user = "$${secrets:PG_USER}"
        pg_pass = "$${secrets:PG_PASS}"
      }
      acceleration = {
        enabled              = true
        engine               = "duckdb"
        refresh_check_interval = "5m"
      }
    }]
  })
}
参数:
参数名称类型必填说明
name
字符串最少4个字符,仅支持字母、数字和连字符
cname
字符串区域标识符(来自
spiceai_regions
数据源)
description
字符串应用描述
visibility
字符串可见性,可选
public
private
(默认:
private
spicepod
字符串YAML或JSON格式的Spicepod配置
image_tag
字符串Spice运行时版本标签
replicas
数字副本数,范围1-10
region
字符串AWS区域代码
production_branch
字符串用于生产部署的Git分支
node_group
字符串Kubernetes节点组
storage_claim_size_gb
数字持久化卷大小(GB)
只读属性:
id
api_key
(敏感)、
created_at

spiceai_deployment

spiceai_deployment

Creates an immutable deployment for an app. Use
triggers
to auto-redeploy on config changes.
hcl
resource "spiceai_deployment" "current" {
  app_id         = spiceai_app.analytics.id
  commit_message = "Deploy analytics app"

  triggers = {
    spicepod  = spiceai_app.analytics.spicepod
    image_tag = spiceai_app.analytics.image_tag
    replicas  = spiceai_app.analytics.replicas
  }
}
Arguments:
ArgumentTypeRequiredNotes
app_id
stringYesApp ID to deploy
image_tag
stringNoOverride runtime image
replicas
numberNoOverride replicas (1-10)
debug
booleanNoEnable debug mode (default: false)
branch
stringNoGit branch for tracking
commit_sha
stringNoGit commit SHA
commit_message
stringNoDeployment description
Read-only attributes:
id
,
status
(
queued
|
in_progress
|
succeeded
|
failed
),
error_message
,
created_at
The
triggers
map causes Terraform to replace the deployment whenever any tracked value changes.
为应用创建不可变的部署。使用
triggers
在配置变更时自动重新部署。
hcl
resource "spiceai_deployment" "current" {
  app_id         = spiceai_app.analytics.id
  commit_message = "部署分析应用"

  triggers = {
    spicepod  = spiceai_app.analytics.spicepod
    image_tag = spiceai_app.analytics.image_tag
    replicas  = spiceai_app.analytics.replicas
  }
}
参数:
参数名称类型必填说明
app_id
字符串要部署的应用ID
image_tag
字符串覆盖运行时镜像
replicas
数字覆盖副本数(1-10)
debug
布尔值启用调试模式(默认:false)
branch
字符串用于跟踪的Git分支
commit_sha
字符串Git提交SHA值
commit_message
字符串部署描述
只读属性:
id
status
queued
|
in_progress
|
succeeded
|
failed
)、
error_message
created_at
triggers
映射会在任何跟踪值变更时触发Terraform替换现有部署。

spiceai_secret

spiceai_secret

Manages app secrets. Values are AES-256 encrypted at rest.
hcl
variable "secrets" {
  type      = map(string)
  sensitive = true
  default = {
    PG_USER       = "analytics"
    PG_PASS       = "secret123"
    OPENAI_API_KEY = "sk-..."
  }
}

resource "spiceai_secret" "app_secrets" {
  for_each = var.secrets

  app_id = spiceai_app.analytics.id
  name   = each.key
  value  = each.value
}
Arguments:
ArgumentTypeRequiredNotes
app_id
stringYes
name
stringYesStart with letter/underscore, alphanumeric +
_
value
stringYesSensitive. Must set manually after import (API masks values)
Read-only attributes:
id
管理应用密钥。值在静态存储时采用AES-256加密。
hcl
variable "secrets" {
  type      = map(string)
  sensitive = true
  default = {
    PG_USER       = "analytics"
    PG_PASS       = "secret123"
    OPENAI_API_KEY = "sk-..."
  }
}

resource "spiceai_secret" "app_secrets" {
  for_each = var.secrets

  app_id = spiceai_app.analytics.id
  name   = each.key
  value  = each.value
}
参数:
参数名称类型必填说明
app_id
字符串所属应用ID
name
字符串以字母或下划线开头,仅支持字母、数字和
_
value
字符串敏感值。导入后必须手动设置(API会屏蔽值内容)
只读属性:
id

spiceai_member

spiceai_member

Manages organization members by GitHub username.
hcl
variable "team" {
  type    = set(string)
  default = ["alice", "bob"]
}

resource "spiceai_member" "team" {
  for_each = var.team

  username = each.key
  roles    = ["member"]
}
Arguments:
ArgumentTypeRequiredNotes
username
stringYesGitHub username
roles
string[]NoDefault:
["member"]
. Options:
owner
,
member
,
billing
Read-only attributes:
user_id
Organization owners cannot be managed via Terraform.
通过GitHub用户名管理组织成员。
hcl
variable "team" {
  type    = set(string)
  default = ["alice", "bob"]
}

resource "spiceai_member" "team" {
  for_each = var.team

  username = each.key
  roles    = ["member"]
}
参数:
参数名称类型必填说明
username
字符串GitHub用户名
roles
字符串数组默认:
["member"]
。可选值:
owner
member
billing
只读属性:
user_id
组织所有者无法通过Terraform进行管理。

Data Sources

数据源

spiceai_regions

spiceai_regions

hcl
data "spiceai_regions" "available" {}
hcl
data "spiceai_regions" "available" {}

Use: data.spiceai_regions.available.default

使用方式:data.spiceai_regions.available.default

Use: data.spiceai_regions.available.regions[*].cname

使用方式:data.spiceai_regions.available.regions[*].cname


Returns `regions` list (each with `name`, `region`, `cname`, `provider`, `providerName`) and `default` region.

返回`regions`列表(每个包含`name`、`region`、`cname`、`provider`、`providerName`字段)和`default`默认区域。

spiceai_container_images

spiceai_container_images

hcl
data "spiceai_container_images" "stable" {
  channel = "stable"  # or "enterprise"
}
hcl
data "spiceai_container_images" "stable" {
  channel = "stable"  # 或 "enterprise"
}

Use: data.spiceai_container_images.stable.default

使用方式:data.spiceai_container_images.stable.default

Use: data.spiceai_container_images.stable.images[*].tag

使用方式:data.spiceai_container_images.stable.images[*].tag


Returns `images` list (each with `name`, `tag`, `channel`) and `default` tag.

返回`images`列表(每个包含`name`、`tag`、`channel`字段)和`default`默认标签。

spiceai_app (data)

spiceai_app (数据源)

hcl
data "spiceai_app" "existing" {
  id = 12345
}
Retrieves details of an existing app by ID.
hcl
data "spiceai_app" "existing" {
  id = 12345
}
通过ID检索现有应用的详细信息。

spiceai_apps

spiceai_apps

hcl
data "spiceai_apps" "all" {}
hcl
data "spiceai_apps" "all" {}

Filter in Terraform

在Terraform中过滤

locals { prod_apps = [for app in data.spiceai_apps.all.apps : app if app.visibility == "private"] }

Lists all apps in the organization.
locals { prod_apps = [for app in data.spiceai_apps.all.apps : app if app.visibility == "private"] }

列出组织中的所有应用。

spiceai_members

spiceai_members

hcl
data "spiceai_members" "all" {}
Lists all organization members with
username
,
roles
,
is_owner
, and
user_id
.
hcl
data "spiceai_members" "all" {}
列出组织所有成员,包含
username
roles
is_owner
user_id
字段。

spiceai_secrets

spiceai_secrets

hcl
data "spiceai_secrets" "app" {
  app_id = spiceai_app.analytics.id
}
Lists secrets for an app. Values are always masked.
hcl
data "spiceai_secrets" "app" {
  app_id = spiceai_app.analytics.id
}
列出应用的所有密钥。值始终会被屏蔽。

Import

导入

Import existing resources into Terraform state:
bash
undefined
将现有资源导入Terraform状态:
bash
undefined

App (by app ID)

应用(通过应用ID)

terraform import spiceai_app.analytics 12345
terraform import spiceai_app.analytics 12345

Deployment (appId/deploymentId)

部署(appId/deploymentId)

terraform import spiceai_deployment.current 12345/67890
terraform import spiceai_deployment.current 12345/67890

Secret (appId/SECRET_NAME)

密钥(appId/SECRET_NAME)

terraform import spiceai_secret.db_password 12345/DB_PASSWORD
terraform import spiceai_secret.db_password 12345/DB_PASSWORD

Member (by user ID)

成员(通过用户ID)

terraform import spiceai_member.alice 789
terraform import spiceai_member.alice 789

Member with for_each

使用for_each的成员

terraform import 'spiceai_member.team["alice"]' 789

After importing `spiceai_secret`, manually set the `value` in your config — the API never returns plain-text values.
terraform import 'spiceai_member.team["alice"]' 789

导入`spiceai_secret`后,必须在配置中手动设置`value`——API永远不会返回明文值。

Complete Example

完整示例

hcl
terraform {
  required_providers {
    spiceai = {
      source  = "spiceai/spiceai"
      version = "~> 0.1"
    }
  }
}

provider "spiceai" {}
hcl
terraform {
  required_providers {
    spiceai = {
      source  = "spiceai/spiceai"
      version = "~> 0.1"
    }
  }
}

provider "spiceai" {}

Look up available regions and runtime versions

查询可用区域和运行时版本

data "spiceai_regions" "available" {} data "spiceai_container_images" "stable" { channel = "stable" }
data "spiceai_regions" "available" {} data "spiceai_container_images" "stable" { channel = "stable" }

Create the app

创建应用

resource "spiceai_app" "myapp" { name = "my-analytics" cname = data.spiceai_regions.available.default image_tag = data.spiceai_container_images.stable.default
spicepod = yamlencode({ version = "v1" kind = "Spicepod" name = "my-analytics" datasets = [{ from = "postgres:public.events" name = "events" params = { pg_host = "db.example.com" pg_user = "$${secrets:PG_USER}" pg_pass = "$${secrets:PG_PASS}" } }] models = [{ from = "openai:gpt-4o" name = "assistant" params = { openai_api_key = "$${secrets:OPENAI_API_KEY}" } }] }) }
resource "spiceai_app" "myapp" { name = "my-analytics" cname = data.spiceai_regions.available.default image_tag = data.spiceai_container_images.stable.default
spicepod = yamlencode({ version = "v1" kind = "Spicepod" name = "my-analytics" datasets = [{ from = "postgres:public.events" name = "events" params = { pg_host = "db.example.com" pg_user = "$${secrets:PG_USER}" pg_pass = "$${secrets:PG_PASS}" } }] models = [{ from = "openai:gpt-4o" name = "assistant" params = { openai_api_key = "$${secrets:OPENAI_API_KEY}" } }] }) }

Manage secrets

管理密钥

variable "app_secrets" { type = map(string) sensitive = true }
resource "spiceai_secret" "secrets" { for_each = var.app_secrets app_id = spiceai_app.myapp.id name = each.key value = each.value }
variable "app_secrets" { type = map(string) sensitive = true }
resource "spiceai_secret" "secrets" { for_each = var.app_secrets app_id = spiceai_app.myapp.id name = each.key value = each.value }

Deploy (redeploys when app config changes)

部署(应用配置变更时重新部署)

resource "spiceai_deployment" "current" { app_id = spiceai_app.myapp.id commit_message = "Managed by Terraform"
triggers = { spicepod = spiceai_app.myapp.spicepod image_tag = spiceai_app.myapp.image_tag }
depends_on = [spiceai_secret.secrets] }
resource "spiceai_deployment" "current" { app_id = spiceai_app.myapp.id commit_message = "由Terraform管理"
triggers = { spicepod = spiceai_app.myapp.spicepod image_tag = spiceai_app.myapp.image_tag }
depends_on = [spiceai_secret.secrets] }

Team access

团队权限

resource "spiceai_member" "team" { for_each = toset(["alice", "bob"]) username = each.key }
resource "spiceai_member" "team" { for_each = toset(["alice", "bob"]) username = each.key }

Outputs

输出

output "app_id" { value = spiceai_app.myapp.id }
output "api_key" { value = spiceai_app.myapp.api_key sensitive = true }
output "deployment_status" { value = spiceai_deployment.current.status }
undefined
output "app_id" { value = spiceai_app.myapp.id }
output "api_key" { value = spiceai_app.myapp.api_key sensitive = true }
output "deployment_status" { value = spiceai_deployment.current.status }
undefined

Present Results to User

为用户生成配置的最佳实践

When generating Terraform configurations:
  • Use
    data.spiceai_regions
    for region lookup instead of hardcoding
  • Use
    data.spiceai_container_images
    for image tags instead of hardcoding
  • Always use
    for_each
    for multiple secrets or members
  • Mark secret values and API keys as
    sensitive
  • Include
    triggers
    on deployments to auto-redeploy on changes
  • Use
    depends_on
    to ensure secrets exist before deploying
  • Reference secrets in spicepod with
    $${secrets:NAME}
    (double
    $
    for Terraform escaping)
生成Terraform配置时:
  • 使用
    data.spiceai_regions
    查询区域,而非硬编码
  • 使用
    data.spiceai_container_images
    获取镜像标签,而非硬编码
  • 管理多个密钥或成员时始终使用
    for_each
  • 将密钥值和API标记为
    sensitive
  • 在部署中添加
    triggers
    以在变更时自动重新部署
  • 使用
    depends_on
    确保密钥在部署前已存在
  • 在Spicepod中使用
    $${secrets:NAME}
    引用密钥(双
    $
    用于Terraform转义)

Troubleshooting

故障排除

IssueSolution
401
or auth errors
Verify
SPICEAI_CLIENT_ID
/
SPICEAI_CLIENT_SECRET
; check OAuth client scope
Import loses secret valueExpected — set
value
in config after import; API always masks values
Deployment stuck in
queued
Check app has a valid
spicepod
; verify
image_tag
exists
409
on deployment
Previous deployment still in progress; wait or check status
Spicepod YAML syntax errorsUse
yamlencode()
for type safety; validate YAML before applying
$$
showing in spicepod
Use
$${secrets:NAME}
in Terraform — the double
$
escapes to single
$
Cannot delete org ownerOrganization owners cannot be managed by Terraform; remove manually
Provider not foundCheck
source = "spiceai/spiceai"
and run
terraform init
问题解决方案
401
或身份验证错误
验证
SPICEAI_CLIENT_ID
SPICEAI_CLIENT_SECRET
;检查OAuth客户端权限范围
导入后丢失密钥值此为预期行为——导入后在配置中手动设置
value
;API始终会屏蔽值内容
部署卡在
queued
状态
检查应用是否有有效的
spicepod
;验证
image_tag
是否存在
部署时出现
409
错误
上一个部署仍在进行中;等待或检查状态
Spicepod YAML语法错误使用
yamlencode()
保证类型安全;应用前先验证YAML格式
Spicepod中显示
$$
在Terraform中使用
$${secrets:NAME}
——双
$
会转义为单个
$
无法删除组织所有者组织所有者无法通过Terraform管理;手动移除
找不到提供商检查
source = "spiceai/spiceai"
并运行
terraform init

Documentation

文档