spice-terraform
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSpice.ai Terraform Provider
Spice.ai Terraform Provider
Manage Spice.ai Cloud resources as infrastructure-as-code using the Terraform provider. Supports apps, deployments, secrets, org members, and data sources for regions and runtime images.
spiceai/spiceai使用 Terraform Provider将Spice.ai Cloud资源作为基础设施即代码进行管理。支持应用、部署、密钥、组织成员,以及用于区域和运行时镜像的数据源。
spiceai/spiceaiProvider 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:
- Provider block — and
client_idargumentsclient_secret - Environment variables — and
SPICEAI_CLIENT_IDSPICEAI_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客户端凭证。可通过以下方式设置凭证:
- 提供商块 — 和
client_id参数client_secret - 环境变量 — 和
SPICEAI_CLIENT_IDSPICEAI_CLIENT_SECRET
在Spice.ai门户中创建OAuth客户端:设置 > OAuth客户端。
bash
export SPICEAI_CLIENT_ID="your-client-id"
export SPICEAI_CLIENT_SECRET="your-client-secret"
terraform planResources
资源
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:
| Argument | Type | Required | Notes |
|---|---|---|---|
| string | Yes | Min 4 chars, alphanumeric + hyphens |
| string | Yes | Region identifier (from |
| string | No | |
| string | No | |
| string | No | YAML or JSON spicepod configuration |
| string | No | Spice runtime version tag |
| number | No | 1-10 |
| string | No | AWS region code |
| string | No | Git branch for production deployments |
| string | No | Kubernetes node group |
| number | No | Persistent volume size in GB |
Read-only attributes: , (sensitive),
idapi_keycreated_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"
}
}]
})
}参数:
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 字符串 | 是 | 最少4个字符,仅支持字母、数字和连字符 |
| 字符串 | 是 | 区域标识符(来自 |
| 字符串 | 否 | 应用描述 |
| 字符串 | 否 | 可见性,可选 |
| 字符串 | 否 | YAML或JSON格式的Spicepod配置 |
| 字符串 | 否 | Spice运行时版本标签 |
| 数字 | 否 | 副本数,范围1-10 |
| 字符串 | 否 | AWS区域代码 |
| 字符串 | 否 | 用于生产部署的Git分支 |
| 字符串 | 否 | Kubernetes节点组 |
| 数字 | 否 | 持久化卷大小(GB) |
只读属性: 、(敏感)、
idapi_keycreated_atspiceai_deployment
spiceai_deployment
Creates an immutable deployment for an app. Use to auto-redeploy on config changes.
triggershcl
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:
| Argument | Type | Required | Notes |
|---|---|---|---|
| string | Yes | App ID to deploy |
| string | No | Override runtime image |
| number | No | Override replicas (1-10) |
| boolean | No | Enable debug mode (default: false) |
| string | No | Git branch for tracking |
| string | No | Git commit SHA |
| string | No | Deployment description |
Read-only attributes: , ( | | | ), ,
idstatusqueuedin_progresssucceededfailederror_messagecreated_atThe map causes Terraform to replace the deployment whenever any tracked value changes.
triggers为应用创建不可变的部署。使用在配置变更时自动重新部署。
triggershcl
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
}
}参数:
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 字符串 | 是 | 要部署的应用ID |
| 字符串 | 否 | 覆盖运行时镜像 |
| 数字 | 否 | 覆盖副本数(1-10) |
| 布尔值 | 否 | 启用调试模式(默认:false) |
| 字符串 | 否 | 用于跟踪的Git分支 |
| 字符串 | 否 | Git提交SHA值 |
| 字符串 | 否 | 部署描述 |
只读属性: 、( | | | )、、
idstatusqueuedin_progresssucceededfailederror_messagecreated_attriggersspiceai_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:
| Argument | Type | Required | Notes |
|---|---|---|---|
| string | Yes | |
| string | Yes | Start with letter/underscore, alphanumeric + |
| string | Yes | Sensitive. 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
}参数:
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 字符串 | 是 | 所属应用ID |
| 字符串 | 是 | 以字母或下划线开头,仅支持字母、数字和 |
| 字符串 | 是 | 敏感值。导入后必须手动设置(API会屏蔽值内容) |
只读属性:
idspiceai_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:
| Argument | Type | Required | Notes |
|---|---|---|---|
| string | Yes | GitHub username |
| string[] | No | Default: |
Read-only attributes:
user_idOrganization 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"]
}参数:
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 字符串 | 是 | GitHub用户名 |
| 字符串数组 | 否 | 默认: |
只读属性:
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 , , , and .
usernamerolesis_owneruser_idhcl
data "spiceai_members" "all" {}列出组织所有成员,包含、、和字段。
usernamerolesis_owneruser_idspiceai_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
undefinedApp (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
}
undefinedoutput "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
}
undefinedPresent Results to User
为用户生成配置的最佳实践
When generating Terraform configurations:
- Use for region lookup instead of hardcoding
data.spiceai_regions - Use for image tags instead of hardcoding
data.spiceai_container_images - Always use for multiple secrets or members
for_each - Mark secret values and API keys as
sensitive - Include on deployments to auto-redeploy on changes
triggers - Use to ensure secrets exist before deploying
depends_on - Reference secrets in spicepod with (double
$${secrets:NAME}for Terraform escaping)$
生成Terraform配置时:
- 使用查询区域,而非硬编码
data.spiceai_regions - 使用获取镜像标签,而非硬编码
data.spiceai_container_images - 管理多个密钥或成员时始终使用
for_each - 将密钥值和API标记为
sensitive - 在部署中添加以在变更时自动重新部署
triggers - 使用确保密钥在部署前已存在
depends_on - 在Spicepod中使用引用密钥(双
$${secrets:NAME}用于Terraform转义)$
Troubleshooting
故障排除
| Issue | Solution |
|---|---|
| Verify |
| Import loses secret value | Expected — set |
Deployment stuck in | Check app has a valid |
| Previous deployment still in progress; wait or check status |
| Spicepod YAML syntax errors | Use |
| Use |
| Cannot delete org owner | Organization owners cannot be managed by Terraform; remove manually |
| Provider not found | Check |
| 问题 | 解决方案 |
|---|---|
| 验证 |
| 导入后丢失密钥值 | 此为预期行为——导入后在配置中手动设置 |
部署卡在 | 检查应用是否有有效的 |
部署时出现 | 上一个部署仍在进行中;等待或检查状态 |
| Spicepod YAML语法错误 | 使用 |
Spicepod中显示 | 在Terraform中使用 |
| 无法删除组织所有者 | 组织所有者无法通过Terraform管理;手动移除 |
| 找不到提供商 | 检查 |