Skip to content

Commit 0011626

Browse files
authored
Merge pull request #39 from pluralsh/marcin/eng-2167-add-custom-stack-runs-to-terraform-provider
feat: Add custom stack run resource
2 parents e97ade9 + dcd636e commit 0011626

File tree

11 files changed

+646
-8
lines changed

11 files changed

+646
-8
lines changed

.github/workflows/release.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,21 @@ jobs:
1010
name: Release
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
13+
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
1414
with:
1515
fetch-depth: 0
16-
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
16+
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
1717
with:
1818
go-version-file: 'go.mod'
1919
cache: true
2020
- name: Import GPG key
21-
uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0
21+
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
2222
id: import_gpg
2323
with:
2424
gpg_private_key: ${{ secrets.PLURAL_GPG_PRIVATE_KEY }}
2525
passphrase: ${{ secrets.PLURAL_GPG_KEY_PASSWORD }}
2626
- name: Run GoReleaser
27-
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0
27+
uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811 # v5.1.0
2828
with:
2929
args: release --clean
3030
env:

.goreleaser.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ before:
77
builds:
88
- env:
99
# goreleaser does not work with CGO, it could also complicate
10-
# usage by users in CI/CD systems like Terraform Cloud where
10+
# usage by users in CI/CD systems like HCP Terraform where
1111
# they are unable to install libraries.
1212
- CGO_ENABLED=0
1313
mod_timestamp: '{{ .CommitTimestamp }}'

