Skip to content

Commit 4bfb6a3

Browse files
authored
Update terraform provider to support required cname (#9)
* Add required cname (region identifier) to app resource and docs * Make image_tag configurable in local-spice-api example Preserve user spicepod value during Create/Update to avoid inconsistent result errors
1 parent fa60993 commit 4bfb6a3

12 files changed

Lines changed: 138 additions & 39 deletions

File tree

docs/data-sources/app.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ output "app_api_key" {
6868

6969
- `api_key` (String, Sensitive) The API key for the app.
7070
- `cluster_id` (String) The Kubernetes cluster identifier where the app is deployed.
71+
- `cname` (String) The region identifier (cname) for the app.
7172
- `created_at` (String) The timestamp when the app was created.
7273
- `description` (String) A description of the app.
7374
- `image` (String) Image name for the spiced container.

docs/data-sources/apps.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ Read-Only:
8686

8787
- `api_key` (String, Sensitive) The API key for the app.
8888
- `cluster_id` (String) The Kubernetes cluster identifier where the app is deployed.
89+
- `cname` (String) The region identifier (cname) for the app.
8990
- `created_at` (String) The timestamp when the app was created.
9091
- `description` (String) A description of the app.
9192
- `id` (String) The unique identifier of the app.

docs/resources/app.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ description: |-
1111
name = "my-terraform-app"
1212
description = "An app created and managed by Terraform"
1313
visibility = "private"
14+
cname = "us-east-2.spice.cloud" # Required: region identifier from spiceai_regions data source
1415
1516
# Spicepod configuration (YAML or JSON)
1617
spicepod = <<-YAML
@@ -28,7 +29,7 @@ description: |-
2829
image_tag = "latest"
2930
replicas = 2
3031
node_group = "default"
31-
region = "us-east-1"
32+
region = "us-east-2"
3233
storage_claim_size_gb = 10.0
3334
production_branch = "main"
3435
}
@@ -47,6 +48,7 @@ resource "spiceai_app" "example" {
4748
name = "my-terraform-app"
4849
description = "An app created and managed by Terraform"
4950
visibility = "private"
51+
cname = "us-east-2.spice.cloud" # Required: region identifier from spiceai_regions data source
5052
5153
# Spicepod configuration (YAML or JSON)
5254
spicepod = <<-YAML
@@ -64,7 +66,7 @@ resource "spiceai_app" "example" {
6466
image_tag = "latest"
6567
replicas = 2
6668
node_group = "default"
67-
region = "us-east-1"
69+
region = "us-east-2"
6870
storage_claim_size_gb = 10.0
6971
production_branch = "main"
7072
}
@@ -78,13 +80,15 @@ resource "spiceai_app" "basic" {
7880
name = "my-basic-app"
7981
description = "A basic Spice.ai app"
8082
visibility = "private"
83+
cname = "us-east-2.spice.cloud" # Required: region identifier from spiceai_regions data source
8184
}
8285
8386
# Full app with spicepod and runtime configuration
8487
resource "spiceai_app" "full" {
8588
name = "my-full-app"
8689
description = "A fully configured Spice.ai app"
8790
visibility = "private"
91+
cname = "us-east-2.spice.cloud"
8892
8993
# Spicepod configuration (YAML or JSON)
9094
spicepod = <<-YAML
@@ -105,7 +109,7 @@ resource "spiceai_app" "full" {
105109
image_tag = "latest"
106110
replicas = 2
107111
node_group = "default"
108-
region = "us-east-1"
112+
region = "us-east-2"
109113
storage_claim_size_gb = 10.0
110114
production_branch = "main"
111115
}
@@ -115,6 +119,7 @@ resource "spiceai_app" "json_config" {
115119
name = "my-json-app"
116120
description = "An app with JSON spicepod configuration"
117121
visibility = "public"
122+
cname = "us-west-2.spice.cloud"
118123
119124
spicepod = jsonencode({
120125
version = "v1beta1"
@@ -130,13 +135,24 @@ resource "spiceai_app" "json_config" {
130135
131136
replicas = 1
132137
}
138+
139+
# App using regions data source to get cname
140+
data "spiceai_regions" "available" {}
141+
142+
resource "spiceai_app" "with_region_lookup" {
143+
name = "my-dynamic-region-app"
144+
description = "An app using dynamic region lookup"
145+
visibility = "private"
146+
cname = data.spiceai_regions.available.regions[0].cname
147+
}
133148
```
134149

135150
<!-- schema generated by tfplugindocs -->
136151
## Schema
137152

138153
### Required
139154

155+
- `cname` (String) The region identifier (cname) for the app. This is required when creating an app and determines where the app is deployed. Get available values from the `spiceai_regions` data source. Changing this forces a new resource to be created.
140156
- `name` (String) The name of the app. Must be at least 4 characters and contain only letters, numbers, and hyphens. Changing this forces a new resource to be created.
141157

142158
### Optional

examples/local-spice-api/.terraform.lock.hcl

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/local-spice-api/main.tf

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ terraform {
1111
# Provider configuration
1212
provider "spiceai" {
1313
# Optional: Custom API endpoint (defaults to https://api.spice.ai)
14-
api_endpoint = "http://localhost:8080"
14+
api_endpoint = "https://dev-api.spice.ai"
15+
# api_endpoint = "http://localhost:8080"
1516

1617
# Optional: Custom OAuth endpoint (defaults to https://spice.ai/api/oauth/token)
1718
# oauth_endpoint = "https://spice.ai/api/oauth/token"
@@ -24,20 +25,24 @@ locals {
2425
app_name = "terraform-test-app-local-2"
2526
}
2627

28+
# Get available regions
29+
data "spiceai_regions" "available" {}
30+
2731
# Create a test app with full configuration
2832
resource "spiceai_app" "test" {
2933
name = local.app_name
3034
description = "Test app for Terraform provider validation, updated description"
3135
visibility = "private"
36+
cname = "dev-data" # Required: region identifier
3237

3338
# Spicepod configuration from template file with app name
3439
spicepod = templatefile("${path.module}/spicepod.yaml.tftpl", {
3540
app_name = local.app_name
3641
})
3742

3843
# # Runtime configuration
39-
image_tag = "1.10.0-enterprise-models"
40-
replicas = 3
44+
image_tag = var.image_tag
45+
replicas = 1
4146
# production_branch = "main"
4247
}
4348

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
variable "image_tag" {
2+
description = "The Spice.ai runtime image tag to use for deployments"
3+
type = string
4+
default = "1.10.4-enterprise-models"
5+
}

examples/main.tf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ provider "spiceai" {
1818
# api_endpoint = "https://api.spice.ai" # Optional, defaults to production API
1919
}
2020

21+
# Get available regions
22+
data "spiceai_regions" "available" {}
23+
2124
# Create a new Spice.ai app with configuration
2225
resource "spiceai_app" "example" {
2326
name = "my-terraform-app"
2427
description = "An app created and managed by Terraform"
2528
visibility = "private"
29+
cname = data.spiceai_regions.available.regions[0].cname # Required: region identifier
2630

2731
# Spicepod configuration (YAML or JSON string)
2832
spicepod = <<-YAML
@@ -39,7 +43,7 @@ resource "spiceai_app" "example" {
3943
# Runtime configuration
4044
image_tag = "latest"
4145
replicas = 1
42-
region = "us-east-1"
46+
region = "us-east-2"
4347
production_branch = "main"
4448
}
4549

examples/resources/spiceai_app/resource.tf

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ resource "spiceai_app" "basic" {
33
name = "my-basic-app"
44
description = "A basic Spice.ai app"
55
visibility = "private"
6+
cname = "us-east-2.spice.cloud" # Required: region identifier from spiceai_regions data source
67
}
78

89
# Full app with spicepod and runtime configuration
910
resource "spiceai_app" "full" {
1011
name = "my-full-app"
1112
description = "A fully configured Spice.ai app"
1213
visibility = "private"
14+
cname = "us-east-2.spice.cloud"
1315

1416
# Spicepod configuration (YAML or JSON)
1517
spicepod = <<-YAML
@@ -30,7 +32,7 @@ resource "spiceai_app" "full" {
3032
image_tag = "latest"
3133
replicas = 2
3234
node_group = "default"
33-
region = "us-east-1"
35+
region = "us-east-2"
3436
storage_claim_size_gb = 10.0
3537
production_branch = "main"
3638
}
@@ -40,6 +42,7 @@ resource "spiceai_app" "json_config" {
4042
name = "my-json-app"
4143
description = "An app with JSON spicepod configuration"
4244
visibility = "public"
45+
cname = "us-west-2.spice.cloud"
4346

4447
spicepod = jsonencode({
4548
version = "v1beta1"
@@ -54,4 +57,14 @@ resource "spiceai_app" "json_config" {
5457
})
5558

5659
replicas = 1
60+
}
61+
62+
# App using regions data source to get cname
63+
data "spiceai_regions" "available" {}
64+
65+
resource "spiceai_app" "with_region_lookup" {
66+
name = "my-dynamic-region-app"
67+
description = "An app using dynamic region lookup"
68+
visibility = "private"
69+
cname = data.spiceai_regions.available.regions[0].cname
5770
}

internal/client/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ type App struct {
158158
Description string `json:"description,omitempty"`
159159
Visibility string `json:"visibility,omitempty"`
160160
CreatedAt string `json:"created_at,omitempty"`
161-
Region string `json:"region,omitempty"`
161+
Cname string `json:"cname,omitempty"`
162162
ClusterID string `json:"cluster_id,omitempty"`
163163
ProductionBranch string `json:"production_branch,omitempty"`
164164
APIKey string `json:"api_key,omitempty"`
@@ -182,6 +182,7 @@ type AppConfig struct {
182182
// CreateAppRequest represents the request to create an app.
183183
type CreateAppRequest struct {
184184
Name string `json:"name"`
185+
Cname string `json:"cname"`
185186
Description string `json:"description,omitempty"`
186187
Visibility string `json:"visibility,omitempty"`
187188
Tags map[string]string `json:"tags,omitempty"`

internal/provider/datasource_app.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type AppDataSourceModel struct {
4141
Visibility types.String `tfsdk:"visibility"`
4242
ProductionBranch types.String `tfsdk:"production_branch"`
4343
Tags types.Map `tfsdk:"tags"`
44+
Cname types.String `tfsdk:"cname"`
4445

4546
// Spicepod configuration
4647
Spicepod types.String `tfsdk:"spicepod"`
@@ -98,6 +99,10 @@ func (d *AppDataSource) Schema(ctx context.Context, req datasource.SchemaRequest
9899
Computed: true,
99100
ElementType: types.StringType,
100101
},
102+
"cname": schema.StringAttribute{
103+
MarkdownDescription: "The region identifier (cname) for the app.",
104+
Computed: true,
105+
},
101106

102107
// Spicepod configuration
103108
"spicepod": schema.StringAttribute{
@@ -233,10 +238,15 @@ func (d *AppDataSource) mapAppToModel(data *AppDataSourceModel, app *client.App)
233238
data.ClusterID = types.StringValue(app.ClusterID)
234239
data.APIKey = types.StringValue(app.APIKey)
235240

236-
// Region can be at top level or inside config
237-
if app.Region != "" {
238-
data.Region = types.StringValue(app.Region)
239-
} else if app.Config != nil && app.Config.Region != "" {
241+
// Map cname
242+
if app.Cname != "" {
243+
data.Cname = types.StringValue(app.Cname)
244+
} else {
245+
data.Cname = types.StringNull()
246+
}
247+
248+
// Region is inside config
249+
if app.Config != nil && app.Config.Region != "" {
240250
data.Region = types.StringValue(app.Config.Region)
241251
} else {
242252
data.Region = types.StringNull()

0 commit comments

Comments
 (0)