Skip to content

Commit 41ce2b5

Browse files
author
Alex Hung
authored
Merge pull request #106 from jfrog/fix-api-error-handling
Fix api error handling
2 parents 6529c0f + 13b00fe commit 41ce2b5

16 files changed

+284
-63
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 1.5.1 (March 14, 2024)
2+
3+
BUG FIXES:
4+
5+
* Fix HTTP response error handling due to change of behavior (for better consistency) from Resty client. PR: [#106](https://github.com/jfrog/terraform-provider-project/pull/106)
6+
17
## 1.5.0 (March 13, 2024)
28

39
FEATURES:

docs/resources/project.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,11 @@ Required:
141141
Optional:
142142

143143
- `description` (String)
144+
145+
## Import
146+
147+
Import is supported using the following syntax:
148+
149+
```shell
150+
terraform import project.myproject myproj
151+
```

examples/resources/project/import.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
terraform import project.myproject myproj

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0
1111
github.com/hashicorp/terraform-plugin-testing v1.7.0
1212
github.com/jfrog/terraform-provider-shared v1.22.0
13+
github.com/samber/lo v1.39.0
1314
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
1415
)
1516

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO
177177
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
178178
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
179179
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
180+
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
181+
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
180182
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
181183
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
182184
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=

pkg/project/membership.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package project
33
import (
44
"context"
55
"fmt"
6+
"net/http"
67

78
"github.com/hashicorp/terraform-plugin-log/tflog"
89
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -101,16 +102,21 @@ var readMembers = func(ctx context.Context, projectKey string, membershipType st
101102

102103
membership := Membership{}
103104

104-
_, err := m.(util.ProvderMetadata).Client.R().
105+
var projectError ProjectErrorsResponse
106+
resp, err := m.(util.ProvderMetadata).Client.R().
105107
SetPathParams(map[string]string{
106108
"projectKey": projectKey,
107109
"membershipType": membershipType,
108110
}).
109111
SetResult(&membership).
112+
SetError(&projectError).
110113
Get(projectMembershipsUrl)
111114
if err != nil {
112115
return nil, err
113116
}
117+
if resp.IsError() {
118+
return nil, fmt.Errorf("%s", projectError.String())
119+
}
114120

115121
tflog.Trace(ctx, fmt.Sprintf("readMembers: %+v\n", membership))
116122

@@ -163,14 +169,22 @@ var updateMember = func(ctx context.Context, projectKey string, membershipType s
163169
return fmt.Errorf("invalid membershipType: %s", membershipType)
164170
}
165171

166-
_, err := m.(util.ProvderMetadata).Client.R().
172+
var projectError ProjectErrorsResponse
173+
resp, err := m.(util.ProvderMetadata).Client.R().
167174
SetPathParams(map[string]string{
168175
"projectKey": projectKey,
169176
"membershipType": membershipType,
170177
"memberName": member.Name,
171178
}).
172179
SetBody(member).
180+
SetError(&projectError).
173181
Put(projectMembershipUrl)
182+
if err != nil {
183+
return err
184+
}
185+
if resp.IsError() {
186+
return fmt.Errorf("%s", projectError.String())
187+
}
174188

175189
return err
176190
}
@@ -196,16 +210,21 @@ var deleteMember = func(ctx context.Context, projectKey string, membershipType s
196210
return fmt.Errorf("invalid membershipType: %s", membershipType)
197211
}
198212

199-
_, err := m.(util.ProvderMetadata).Client.R().
213+
var projectError ProjectErrorsResponse
214+
resp, err := m.(util.ProvderMetadata).Client.R().
200215
SetPathParams(map[string]string{
201216
"projectKey": projectKey,
202217
"membershipType": membershipType,
203218
"memberName": member.Name,
204219
}).
220+
SetError(&projectError).
205221
Delete(projectMembershipUrl)
206222
if err != nil {
207223
return err
208224
}
225+
if resp.IsError() && resp.StatusCode() != http.StatusNotFound {
226+
return fmt.Errorf("%s", projectError.String())
227+
}
209228

210229
return nil
211230
}

