Skip to content

Commit 4a43137

Browse files
committed
handle external challenge deletion
1 parent 970fbf3 commit 4a43137

File tree

7 files changed

+66
-106
lines changed

7 files changed

+66
-106
lines changed

.goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ builds:
33
flags:
44
- -trimpath
55
ldflags:
6-
- -s -w -X github.com/redpwn/terraform-provider-rctf/internal/version.Version={{.Version}}
6+
- -s -w -X {{ .ModulePath }}/internal/version.Version={{ .Version }}
77
goos:
88
- windows
99
- linux

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ require (
1414
github.com/Masterminds/semver v1.5.0 // indirect
1515
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
1616
github.com/agext/levenshtein v1.2.3 // indirect
17-
github.com/apparentlymart/go-textseg v1.0.0 // indirect
1817
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
1918
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
2019
github.com/aws/aws-sdk-go v1.25.3 // indirect

go.sum

Lines changed: 3 additions & 25 deletions
Large diffs are not rendered by default.

internal/provider/rctf.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package provider
22

33
import (
44
"context"
5+
56
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
67
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
78
"github.com/redpwn/terraform-provider-rctf/internal/rctf"

internal/provider/resource_challenge.go

Lines changed: 35 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package provider
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
7+
"regexp"
8+
69
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
710
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
811
"github.com/redpwn/terraform-provider-rctf/internal/rctf"
@@ -20,9 +23,7 @@ func resourceChallenge() *schema.Resource {
2023
Schema: map[string]*schema.Schema{
2124
"id": {
2225
Type: schema.TypeString,
23-
Optional: true,
2426
Computed: true,
25-
ForceNew: true,
2627
},
2728
"name": {
2829
Type: schema.TypeString,
@@ -82,9 +83,10 @@ func resourceChallenge() *schema.Resource {
8283
}
8384
}
8485

85-
func resourceChallengePut(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
86+
var idReg = regexp.MustCompile(`[^\w-]+`)
87+
88+
func resourceChallengePut(ctx context.Context, d *schema.ResourceData, m interface{}) (diags diag.Diagnostics) {
8689
r := m.(*rctf.Client)
87-
var diags diag.Diagnostics
8890
c := rctf.Challenge{
8991
Name: d.Get("name").(string),
9092
Description: d.Get("description").(string),
@@ -108,80 +110,54 @@ func resourceChallengePut(ctx context.Context, d *schema.ResourceData, m interfa
108110
}
109111
c.Id = d.Id()
110112
if c.Id == "" {
111-
c.Id = d.Get("id").(string)
112-
}
113-
if c.Id == "" {
114-
c.Id = fmt.Sprintf("%s-%s", c.Category, c.Name)
113+
c.Id = idReg.ReplaceAllString(fmt.Sprintf("%s-%s", c.Category, c.Name), "-")
114+
d.SetId(c.Id)
115+
d.Set("id", c.Id)
115116
}
116-
d.SetId(c.Id)
117117
if err := r.PutChallenge(ctx, c); err != nil {
118118
return diag.Errorf("put challenge: %s", err)
119119
}
120-
diags = append(diags, resourceChallengeRead(ctx, d, m)...)
121120
return diags
122121
}
123122

124-
func flattenFiles(files []rctf.ChallengeFile) []map[string]interface{} {
125-
var f []map[string]interface{}
126-
for _, file := range files {
127-
f = append(f, map[string]interface{}{
128-
"name": file.Name,
129-
"url": file.Url,
130-
})
131-
}
132-
return f
133-
}
134-
135-
func resourceChallengeRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
123+
func resourceChallengeRead(ctx context.Context, d *schema.ResourceData, m interface{}) (diags diag.Diagnostics) {
136124
r := m.(*rctf.Client)
137-
var diags diag.Diagnostics
138125
id := d.Id()
139126
c, err := r.Challenge(ctx, id)
140127
if err != nil {
128+
rctfErr := &rctf.Error{}
129+
if errors.As(err, rctfErr) && rctfErr.Kind == "badChallenge" {
130+
d.SetId("")
131+
return
132+
}
141133
return diag.Errorf("get challenge: %s", err)
142134
}
143-
if err := d.Set("id", c.Id); err != nil {
144-
return diag.FromErr(err)
145-
}
146-
if err := d.Set("name", c.Name); err != nil {
147-
return diag.FromErr(err)
148-
}
149-
if err := d.Set("description", c.Description); err != nil {
150-
return diag.FromErr(err)
151-
}
152-
if err := d.Set("category", c.Category); err != nil {
153-
return diag.FromErr(err)
154-
}
155-
if err := d.Set("author", c.Author); err != nil {
156-
return diag.FromErr(err)
157-
}
158-
if err := d.Set("file", flattenFiles(c.Files)); err != nil {
159-
return diag.FromErr(err)
160-
}
161-
if err := d.Set("min_points", c.Points.Min); err != nil {
162-
return diag.FromErr(err)
163-
}
164-
if err := d.Set("max_points", c.Points.Max); err != nil {
165-
return diag.FromErr(err)
166-
}
167-
if err := d.Set("flag", c.Flag); err != nil {
168-
return diag.FromErr(err)
169-
}
170-
if err := d.Set("tiebreak_eligible", c.TiebreakEligible); err != nil {
171-
return diag.FromErr(err)
172-
}
173-
if err := d.Set("sort_weight", c.SortWeight); err != nil {
174-
return diag.FromErr(err)
135+
d.Set("id", c.Id)
136+
d.Set("name", c.Name)
137+
d.Set("description", c.Description)
138+
d.Set("category", c.Category)
139+
d.Set("author", c.Author)
140+
var f []map[string]interface{}
141+
for _, file := range c.Files {
142+
f = append(f, map[string]interface{}{
143+
"name": file.Name,
144+
"url": file.Url,
145+
})
175146
}
176-
return diags
147+
d.Set("file", f)
148+
d.Set("min_points", c.Points.Min)
149+
d.Set("max_points", c.Points.Max)
150+
d.Set("flag", c.Flag)
151+
d.Set("tiebreak_eligible", c.TiebreakEligible)
152+
d.Set("sort_weight", c.SortWeight)
153+
return
177154
}
178155

179-
func resourceChallengeDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
156+
func resourceChallengeDelete(ctx context.Context, d *schema.ResourceData, m interface{}) (diags diag.Diagnostics) {
180157
r := m.(*rctf.Client)
181-
var diags diag.Diagnostics
182158
id := d.Id()
183159
if err := r.DeleteChallenge(ctx, id); err != nil {
184160
return diag.Errorf("delete challenge: %s", err)
185161
}
186-
return diags
162+
return
187163
}

internal/rctf/challenge.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package rctf
22

33
import (
44
"context"
5-
"errors"
65
"net/url"
76
)
87

@@ -48,21 +47,19 @@ func (c *Client) Challenge(ctx context.Context, id string) (Challenge, error) {
4847
return Challenge{}, err
4948
}
5049
if res.Kind != "goodChallenges" {
51-
return Challenge{}, errors.New(res.String())
50+
return Challenge{}, res.err()
5251
}
5352
return res.Data, nil
5453
}
5554

5655
func (c *Client) PutChallenge(ctx context.Context, challenge Challenge) error {
56+
req := challengeRequest{Data: challenge}
5757
res := response{}
58-
req := challengeRequest{
59-
Data: challenge,
60-
}
6158
if err := c.req(ctx, "PUT", challengeUrl(challenge.Id), &req, &res); err != nil {
6259
return err
6360
}
6461
if res.Kind != "goodChallengeUpdate" {
65-
return errors.New(res.String())
62+
return res.err()
6663
}
6764
return nil
6865
}
@@ -73,7 +70,7 @@ func (c *Client) DeleteChallenge(ctx context.Context, id string) error {
7370
return err
7471
}
7572
if res.Kind != "goodChallengeDelete" {
76-
return errors.New(res.String())
73+
return res.err()
7774
}
7875
return nil
7976
}

internal/rctf/client.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,31 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8-
"github.com/redpwn/terraform-provider-rctf/internal/version"
98
"net/http"
109
"net/url"
10+
11+
"github.com/redpwn/terraform-provider-rctf/internal/version"
1112
)
1213

1314
type Client struct {
14-
BaseUrl string
15-
AuthToken string
16-
http *http.Client
15+
BaseUrl string
16+
Header http.Header
17+
http *http.Client
1718
}
1819

1920
func New(baseUrl, authToken string) (*Client, error) {
2021
u, err := url.Parse(baseUrl)
2122
if err != nil {
2223
return nil, err
2324
}
25+
h := http.Header{}
26+
h.Set("user-agent", "terraform-provider-rctf/"+version.Version)
27+
h.Set("content-type", "application/json")
28+
h.Set("authorization", "Bearer "+authToken)
2429
c := &Client{
25-
BaseUrl: fmt.Sprintf("%s://%s/api/v1/", u.Scheme, u.Host),
26-
AuthToken: authToken,
27-
http: http.DefaultClient,
30+
BaseUrl: fmt.Sprintf("%s://%s/api/v1/", u.Scheme, u.Host),
31+
Header: h,
32+
http: http.DefaultClient,
2833
}
2934
return c, nil
3035
}
@@ -34,12 +39,18 @@ type response struct {
3439
Message string `json:"message"`
3540
}
3641

37-
func (r response) String() string {
38-
return fmt.Sprintf("rctf response: %s: %s", r.Kind, r.Message)
42+
type Error response
43+
44+
func (e Error) Error() string {
45+
return fmt.Sprintf("rctf error: %s: %s", e.Kind, e.Message)
46+
}
47+
48+
func (r response) err() error {
49+
return Error(r)
3950
}
4051

4152
func (c *Client) req(ctx context.Context, method, uri string, reqBody, resBody interface{}) error {
42-
body := new(bytes.Buffer)
53+
body := &bytes.Buffer{}
4354
if reqBody != nil {
4455
if err := json.NewEncoder(body).Encode(reqBody); err != nil {
4556
return err
@@ -49,9 +60,7 @@ func (c *Client) req(ctx context.Context, method, uri string, reqBody, resBody i
4960
if err != nil {
5061
return err
5162
}
52-
req.Header.Set("user-agent", "terraform-provider-rctf/"+version.Version)
53-
req.Header.Set("content-type", "application/json")
54-
req.Header.Set("authorization", "Bearer "+c.AuthToken)
63+
req.Header = c.Header
5564
res, err := c.http.Do(req)
5665
if err != nil {
5766
return fmt.Errorf("do request %s %s: %w", method, uri, err)

0 commit comments

Comments
 (0)