spice-terraform

📁 spiceai/skills 📅 8 days ago
3
总安装量
2
周安装量
#54899
全站排名
安装命令
npx skills add https://github.com/spiceai/skills --skill spice-terraform

Agent 安装分布

opencode 2
qwen-code 2
claude-code 2
github-copilot 2
windsurf 2
codex 2

Skill 文档

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.

Provider Setup

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

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.

export SPICEAI_CLIENT_ID="your-client-id"
export SPICEAI_CLIENT_SECRET="your-client-secret"
terraform plan

Resources

spiceai_app

Manages a Spice.ai application.

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
name string Yes Min 4 chars, alphanumeric + hyphens
cname string Yes Region identifier (from spiceai_regions)
description string No
visibility string No public or private (default: private)
spicepod string No YAML or JSON spicepod configuration
image_tag string No Spice runtime version tag
replicas number No 1-10
region string No AWS region code
production_branch string No Git branch for production deployments
node_group string No Kubernetes node group
storage_claim_size_gb number No Persistent volume size in GB

Read-only attributes: id, api_key (sensitive), created_at

spiceai_deployment

Creates an immutable deployment for an app. Use triggers to auto-redeploy on config changes.

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
app_id string Yes App ID to deploy
image_tag string No Override runtime image
replicas number No Override replicas (1-10)
debug boolean No Enable debug mode (default: false)
branch string No Git branch for tracking
commit_sha string No Git commit SHA
commit_message string No Deployment 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.

spiceai_secret

Manages app secrets. Values are AES-256 encrypted at rest.

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
app_id string Yes
name string Yes Start with letter/underscore, alphanumeric + _
value string Yes Sensitive. Must set manually after import (API masks values)

Read-only attributes: id

spiceai_member

Manages organization members by GitHub username.

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
username string Yes GitHub username
roles string[] No Default: ["member"]. Options: owner, member, billing

Read-only attributes: user_id

Organization owners cannot be managed via Terraform.

Data Sources

spiceai_regions

data "spiceai_regions" "available" {}

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

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

spiceai_container_images

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

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

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

spiceai_app (data)

data "spiceai_app" "existing" {
  id = 12345
}

Retrieves details of an existing app by ID.

spiceai_apps

data "spiceai_apps" "all" {}

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

Lists all apps in the organization.

spiceai_members

data "spiceai_members" "all" {}

Lists all organization members with username, roles, is_owner, and user_id.

spiceai_secrets

data "spiceai_secrets" "app" {
  app_id = spiceai_app.analytics.id
}

Lists secrets for an app. Values are always masked.

Import

Import existing resources into Terraform state:

# App (by app ID)
terraform import spiceai_app.analytics 12345

# Deployment (appId/deploymentId)
terraform import spiceai_deployment.current 12345/67890

# Secret (appId/SECRET_NAME)
terraform import spiceai_secret.db_password 12345/DB_PASSWORD

# Member (by user ID)
terraform import spiceai_member.alice 789

# Member with 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.

Complete Example

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"
}

# 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}"
      }
    }]
  })
}

# 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
}

# 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]
}

# Team access
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
}

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)

Troubleshooting

Issue Solution
401 or auth errors Verify SPICEAI_CLIENT_ID / SPICEAI_CLIENT_SECRET; check OAuth client scope
Import loses secret value Expected — 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 errors Use yamlencode() for type safety; validate YAML before applying
$$ showing in spicepod Use $${secrets:NAME} in Terraform — the double $ escapes to single $
Cannot delete org owner Organization owners cannot be managed by Terraform; remove manually
Provider not found Check source = "spiceai/spiceai" and run terraform init

Documentation