pkg/project/repo.go

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,19 @@ var readRepos = func(ctx context.Context, projectKey string, m interface{}) ([]R
5454

5555
artifactoryRepos := []ArtifactoryRepo{}
5656

57-
_, err := m.(util.ProvderMetadata).Client.R().
57+
var projectError ProjectErrorsResponse
58+
resp, err := m.(util.ProvderMetadata).Client.R().
5859
SetPathParam("projectKey", projectKey).
5960
SetResult(&artifactoryRepos).
61+
SetError(&projectError).
6062
Get("/artifactory/api/repositories?project={projectKey}")
6163

6264
if err != nil {
6365
return nil, err
6466
}
67+
if resp.IsError() {
68+
return nil, fmt.Errorf("%s", projectError.String())
69+
}
6570

6671
tflog.Trace(ctx, fmt.Sprintf("artifactoryRepos: %+v\n", artifactoryRepos))
6772

@@ -127,13 +132,21 @@ var addRepos = func(ctx context.Context, projectKey string, repoKeys []RepoKey,
127132
var addRepo = func(ctx context.Context, projectKey string, repoKey RepoKey, req *resty.Request) error {
128133
tflog.Debug(ctx, fmt.Sprintf("addRepo: %s", repoKey))
129134

130-
_, err := req.
135+
var projectError ProjectErrorsResponse
136+
resp, err := req.
131137
SetPathParams(map[string]string{
132138
"projectKey": projectKey,
133139
"repoKey": string(repoKey),
134140
}).
135141
SetQueryParam("force", "true").
142+
SetError(&projectError).
136143
Put(projectsUrl + "/_/attach/repositories/{repoKey}/{projectKey}")
144+
if err != nil {
145+
return err
146+
}
147+
if resp.IsError() {
148+
return fmt.Errorf("%s", projectError.String())
149+
}
137150

138151
return err
139152
}
@@ -159,32 +172,28 @@ var deleteRepos = func(ctx context.Context, repoKeys []RepoKey, m interface{}) e
159172
var deleteRepo = func(ctx context.Context, repoKey RepoKey, req *resty.Request) error {
160173
tflog.Debug(ctx, fmt.Sprintf("deleteRepo: %s", repoKey))
161174

162-
type Error struct {
163-
Code string `json:"code"`
164-
Message string `json:"message"`
165-
}
166-
167-
type ErrorResponse struct {
168-
Errors []Error `json:"errors"`
169-
}
170-
171-
var errorResp ErrorResponse
172-
175+
var projectError ProjectErrorsResponse
173176
resp, err := req.
174177
SetPathParam("repoKey", string(repoKey)).
175-
SetError(&errorResp).
178+
SetError(&projectError).
176179
Delete(projectsUrl + "/_/attach/repositories/{repoKey}")
177180

181+
if err != nil {
182+
return err
183+
}
184+
178185
// Ignore 404 NOT_FOUND error when unassigning repo from project
179186
// Possible that repo was deleted out-of-band from TF
180-
if resp.StatusCode() == http.StatusNotFound && len(errorResp.Errors) > 0 {
181-
for _, error := range errorResp.Errors {
182-
if error.Code == "NOT_FOUND" {
183-
tflog.Warn(ctx, fmt.Sprintf("failed to unassign repo: %s", error.Message))
187+
if resp.StatusCode() == http.StatusNotFound && len(projectError.Errors) > 0 {
188+
for _, e := range projectError.Errors {
189+
if e.Code == "NOT_FOUND" {
190+
tflog.Warn(ctx, fmt.Sprintf("failed to unassign repo: %s", e.Message))
184191
return nil
185192
}
186193
}
194+
} else if resp.IsError() {
195+
return fmt.Errorf("%s", projectError.String())
187196
}
188197

189-
return err
198+
return nil
190199
}

pkg/project/resource_project.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,23 @@ func projectResource() *schema.Resource {
437437
var readProject = func(ctx context.Context, data *schema.ResourceData, m interface{}) diag.Diagnostics {
438438
project := Project{}
439439

440-
_, err := m.(util.ProvderMetadata).Client.R().
440+
var projectError ProjectErrorsResponse
441+
resp, err := m.(util.ProvderMetadata).Client.R().
441442
SetPathParam("projectKey", data.Id()).
442443
SetResult(&project).
444+
SetError(&projectError).
443445
Get(projectUrl)
446+
444447
if err != nil {
445448
return diag.FromErr(err)
446449
}
450+
if resp.StatusCode() == http.StatusNotFound {
451+
data.SetId("")
452+
return nil
453+
}
454+
if resp.IsError() {
455+
return diag.Errorf("%s", projectError.String())
456+
}
447457

448458
users := []Member{}
449459
useProjectUserResource := data.Get("use_project_user_resource").(bool)
@@ -493,12 +503,17 @@ func projectResource() *schema.Resource {
493503
return diag.FromErr(err)
494504
}
495505

496-
_, err = m.(util.ProvderMetadata).Client.R().
506+
var projectError ProjectErrorsResponse
507+
resp, err := m.(util.ProvderMetadata).Client.R().
497508
SetBody(project).
509+
SetError(&projectError).
498510
Post(projectsUrl)
499511
if err != nil {
500512
return diag.FromErr(err)
501513
}
514+
if resp.IsError() {
515+
return diag.Errorf("%s", projectError.String())
516+
}
502517

503518
data.SetId(project.Id())
504519

@@ -547,13 +562,18 @@ func projectResource() *schema.Resource {
547562
return diag.FromErr(err)
548563
}
549564

550-
_, err = m.(util.ProvderMetadata).Client.R().
565+
var projectError ProjectErrorsResponse
566+
resp, err := m.(util.ProvderMetadata).Client.R().
551567
SetPathParam("projectKey", data.Id()).
552568
SetBody(project).
569+
SetError(&projectError).
553570
Put(projectUrl)
554571
if err != nil {
555572
return diag.FromErr(err)
556573
}
574+
if resp.IsError() {
575+
return diag.Errorf("%s", projectError.String())
576+
}
557577

558578
data.SetId(project.Id())
559579

@@ -615,16 +635,22 @@ func projectResource() *schema.Resource {
615635
},
616636
)
617637

618-
resp, err := req.
638+
var projectError ProjectErrorsResponse
639+
res, err := req.
619640
SetPathParam("projectKey", data.Id()).
641+
SetError(&projectError).
620642
Delete(projectUrl)
621643

622644
if err != nil {
623-
if resp.StatusCode() == http.StatusNotFound {
624-
data.SetId("")
625-
}
626645
return diag.FromErr(err)
627646
}
647+
if res.StatusCode() == http.StatusNotFound {
648+
data.SetId("")
649+
return nil
650+
}
651+
if res.IsError() {
652+
return diag.Errorf("%s", projectError.String())
653+
}
628654

629655
return nil
630656
}

pkg/project/resource_project_environment.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package project
33
import (
44
"context"
55
"fmt"
6+
"net/http"
67
"regexp"
78
"strings"
89

@@ -57,13 +58,22 @@ func projectEnvironmentResource() *schema.Resource {
5758
projectKey := data.Get("project_key").(string)
5859
var envs []ProjectEnvironment
5960

60-
_, err := m.(util.ProvderMetadata).Client.R().
61+
var projectError ProjectErrorsResponse
62+
resp, err := m.(util.ProvderMetadata).Client.R().
6163
SetPathParam("projectKey", projectKey).
6264
SetResult(&envs).
65+
SetError(&projectError).
6366
Get(projectEnvironmentUrl)
6467
if err != nil {
6568
return diag.FromErr(err)
6669
}
70+
if resp.StatusCode() == http.StatusNotFound {
71+
data.SetId("")
72+
return nil
73+
}
74+
if resp.IsError() {
75+
return diag.Errorf("%s", projectError.String())
76+
}
6777

6878
var matchedEnv *ProjectEnvironment
6979
for _, env := range envs {
@@ -91,13 +101,18 @@ func projectEnvironmentResource() *schema.Resource {
91101
Name: fmt.Sprintf("%s-%s", projectKey, data.Get("name").(string)),
92102
}
93103

94-
_, err := m.(util.ProvderMetadata).Client.R().
104+
var projectError ProjectErrorsResponse
105+
resp, err := m.(util.ProvderMetadata).Client.R().
95106
SetPathParam("projectKey", projectKey).
96107
SetBody(projectEnvironment).
108+
SetError(&projectError).
97109
Post(projectEnvironmentUrl)
98110
if err != nil {
99111
return diag.FromErr(err)
100112
}
113+
if resp.IsError() {
114+
return diag.Errorf("%s", projectError.String())
115+
}
101116

102117
data.SetId(projectEnvironment.Id())
103118

@@ -112,16 +127,21 @@ func projectEnvironmentResource() *schema.Resource {
112127
NewName: fmt.Sprintf("%s-%s", projectKey, newName),
113128
}
114129

115-
_, err := m.(util.ProvderMetadata).Client.R().
130+
var projectError ProjectErrorsResponse
131+
resp, err := m.(util.ProvderMetadata).Client.R().
116132
SetPathParams(map[string]string{
117133
"projectKey": projectKey,
118134
"environmentName": fmt.Sprintf("%s-%s", projectKey, oldName),
119135
}).
120136
SetBody(projectEnvironmentUpdate).
137+
SetError(&projectError).
121138
Post(projectEnvironmentUrl + "/{environmentName}/rename")
122139
if err != nil {
123140
return diag.FromErr(err)
124141
}
142+
if resp.IsError() {
143+
return diag.Errorf("%s", projectError.String())
144+
}
125145

126146
data.SetId(projectEnvironmentUpdate.Id())
127147
data.Set("name", newName)
@@ -131,15 +151,21 @@ func projectEnvironmentResource() *schema.Resource {
131151

132152
var deleteProjectEnvironment = func(ctx context.Context, data *schema.ResourceData, m interface{}) diag.Diagnostics {
133153
projectKey := data.Get("project_key").(string)
134-
_, err := m.(util.ProvderMetadata).Client.R().
154+
155+
var projectError ProjectErrorsResponse
156+
resp, err := m.(util.ProvderMetadata).Client.R().
135157
SetPathParams(map[string]string{
136158
"projectKey": projectKey,
137159
"environmentName": fmt.Sprintf("%s-%s", projectKey, data.Get("name")),
138160
}).
161+
SetError(&projectError).
139162
Delete(projectEnvironmentUrl + "/{environmentName}")
140163
if err != nil {
141164
return diag.FromErr(err)
142165
}
166+
if resp.IsError() && resp.StatusCode() != http.StatusNotFound {
167+
return diag.Errorf("%s", projectError.String())
168+
}
143169

144170
data.SetId("")
145171

0 commit comments

Comments
 (0)