Skip to content

Commit edeeded

Browse files
committed
feat(audit-trail): add support for audit trail to terraform provider
Signed-off-by: Michal Wasilewski <[email protected]>
1 parent 4d3a072 commit edeeded

File tree

7 files changed

+236
-0
lines changed

7 files changed

+236
-0
lines changed

docs/resources/audit_trail_webhook.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "spacelift_audit_trail_webhook Resource - terraform-provider-spacelift"
4+
subcategory: ""
5+
description: |-
6+
spacelift_audit_trail_webhook represents a webhook endpoint to which Spacelift sends the POST request about events the user wants to track.
7+
---
8+
9+
# spacelift_audit_trail_webhook (Resource)
10+
11+
`spacelift_audit_trail_webhook` represents a webhook endpoint to which Spacelift sends the POST request about events the user wants to track.
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "spacelift_audit_trail_webhook" "example" {
17+
endpoint = "https://example.com"
18+
enabled = true
19+
secret = "mysecretkey"
20+
}
21+
```
22+
23+
<!-- schema generated by tfplugindocs -->
24+
## Schema
25+
26+
### Required
27+
28+
- `enabled` (Boolean)
29+
- `endpoint` (String)
30+
- `secret` (String, Sensitive)
31+
32+
### Optional
33+
34+
- `include_runs` (Boolean)
35+
36+
### Read-Only
37+
38+
- `id` (String) The ID of this resource.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
resource "spacelift_audit_trail_webhook" "example" {
2+
endpoint = "https://example.com"
3+
enabled = true
4+
secret = "mysecretkey"
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package structs
2+
3+
type AuditTrailWebhook struct {
4+
Enabled bool `graphql:"enabled"`
5+
Endpoint string `graphql:"endpoint"`
6+
IncludeRuns bool `graphql:"includeRuns"`
7+
Secret string `graphql:"secret"`
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package structs
2+
3+
import "github.com/shurcooL/graphql"
4+
5+
type AuditTrailWebhookInput struct {
6+
Enabled graphql.Boolean `json:"enabled"`
7+
Endpoint graphql.String `json:"endpoint"`
8+
IncludeRuns graphql.Boolean `json:"includeRuns"`
9+
Secret graphql.String `json:"secret"`
10+
}

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_worker_pools": dataWorkerPools(),
9999
},
100100
ResourcesMap: map[string]*schema.Resource{
101+
"spacelift_audit_trail_webhook": resourceAuditTrailWebhook(),
101102
"spacelift_aws_role": resourceAWSRole(),
102103
"spacelift_aws_integration": resourceAWSIntegration(),
103104
"spacelift_aws_integration_attachment": resourceAWSIntegrationAttachment(),
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package spacelift
2+
3+
import (
4+
"context"
5+
"time"
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+
)
13+
14+
func resourceAuditTrailWebhook() *schema.Resource {
15+
return &schema.Resource{
16+
Description: "" +
17+
"`spacelift_audit_trail_webhook` represents a webhook endpoint to which Spacelift " +
18+
"sends the POST request about events the user wants to track.",
19+
CreateContext: resourceAuditTrailWebhookCreate,
20+
ReadContext: resourceAuditTrailWebhookRead,
21+
UpdateContext: resourceAuditTrailWebhookUpdate,
22+
DeleteContext: resourceAuditTrailWebhookDelete,
23+
Importer: &schema.ResourceImporter{
24+
StateContext: schema.ImportStatePassthroughContext,
25+
},
26+
27+
Schema: map[string]*schema.Schema{
28+
"enabled": {
29+
Type: schema.TypeBool,
30+
Required: true,
31+
},
32+
"endpoint": {
33+
Type: schema.TypeString,
34+
Required: true,
35+
},
36+
"include_runs": {
37+
Type: schema.TypeBool,
38+
Optional: true,
39+
},
40+
"secret": {
41+
Type: schema.TypeString,
42+
Required: true,
43+
Sensitive: true,
44+
},
45+
},
46+
}
47+
}
48+
49+
func resourceAuditTrailWebhookCreate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
50+
var mutation struct {
51+
AuditTrailWebhook *structs.AuditTrailWebhook `graphql:"auditTrailSetWebhook(input: $input)"`
52+
}
53+
variables := map[string]interface{}{
54+
"input": structs.AuditTrailWebhookInput{
55+
Enabled: toBool(data.Get("enabled")),
56+
Endpoint: toString(data.Get("endpoint")),
57+
IncludeRuns: toBool(data.Get("include_runs")),
58+
Secret: toString(data.Get("secret")),
59+
},
60+
}
61+
if err := i.(*internal.Client).Mutate(ctx, "AuditTrailWebhookCreate", &mutation, variables); err != nil {
62+
return diag.Errorf("could not create audit trail webhook: %v", internal.FromSpaceliftError(err))
63+
}
64+
65+
data.SetId(time.Now().String())
66+
67+
return resourceAuditTrailWebhookRead(ctx, data, i)
68+
}
69+
70+
func resourceAuditTrailWebhookRead(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
71+
var query struct {
72+
AuditTrailWebhook *structs.AuditTrailWebhook `graphql:"auditTrailWebhook"`
73+
}
74+
if err := i.(*internal.Client).Query(ctx, "AuditTrailWebhookRead", &query, nil); err != nil {
75+
return diag.Errorf("could not query for audit trail webhook: %v", internal.FromSpaceliftError(err))
76+
}
77+
78+
if query.AuditTrailWebhook == nil {
79+
data.SetId("")
80+
return nil
81+
}
82+
83+
data.Set("enabled", query.AuditTrailWebhook.Enabled)
84+
data.Set("endpoint", query.AuditTrailWebhook.Endpoint)
85+
data.Set("include_runs", query.AuditTrailWebhook.IncludeRuns)
86+
data.Set("secret", query.AuditTrailWebhook.Secret)
87+
88+
return nil
89+
}
90+
91+
func resourceAuditTrailWebhookUpdate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
92+
var mutation struct {
93+
AuditTrailWebhook *structs.AuditTrailWebhook `graphql:"auditTrailSetWebhook(input: $input)"`
94+
}
95+
variables := map[string]interface{}{
96+
"input": structs.AuditTrailWebhookInput{
97+
Enabled: toBool(data.Get("enabled")),
98+
Endpoint: toString(data.Get("endpoint")),
99+
IncludeRuns: toBool(data.Get("include_runs")),
100+
Secret: toString(data.Get("secret")),
101+
},
102+
}
103+
if err := i.(*internal.Client).Mutate(ctx, "AuditTrailWebhookUpdate", &mutation, variables); err != nil {
104+
return diag.Errorf("could not update audit trail webhook: %v", internal.FromSpaceliftError(err))
105+
}
106+
107+
return resourceAuditTrailWebhookRead(ctx, data, i)
108+
}
109+
110+
func resourceAuditTrailWebhookDelete(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
111+
var mutation struct {
112+
AuditTrailWebhook *structs.AuditTrailWebhook `graphql:"auditTrailDeleteWebhook"`
113+
}
114+
if err := i.(*internal.Client).Mutate(ctx, "AuditTrailWebhookDelete", &mutation, nil); err != nil {
115+
return diag.Errorf("could not delete audit trail webhook: %v", internal.FromSpaceliftError(err))
116+
}
117+
118+
data.SetId("")
119+
120+
return nil
121+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package spacelift
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
10+
. "github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal/testhelpers"
11+
)
12+
13+
var auditTrailWebhookSimple = `
14+
resource "spacelift_audit_trail_webhook" "test" {
15+
enabled = true
16+
endpoint = "%s"
17+
include_runs = true
18+
secret = "secret"
19+
}
20+
`
21+
22+
func Test_resourceAuditTrailWebhook(t *testing.T) {
23+
const resourceName = "spacelift_audit_trail_webhook.test"
24+
25+
t.Run("creates an audit trail webhook without an error", func(t *testing.T) {
26+
testSteps(t, []resource.TestStep{
27+
{
28+
Config: fmt.Sprintf(auditTrailWebhookSimple, "https://example.com"),
29+
Check: Resource(
30+
resourceName,
31+
Attribute("enabled", Equals("true")),
32+
Attribute("endpoint", Equals("https://example.com")),
33+
Attribute("include_runs", Equals("true")),
34+
Attribute("secret", Equals("secret")),
35+
),
36+
},
37+
{
38+
ResourceName: resourceName,
39+
ImportState: true,
40+
ImportStateVerify: true,
41+
},
42+
})
43+
})
44+
45+
t.Run("cannot change endpoint", func(t *testing.T) {
46+
testSteps(t, []resource.TestStep{
47+
{
48+
Config: fmt.Sprintf(auditTrailWebhookSimple, "https://example2.com/"),
49+
ExpectError: regexp.MustCompile(`could not send webhook to given endpoint`),
50+
},
51+
})
52+
})
53+
}

0 commit comments

Comments
 (0)