Skip to content

Commit f513372

Browse files
committed
Add new resource sentry_release_deployment
This resource creates a new deployment for a specific release and environment in sentry.
1 parent 3bf565e commit f513372

File tree

5 files changed

+282
-5
lines changed

5 files changed

+282
-5
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/hashicorp/terraform-plugin-docs v0.13.0
1010
github.com/hashicorp/terraform-plugin-log v0.7.0
1111
github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1
12-
github.com/jianyuan/go-sentry/v2 v2.2.0
12+
github.com/jianyuan/go-sentry/v2 v2.3.0
1313
github.com/mitchellh/mapstructure v1.5.0
1414
golang.org/x/oauth2 v0.4.0
1515
golang.org/x/sync v0.1.0

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
8080
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
8181
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
8282
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
83-
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
84-
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
8583
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 h1:Ud/6/AdmJ1R7ibdS0Wo5MWPj0T1R0fkpaD087bBaW8I=
8684
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
8785
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
@@ -136,8 +134,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
136134
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
137135
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
138136
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
139-
github.com/jianyuan/go-sentry/v2 v2.2.0 h1:yAJxTjEBFLh/3ED8n4XiheaeadPaeBuMr8owTq1ZUJE=
140-
github.com/jianyuan/go-sentry/v2 v2.2.0/go.mod h1:OZZZB/l6QO4g1qzLWiW4wu6KvOBSmebOnskOr4Uc99o=
137+
github.com/jianyuan/go-sentry/v2 v2.3.0 h1:uUz/nNCxrtq+SRNJrSY1ORc5rBx7rq+uQZn2fwH6gSU=
138+
github.com/jianyuan/go-sentry/v2 v2.3.0/go.mod h1:OZZZB/l6QO4g1qzLWiW4wu6KvOBSmebOnskOr4Uc99o=
141139
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
142140
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
143141
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=

