Skip to content

Commit 59e6058

Browse files
committed
feat: add datasource spacelift_template_deployment
Added datasource for blueprint template deployments
1 parent 8feacb3 commit 59e6058

File tree

4 files changed

+328
-0
lines changed

4 files changed

+328
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "spacelift_template_deployment Data Source - terraform-provider-spacelift"
4+
subcategory: ""
5+
description: |-
6+
spacelift_template_deployment represents an existing deployment of a Spacelift template.
7+
---
8+
9+
# spacelift_template_deployment (Data Source)
10+
11+
`spacelift_template_deployment` represents an existing deployment of a Spacelift template.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `deployment_id` (String) ID (slug) of the deployment
21+
- `template_id` (String) ID of the template this deployment belongs to
22+
23+
### Read-Only
24+
25+
- `created_at` (Number) Unix timestamp when the deployment was created
26+
- `description` (String) Description of the deployment
27+
- `id` (String) The ID of this resource.
28+
- `input` (List of Object) Input values for the template (see [below for nested schema](#nestedatt--input))
29+
- `name` (String) Name of the deployment
30+
- `space` (String) Space where the stacks created by this deployment are placed
31+
- `stacks` (List of Object) List of stacks IDs created by the deployment (see [below for nested schema](#nestedatt--stacks))
32+
- `state` (String) Current state of the deployment
33+
- `template_version_id` (String) ID of the template version used by this deployment
34+
35+
<a id="nestedatt--input"></a>
36+
### Nested Schema for `input`
37+
38+
Read-Only:
39+
40+
- `checksum` (String)
41+
- `id` (String)
42+
- `secret` (Boolean)
43+
- `value` (String)
44+
45+
46+
<a id="nestedatt--stacks"></a>
47+
### Nested Schema for `stacks`
48+
49+
Read-Only:
50+
51+
- `id` (String)
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package spacelift
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
10+
"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal"
11+
"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal/structs"
12+
"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal/validations"
13+
)
14+
15+
func dataTemplateDeployment() *schema.Resource {
16+
return &schema.Resource{
17+
Description: "`spacelift_template_deployment` represents an existing deployment of a Spacelift template.",
18+
19+
ReadContext: dataTemplateDeploymentRead,
20+
21+
Schema: map[string]*schema.Schema{
22+
"template_id": {
23+
Type: schema.TypeString,
24+
Description: "ID of the template this deployment belongs to",
25+
Required: true,
26+
ValidateDiagFunc: validations.DisallowEmptyString,
27+
},
28+
"deployment_id": {
29+
Type: schema.TypeString,
30+
Description: "ID (slug) of the deployment",
31+
Required: true,
32+
ValidateDiagFunc: validations.DisallowEmptyString,
33+
},
34+
"name": {
35+
Type: schema.TypeString,
36+
Description: "Name of the deployment",
37+
Computed: true,
38+
},
39+
"description": {
40+
Type: schema.TypeString,
41+
Description: "Description of the deployment",
42+
Computed: true,
43+
},
44+
"state": {
45+
Type: schema.TypeString,
46+
Description: "Current state of the deployment",
47+
Computed: true,
48+
},
49+
"created_at": {
50+
Type: schema.TypeInt,
51+
Description: "Unix timestamp when the deployment was created",
52+
Computed: true,
53+
},
54+
"space": {
55+
Type: schema.TypeString,
56+
Description: "Space where the stacks created by this deployment are placed",
57+
Computed: true,
58+
},
59+
"template_version_id": {
60+
Type: schema.TypeString,
61+
Description: "ID of the template version used by this deployment",
62+
Computed: true,
63+
},
64+
"input": {
65+
Type: schema.TypeList,
66+
Description: "Input values for the template",
67+
Computed: true,
68+
Elem: &schema.Resource{
69+
Schema: map[string]*schema.Schema{
70+
"id": {
71+
Type: schema.TypeString,
72+
Description: "Input identifier",
73+
Computed: true,
74+
},
75+
"value": {
76+
Type: schema.TypeString,
77+
Description: "Input value, for secrets this will be set to an empty string",
78+
Computed: true,
79+
Sensitive: true,
80+
},
81+
"secret": {
82+
Type: schema.TypeBool,
83+
Description: "True if the input value is a secret",
84+
Computed: true,
85+
},
86+
"checksum": {
87+
Type: schema.TypeString,
88+
Description: "SHA-256 checksum of the input value",
89+
Computed: true,
90+
},
91+
},
92+
},
93+
},
94+
"stacks": {
95+
Type: schema.TypeList,
96+
Description: "List of stacks IDs created by the deployment",
97+
Computed: true,
98+
Elem: &schema.Resource{
99+
Schema: map[string]*schema.Schema{
100+
"id": {
101+
Type: schema.TypeString,
102+
Description: "ID of the stack",
103+
Computed: true,
104+
},
105+
},
106+
},
107+
},
108+
},
109+
}
110+
}
111+
112+
func dataTemplateDeploymentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
113+
templateID := d.Get("template_id").(string)
114+
deploymentID := d.Get("deployment_id").(string)
115+
116+
var query struct {
117+
TemplateDeployment *structs.TemplateDeployment `graphql:"blueprintDeployment(id: $id, blueprintID: $blueprintID)"`
118+
}
119+
120+
variables := map[string]interface{}{
121+
"id": toID(deploymentID),
122+
"blueprintID": toID(templateID),
123+
}
124+
125+
if err := meta.(*internal.Client).Query(ctx, "BlueprintDeployment", &query, variables); err != nil {
126+
return diag.Errorf("could not query for template deployment: %v", err)
127+
}
128+
129+
if query.TemplateDeployment == nil {
130+
return diag.Errorf("could not find template deployment %s/%s", templateID, deploymentID)
131+
}
132+
133+
deployment := query.TemplateDeployment
134+
135+
// Set the resource ID in the format template_id/deployment_id
136+
d.SetId(fmt.Sprintf("%s/%s", templateID, deploymentID))
137+
138+
d.Set("template_id", deployment.Template.ID)
139+
d.Set("deployment_id", deployment.ID)
140+
d.Set("name", deployment.Name)
141+
d.Set("state", deployment.State)
142+
d.Set("created_at", deployment.CreatedAt)
143+
d.Set("space", deployment.Space.ID)
144+
d.Set("template_version_id", deployment.TemplateVersion.ID)
145+
146+
if deployment.Description != nil {
147+
d.Set("description", *deployment.Description)
148+
} else {
149+
d.Set("description", "")
150+
}
151+
152+
// Set input values
153+
inputList := make([]map[string]interface{}, len(deployment.Inputs))
154+
for i, input := range deployment.Inputs {
155+
in := map[string]interface{}{
156+
"id": input.ID,
157+
"value": input.Value,
158+
"secret": input.Secret,
159+
"checksum": input.Checksum,
160+
}
161+
inputList[i] = in
162+
}
163+
if err := d.Set("input", inputList); err != nil {
164+
return diag.FromErr(err)
165+
}
166+
167+
// Set stacks
168+
stacks := make([]map[string]string, len(deployment.Stacks))
169+
for i, stack := range deployment.Stacks {
170+
stacks[i] = map[string]string{
171+
"id": stack.ID,
172+
}
173+
}
174+
if err := d.Set("stacks", stacks); err != nil {
175+
return diag.FromErr(err)
176+
}
177+
178+
return nil
179+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package spacelift
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
)
10+
11+
func TestTemplateDeploymentData(t *testing.T) {
12+
const datasourceName = "data.spacelift_template_deployment.test"
13+
14+
t.Run("creates and reads a template deployment", func(t *testing.T) {
15+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
16+
17+
testSteps(t, []resource.TestStep{{
18+
Config: fmt.Sprintf(`
19+
resource "spacelift_template" "test" {
20+
name = "test-template-%[1]s"
21+
space = "root"
22+
}
23+
24+
resource "spacelift_template_version" "test" {
25+
template_id = spacelift_template.test.id
26+
version_number = "1.0.0"
27+
state = "PUBLISHED"
28+
template = <<-EOT
29+
stacks:
30+
- name: test-stack-$${{ inputs.env_name }}-%[1]s
31+
key: test
32+
autodeploy: true
33+
vcs:
34+
reference:
35+
value: master
36+
type: branch
37+
repository: terraform-bacon-tasty
38+
provider: GITHUB
39+
vendor:
40+
terraform:
41+
manage_state: true
42+
version: "1.5.0"
43+
inputs:
44+
- id: env_name
45+
name: Environment Name
46+
default: dev
47+
- id: secret
48+
name: secret
49+
type: secret
50+
EOT
51+
}
52+
53+
resource "spacelift_template_deployment" "test" {
54+
template_version_id = spacelift_template_version.test.id
55+
space = "root"
56+
name = "test-deployment-%[1]s"
57+
description = "test description"
58+
59+
input {
60+
id = "env_name"
61+
value = "production"
62+
}
63+
64+
input {
65+
id = "secret"
66+
value = "secret_value"
67+
}
68+
}
69+
70+
data "spacelift_template_deployment" "test" {
71+
template_id = spacelift_template.test.id
72+
deployment_id = spacelift_template_deployment.test.deployment_id
73+
}
74+
`, randomID),
75+
Check: resource.ComposeAggregateTestCheckFunc(
76+
resource.TestCheckResourceAttrSet(datasourceName, "id"),
77+
resource.TestCheckResourceAttr(datasourceName, "template_id", "test-template-"+randomID),
78+
resource.TestCheckResourceAttr(datasourceName, "deployment_id", "test-deployment-"+randomID),
79+
resource.TestCheckResourceAttr(datasourceName, "name", "test-deployment-"+randomID),
80+
resource.TestCheckResourceAttr(datasourceName, "space", "root"),
81+
resource.TestCheckResourceAttr(datasourceName, "description", "test description"),
82+
resource.TestCheckResourceAttrSet(datasourceName, "state"),
83+
resource.TestCheckResourceAttrSet(datasourceName, "created_at"),
84+
resource.TestCheckResourceAttrSet(datasourceName, "template_version_id"),
85+
resource.TestCheckResourceAttr(datasourceName, "input.#", "2"),
86+
resource.TestCheckResourceAttr(datasourceName, "input.0.id", "env_name"),
87+
resource.TestCheckResourceAttr(datasourceName, "input.0.value", "production"),
88+
resource.TestCheckResourceAttr(datasourceName, "input.0.secret", "false"),
89+
resource.TestCheckResourceAttr(datasourceName, "input.1.id", "secret"),
90+
resource.TestCheckResourceAttr(datasourceName, "input.1.secret", "true"),
91+
resource.TestCheckResourceAttr(datasourceName, "input.1.checksum", "28dd40f834818f2e63827ddd50a1d50198b8e5233b9e21956ccedccc1be8a35e"),
92+
resource.TestCheckResourceAttr(datasourceName, "stacks.#", "1"),
93+
resource.TestCheckResourceAttr(datasourceName, "stacks.0.id", "test-stack-production-"+randomID),
94+
),
95+
}})
96+
})
97+
}

spacelift/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func Provider(commit, version string) plugin.ProviderFunc {
9898
"spacelift_stack_outputs": dataStackOutputs(),
9999
"spacelift_stacks": dataStacks(),
100100
"spacelift_template": dataTemplate(),
101+
"spacelift_template_deployment": dataTemplateDeployment(),
101102
"spacelift_template_version": dataTemplateVersion(),
102103
"spacelift_tool_versions": dataToolVersions(),
103104
"spacelift_user": dataUser(),

0 commit comments

Comments
 (0)