docs/resources/custom_stack_run.md

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "plural_custom_stack_run Resource - terraform-provider-plural"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# plural_custom_stack_run (Resource)
10+
11+
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `name` (String) Human-readable name of this custom run.
21+
22+
### Optional
23+
24+
- `commands` (Attributes Set) The commands for this custom run. (see [below for nested schema](#nestedatt--commands))
25+
- `configuration` (Attributes Set) Self-service configuration which will be presented in UI before triggering. (see [below for nested schema](#nestedatt--configuration))
26+
- `documentation` (String) Extended documentation to explain what this will do.
27+
- `stack_id` (String) The ID of the stack to attach it to.
28+
29+
### Read-Only
30+
31+
- `id` (String) Internal identifier of this custom run.
32+
33+
<a id="nestedatt--commands"></a>
34+
### Nested Schema for `commands`
35+
36+
Required:
37+
38+
- `cmd` (String) Command to run.
39+
40+
Optional:
41+
42+
- `args` (Set of String) Arguments to pass to the command when executing it.
43+
- `dir` (String)
44+
45+
46+
<a id="nestedatt--configuration"></a>
47+
### Nested Schema for `configuration`
48+
49+
Required:
50+
51+
- `name` (String)
52+
- `type` (String)
53+
54+
Optional:
55+
56+
- `condition` (Attributes) (see [below for nested schema](#nestedatt--configuration--condition))
57+
- `default` (String)
58+
- `documentation` (String)
59+
- `longform` (String)
60+
- `optional` (Boolean)
61+
- `placeholder` (String)
62+
63+
<a id="nestedatt--configuration--condition"></a>
64+
### Nested Schema for `configuration.condition`
65+
66+
Required:
67+
68+
- `field` (String)
69+
- `operation` (String)
70+
71+
Optional:
72+
73+
- `value` (String)

docs/resources/infrastructure_stack.md

+15
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ description: |-
2525

2626
### Optional
2727

28+
- `actor` (String) The User email to use for default Plural authentication in this stack.
2829
- `approval` (Boolean) Determines whether to require approval.
2930
- `bindings` (Attributes) Read and write policies of this stack. (see [below for nested schema](#nestedatt--bindings))
3031
- `detach` (Boolean) Determines behavior during resource destruction, if true it will detach resource instead of deleting it.
@@ -45,8 +46,22 @@ Required:
4546

4647
Optional:
4748

49+
- `hooks` (Attributes Set) The hooks to customize execution for this stack. (see [below for nested schema](#nestedatt--configuration--hooks))
4850
- `image` (String) Optional custom image you might want to use.
4951

52+
<a id="nestedatt--configuration--hooks"></a>
53+
### Nested Schema for `configuration.hooks`
54+
55+
Required:
56+
57+
- `after_stage` (String)
58+
- `cmd` (String)
59+
60+
Optional:
61+
62+
- `args` (List of String) Arguments to pass to the command when executing it.
63+
64+
5065

5166
<a id="nestedatt--repository"></a>
5267
### Nested Schema for `repository`

example/customstackrun/main.tf

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
terraform {
2+
required_providers {
3+
plural = {
4+
source = "pluralsh/plural"
5+
version = "0.2.1"
6+
}
7+
}
8+
}
9+
10+
provider "plural" {
11+
use_cli = true
12+
}
13+
14+
data "plural_cluster" "cluster" {
15+
handle = "mgmt"
16+
}
17+
18+
data "plural_git_repository" "repository" {
19+
url = "https://github.com/zreigz/tf-hello.git"
20+
}
21+
22+
resource "random_string" "random" {
23+
length = 5
24+
upper = false
25+
special = false
26+
}
27+
28+
resource "plural_infrastructure_stack" "stack" {
29+
name = "stack-tf-${random_string.random.result}"
30+
type = "TERRAFORM"
31+
detach = true
32+
cluster_id = data.plural_cluster.cluster.id
33+
repository = {
34+
id = data.plural_git_repository.repository.id
35+
ref = "main"
36+
folder = "terraform"
37+
}
38+
configuration = {
39+
version = "1.8.1"
40+
}
41+
}
42+
43+
resource "plural_custom_stack_run" "run-full" {
44+
name = "run-tf-full-${random_string.random.result}"
45+
documentation = "test"
46+
stack_id = plural_infrastructure_stack.stack.id
47+
commands = [{
48+
cmd = "ls"
49+
args = ["-al"]
50+
dir = "/"
51+
}]
52+
configuration = [{
53+
type = "STRING"
54+
name = "author"
55+
default = "john"
56+
documentation = "author name"
57+
longform = "author name"
58+
placeholder = "author name, i.e. john"
59+
optional = true
60+
condition = {
61+
operation = "PREFIX"
62+
field = "author"
63+
value = "j"
64+
}
65+
}]
66+
}
67+
68+
resource "plural_custom_stack_run" "run-minimal" {
69+
name = "run-tf-minimal-${random_string.random.result}"
70+
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
1313
github.com/hashicorp/terraform-plugin-log v0.9.0
1414
github.com/mitchellh/go-homedir v1.1.0
15-
github.com/pluralsh/console-client-go v0.5.14
15+
github.com/pluralsh/console-client-go v0.5.16
1616
github.com/pluralsh/plural-cli v0.8.5-0.20240216094552-efc34ee6de37
1717
github.com/pluralsh/polly v0.1.7
1818
github.com/samber/lo v1.38.1

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
856856
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
857857
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
858858
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
859-
github.com/pluralsh/console-client-go v0.5.14 h1:JgpFSx481O4Od63iIbj3+hKBn+JW/WyAZrJOofFBPpk=
860-
github.com/pluralsh/console-client-go v0.5.14/go.mod h1:eyCiLA44YbXiYyJh8303jk5JdPkt9McgCo5kBjk4lKo=
859+
github.com/pluralsh/console-client-go v0.5.16 h1:AHBnis/xUdXbUclNH1GUwcqAsCOzHzOtwetKOIS0dTM=
860+
github.com/pluralsh/console-client-go v0.5.16/go.mod h1:eyCiLA44YbXiYyJh8303jk5JdPkt9McgCo5kBjk4lKo=
861861
github.com/pluralsh/gqlclient v1.11.0 h1:FfXW7FiEJLHOfTAa7NxDb8jb3aMZNIpCAcG+bg8uHYA=
862862
github.com/pluralsh/gqlclient v1.11.0/go.mod h1:qSXKUlio1F2DRPy8el4oFYsmpKbkUYspgPB87T4it5I=
863863
github.com/pluralsh/plural-cli v0.8.5-0.20240216094552-efc34ee6de37 h1:DBnaKvKmbTbKwbkrh/2gJBwyHYfaXdxeT3UGh+94K4g=

internal/provider/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ func (p *PluralProvider) Resources(_ context.Context) []func() resource.Resource
185185
r.NewServiceDeploymentResource,
186186
r.NewServiceContextResource,
187187
r.NewInfrastructureStackResource,
188+
r.NewCustomStackRunResource,
188189
}
189190
}
190191

internal/resource/custom_stack_run.go

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package resource
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"terraform-provider-plural/internal/client"
8+
"terraform-provider-plural/internal/common"
9+
10+
"github.com/hashicorp/terraform-plugin-framework/path"
11+
"github.com/hashicorp/terraform-plugin-framework/resource"
12+
)
13+
14+
var _ resource.Resource = &CustomStackRunResource{}
15+
var _ resource.ResourceWithImportState = &CustomStackRunResource{}
16+
17+
func NewCustomStackRunResource() resource.Resource {
18+
return &CustomStackRunResource{}
19+
}
20+
21+
// CustomStackRunResource defines the custom stack run resource implementation.
22+
type CustomStackRunResource struct {
23+
client *client.Client
24+
}
25+
26+
func (r *CustomStackRunResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
27+
resp.TypeName = req.ProviderTypeName + "_custom_stack_run"
28+
}
29+
30+
func (r *CustomStackRunResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
31+
resp.Schema = r.schema()
32+
}
33+
34+
func (r *CustomStackRunResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
35+
if req.ProviderData == nil {
36+
return
37+
}
38+
39+
data, ok := req.ProviderData.(*common.ProviderData)
40+
if !ok {
41+
resp.Diagnostics.AddError(
42+
"Unexpected Custom Stack Run Resource Configure Type",
43+
fmt.Sprintf("Expected *common.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
44+
)
45+
46+
return
47+
}
48+
49+
r.client = data.Client
50+
}
51+
52+
func (r *CustomStackRunResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
53+
data := new(customStackRun)
54+
resp.Diagnostics.Append(req.Plan.Get(ctx, data)...)
55+
if resp.Diagnostics.HasError() {
56+
return
57+
}
58+
59+
attr, err := data.Attributes(ctx, resp.Diagnostics, r.client)
60+
if err != nil {
61+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get attributes, got error: %s", err))
62+
return
63+
}
64+
sd, err := r.client.CreateCustomStackRun(ctx, *attr)
65+
if err != nil {
66+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create custom stack run, got error: %s", err))
67+
return
68+
}
69+
70+
data.From(sd.CreateCustomStackRun, ctx, resp.Diagnostics)
71+
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
72+
}
73+
74+
func (r *CustomStackRunResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
75+
data := new(customStackRun)
76+
resp.Diagnostics.Append(req.State.Get(ctx, data)...)
77+
if resp.Diagnostics.HasError() {
78+
return
79+
}
80+
81+
response, err := r.client.GetCustomStackRun(ctx, data.Id.ValueString())
82+
if err != nil {
83+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read custom stack run, got error: %s", err))
84+
return
85+
}
86+
87+
data.From(response.CustomStackRun, ctx, resp.Diagnostics)
88+
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
89+
}
90+
91+
func (r *CustomStackRunResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
92+
data := new(customStackRun)
93+
resp.Diagnostics.Append(req.Plan.Get(ctx, data)...)
94+
if resp.Diagnostics.HasError() {
95+
return
96+
}
97+
98+
attr, err := data.Attributes(ctx, resp.Diagnostics, r.client)
99+
if err != nil {
100+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get attributes, got error: %s", err))
101+
return
102+
}
103+
_, err = r.client.UpdateCustomStackRun(ctx, data.Id.ValueString(), *attr)
104+
if err != nil {
105+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update custom stack run, got error: %s", err))
106+
return
107+
}
108+
109+
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
110+
}
111+
112+
func (r *CustomStackRunResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
113+
data := new(customStackRun)
114+
resp.Diagnostics.Append(req.State.Get(ctx, data)...)
115+
if resp.Diagnostics.HasError() {
116+
return
117+
}
118+
119+
_, err := r.client.DeleteCustomStackRun(ctx, data.Id.ValueString())
120+
if err != nil {
121+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete custom stack run, got error: %s", err))
122+
return
123+
}
124+
}
125+
126+
func (r *CustomStackRunResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
127+
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
128+
}

0 commit comments

Comments
 (0)