sentry/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func NewProvider(version string) func() *schema.Provider {
4747
"sentry_organization": resourceSentryOrganization(),
4848
"sentry_plugin": resourceSentryPlugin(),
4949
"sentry_project": resourceSentryProject(),
50+
"sentry_release_deployment": resourceSentryReleaseDeployment(),
5051
"sentry_rule": resourceSentryRule(),
5152
"sentry_team": resourceSentryTeam(),
5253
},
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package sentry
2+
3+
import (
4+
"context"
5+
"sort"
6+
7+
"github.com/hashicorp/go-multierror"
8+
"github.com/hashicorp/terraform-plugin-log/tflog"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/jianyuan/go-sentry/v2/sentry"
12+
)
13+
14+
func resourceSentryReleaseDeployment() *schema.Resource {
15+
return &schema.Resource{
16+
CreateContext: resourceSentryReleaseDeploymentCreate,
17+
ReadContext: resourceSentryReleaseDeploymentRead,
18+
UpdateContext: resourceSentryReleaseDeploymentUpdate,
19+
DeleteContext: resourceSentryReleaseDeploymentDelete,
20+
21+
Importer: &schema.ResourceImporter{
22+
StateContext: schema.ImportStatePassthroughContext,
23+
},
24+
25+
Schema: map[string]*schema.Schema{
26+
"organization": {
27+
Description: "The slug of the organization the deploy belongs to.",
28+
Type: schema.TypeString,
29+
Required: true,
30+
},
31+
"version": {
32+
Description: "The version identifier of the release.",
33+
Type: schema.TypeString,
34+
Required: true,
35+
},
36+
"environment": {
37+
Type: schema.TypeString,
38+
Required: true,
39+
Description: "The environment this deployment is for.",
40+
},
41+
"url": {
42+
Description: "The optional URL that points to the deploy.",
43+
Type: schema.TypeString,
44+
Optional: true,
45+
},
46+
"name": {
47+
Description: "The optional name of the deploy.",
48+
Type: schema.TypeString,
49+
Optional: true,
50+
},
51+
"projects": {
52+
Description: "The optional list of projects to deploy.",
53+
Type: schema.TypeList,
54+
Elem: &schema.Schema{
55+
Type: schema.TypeString,
56+
},
57+
Optional: true,
58+
},
59+
},
60+
}
61+
}
62+
63+
func resourceSentryReleaseDeploymentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
64+
client := meta.(*sentry.Client)
65+
66+
org := d.Get("organization").(string)
67+
version := d.Get("version").(string)
68+
params := releaseDeploymentCreateParams(d)
69+
70+
deploy, _, err := client.ReleaseDeployments.Create(ctx, org, version, params)
71+
if err != nil {
72+
return diag.FromErr(err)
73+
}
74+
75+
d.SetId(buildThreePartID(org, version, deploy.ID))
76+
return resourceSentryReleaseDeploymentRead(ctx, d, meta)
77+
}
78+
79+
func resourceSentryReleaseDeploymentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
80+
client := meta.(*sentry.Client)
81+
82+
org, release, deployID, err := splitSentryReleaseDeploymentID(d.Id())
83+
84+
tflog.Debug(ctx, "Reading release deployment", map[string]interface{}{
85+
"org": org,
86+
"release": release,
87+
"deployID": deployID,
88+
})
89+
deploy, resp, err := client.ReleaseDeployments.Get(ctx, org, release, deployID)
90+
if found, err := checkClientGet(resp, err, d); !found {
91+
tflog.Info(ctx, "Removed deployment from state because it no longer exists in Sentry", map[string]interface{}{
92+
"org": org,
93+
"release": release,
94+
"deployID": deployID,
95+
})
96+
return diag.FromErr(err)
97+
}
98+
99+
sort.Strings(deploy.Projects)
100+
101+
d.SetId(buildThreePartID(org, release, deploy.ID))
102+
retErr := multierror.Append(
103+
d.Set("organization", org),
104+
d.Set("version", release),
105+
d.Set("environment", deploy.Environment),
106+
d.Set("url", deploy.URL),
107+
d.Set("name", deploy.Name),
108+
d.Set("projects", deploy.Projects),
109+
)
110+
return diag.FromErr(retErr.ErrorOrNil())
111+
}
112+
113+
func resourceSentryReleaseDeploymentUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
114+
client := meta.(*sentry.Client)
115+
116+
// Since we cannot update or delete deployments we create a new deployment
117+
// when an update is needed
118+
org := d.Get("organization").(string)
119+
version := d.Get("version").(string)
120+
params := releaseDeploymentCreateParams(d)
121+
122+
deploy, _, err := client.ReleaseDeployments.Create(ctx, org, version, params)
123+
if err != nil {
124+
return diag.FromErr(err)
125+
}
126+
127+
d.SetId(buildThreePartID(org, version, deploy.ID))
128+
return resourceSentryReleaseDeploymentRead(ctx, d, meta)
129+
}
130+
131+
func resourceSentryReleaseDeploymentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
132+
org, release, deployID, err := splitSentryReleaseDeploymentID(d.Id())
133+
if err != nil {
134+
return diag.FromErr(err)
135+
}
136+
137+
tflog.Debug(ctx, "Deleting deployment", map[string]interface{}{
138+
"org": org,
139+
"release": release,
140+
"deployID": deployID,
141+
})
142+
143+
// Sentry has no option to delete a deployment. So we skip this and just
144+
// remove it from the terraform state
145+
return nil
146+
}
147+
148+
func splitSentryReleaseDeploymentID(id string) (org, release, deployID string, err error) {
149+
org, release, deployID, err = splitThreePartID(id, "organization-id", "release", "deploy-id")
150+
return
151+
}
152+
153+
func releaseDeploymentCreateParams(d *schema.ResourceData) *sentry.ReleaseDeployment {
154+
params := &sentry.ReleaseDeployment{
155+
Environment: d.Get("environment").(string),
156+
}
157+
if v := d.Get("name").(string); v != "" {
158+
params.Name = sentry.String(v)
159+
}
160+
if v := d.Get("url").(string); v != "" {
161+
params.URL = sentry.String(v)
162+
}
163+
if v, ok := d.GetOk("projects"); ok {
164+
projects := expandStringList(v.([]interface{}))
165+
if len(projects) > 0 {
166+
params.Projects = projects
167+
}
168+
}
169+
return params
170+
171+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package sentry
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
11+
"github.com/jianyuan/go-sentry/v2/sentry"
12+
)
13+
14+
func TestAccSentryReleaseDeployment_basic(t *testing.T) {
15+
rn := "sentry_organization_member.john_doe"
16+
environment := "test"
17+
18+
check := func(role string) resource.TestCheckFunc {
19+
var deploy sentry.ReleaseDeployment
20+
return resource.ComposeTestCheckFunc(
21+
testAccCheckSentryReleaseDeploymentExists(rn, &deploy),
22+
resource.TestCheckResourceAttr(rn, "organization", testOrganization),
23+
resource.TestCheckResourceAttr(rn, "version", "0.1.0"),
24+
)
25+
}
26+
27+
resource.Test(t, resource.TestCase{
28+
PreCheck: func() { testAccPreCheck(t) },
29+
ProviderFactories: testAccProviderFactories,
30+
CheckDestroy: testAccCheckSentryReleaseDeploymentDestroy,
31+
Steps: []resource.TestStep{
32+
{
33+
Config: testAccSentryReleaseDeploymentConfig("0.1.0", environment),
34+
Check: check("member"),
35+
},
36+
{
37+
Config: testAccSentryReleaseDeploymentConfig("0.2.0", environment),
38+
Check: check("manager"),
39+
},
40+
},
41+
})
42+
}
43+
44+
func testAccCheckSentryReleaseDeploymentDestroy(s *terraform.State) error {
45+
client := testAccProvider.Meta().(*sentry.Client)
46+
47+
for _, rs := range s.RootModule().Resources {
48+
if rs.Type != "sentry_release_deployment" {
49+
continue
50+
}
51+
52+
ctx := context.Background()
53+
deploy, resp, err := client.ReleaseDeployments.Get(
54+
ctx,
55+
rs.Primary.Attributes["organization"],
56+
rs.Primary.Attributes["version"],
57+
rs.Primary.ID,
58+
)
59+
if err == nil {
60+
if deploy != nil {
61+
return errors.New("release deployment still exists")
62+
}
63+
}
64+
if resp.StatusCode != 404 {
65+
return err
66+
}
67+
return nil
68+
}
69+
return nil
70+
}
71+
72+
func testAccCheckSentryReleaseDeploymentExists(n string, deploy *sentry.ReleaseDeployment) resource.TestCheckFunc {
73+
return func(s *terraform.State) error {
74+
rs, ok := s.RootModule().Resources[n]
75+
if !ok {
76+
return fmt.Errorf("not found: %s", n)
77+
}
78+
79+
if rs.Primary.ID == "" {
80+
return errors.New("no deploy ID is set")
81+
}
82+
83+
org, version, id, err := splitSentryReleaseDeploymentID(rs.Primary.ID)
84+
if err != nil {
85+
return err
86+
}
87+
client := testAccProvider.Meta().(*sentry.Client)
88+
ctx := context.Background()
89+
gotDeployment, _, err := client.ReleaseDeployments.Get(ctx, org, version, id)
90+
91+
if err != nil {
92+
return err
93+
}
94+
*deploy = *gotDeployment
95+
return nil
96+
}
97+
}
98+
99+
func testAccSentryReleaseDeploymentConfig(version, environment string) string {
100+
return testAccSentryOrganizationDataSourceConfig + fmt.Sprintf(`
101+
resource "sentry_release_deployment" "my-release" {
102+
organization = data.sentry_organization.test.id
103+
version = "%[1]s"
104+
environment = "%[2]s"
105+
}
106+
`, version, environment)
107+
}

0 commit comments

Comments
 (0)