-
Notifications
You must be signed in to change notification settings - Fork 601
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FLPROD-796: Create snippets api client
- Loading branch information
Denis Davydov
committed
Oct 22, 2024
1 parent
e2a1fae
commit f62fd6a
Showing
5 changed files
with
430 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:enhancement | ||
Add Snippets API client | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"mime/multipart" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/goccy/go-json" | ||
) | ||
|
||
type SnippetsResponse struct { | ||
Response | ||
Result []Snippet `json:"result"` | ||
} | ||
|
||
type Snippet struct { | ||
CreatedOn time.Time `json:"created_on"` | ||
ModifiedOn time.Time `json:"modified_on"` | ||
SnippetName string `json:"snippet_name"` | ||
} | ||
|
||
type SnippetFile struct { | ||
FileName string `json:"file_name"` | ||
Content string `json:"content"` | ||
} | ||
|
||
type SnippetRequest struct { | ||
SnippetName string `json:"snippet_name"` | ||
MainFile string `json:"main_file"` | ||
Files []SnippetFile `json:"files"` | ||
} | ||
|
||
func (api *API) ListZoneSnippets(ctx context.Context, rc *ResourceContainer) ([]Snippet, error) { | ||
if rc.Identifier == "" { | ||
return nil, ErrMissingZoneID | ||
} | ||
|
||
uri := buildURI(fmt.Sprintf("/zones/%s/snippets", rc.Identifier), nil) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
result := SnippetsResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
type SnippetMetadata struct { | ||
MainModule string `json:"main_module"` | ||
} | ||
|
||
func snippetMultipartBody(request SnippetRequest) (string, *bytes.Buffer, error) { | ||
body := new(bytes.Buffer) | ||
mw := multipart.NewWriter(body) | ||
defer mw.Close() | ||
|
||
for _, file := range request.Files { | ||
tp, err := mw.CreateFormFile(file.FileName, file.FileName) | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
_, err = tp.Write([]byte(file.Content)) | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
} | ||
|
||
tp, err := mw.CreateFormField("metadata") | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
|
||
if err = json.NewEncoder(tp).Encode(SnippetMetadata{ | ||
MainModule: request.MainFile, | ||
}); err != nil { | ||
return "", nil, err | ||
} | ||
|
||
return mw.Boundary(), body, nil | ||
} | ||
|
||
func (api *API) UpdateZoneSnippet(ctx context.Context, rc *ResourceContainer, params SnippetRequest) ([]Snippet, error) { | ||
if rc.Identifier == "" { | ||
return nil, ErrMissingZoneID | ||
} | ||
|
||
uri := fmt.Sprintf("/zones/%s/snippets/%s", rc.Identifier, params.SnippetName) | ||
|
||
boundary, body, err := snippetMultipartBody(params) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, body, http.Header{ | ||
"Content-Type": []string{fmt.Sprintf("multipart/form-data; boundary=%s", boundary)}, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
result := SnippetsResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return result.Result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/goccy/go-json" | ||
) | ||
|
||
type SnippetsRulesResponse struct { | ||
Response | ||
Result []SnippetRule `json:"result"` | ||
} | ||
|
||
type SnippetRule struct { | ||
ID string `json:"id"` | ||
Enabled *bool `json:"enabled,omitempty"` | ||
Expression string `json:"expression"` | ||
SnippetName string `json:"snippet_name"` | ||
Description string `json:"description"` | ||
} | ||
|
||
func (api *API) ListZoneSnippetsRules(ctx context.Context, rc *ResourceContainer) ([]SnippetRule, error) { | ||
if rc.Identifier == "" { | ||
return nil, ErrMissingZoneID | ||
} | ||
|
||
uri := buildURI(fmt.Sprintf("/zones/%s/snippets/rules", rc.Identifier), nil) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
result := SnippetsRulesResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
func (api *API) UpdateZoneSnippetsRules(ctx context.Context, rc *ResourceContainer, params []SnippetRule) ([]SnippetRule, error) { | ||
if rc.Identifier == "" { | ||
return nil, ErrMissingZoneID | ||
} | ||
|
||
uri := fmt.Sprintf("/zones/%s/snippets/rules", rc.Identifier) | ||
|
||
payload, err := json.Marshal(params) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, payload) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
result := SnippetsRulesResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return result.Result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestSnippetsRules(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) | ||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, `{ | ||
"result": [ | ||
{ | ||
"id": "some_id_1", | ||
"expression": "true", | ||
"enabled": true, | ||
"description": "some description", | ||
"snippet_name": "snippet_1" | ||
}, | ||
{ | ||
"id": "some_id_2", | ||
"expression": "true", | ||
"enabled": true, | ||
"description": "some description", | ||
"snippet_name": "snippet_2" | ||
} | ||
], | ||
"success": true, | ||
"errors": [], | ||
"messages": [] | ||
}`) | ||
} | ||
mux.HandleFunc("/zones/"+testZoneID+"/snippets/rules", handler) | ||
|
||
want := []SnippetRule{ | ||
{ | ||
ID: "some_id_1", | ||
Expression: "true", | ||
Enabled: BoolPtr(true), | ||
Description: "some description", | ||
SnippetName: "snippet_1", | ||
}, | ||
{ | ||
ID: "some_id_2", | ||
Expression: "true", | ||
Enabled: BoolPtr(true), | ||
Description: "some description", | ||
SnippetName: "snippet_2", | ||
}, | ||
} | ||
|
||
zoneActual, err := client.ListZoneSnippetsRules(context.Background(), ZoneIdentifier(testZoneID)) | ||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, zoneActual) | ||
} | ||
} | ||
|
||
func TestUpdateSnippetsRules(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) | ||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, `{ | ||
"result": [ | ||
{ | ||
"id": "some_id_1", | ||
"expression": "true", | ||
"enabled": false, | ||
"description": "some description", | ||
"snippet_name": "snippet_1" | ||
}, | ||
{ | ||
"id": "some_id_2", | ||
"expression": "true", | ||
"enabled": false, | ||
"description": "some description", | ||
"snippet_name": "snippet_2" | ||
} | ||
], | ||
"success": true, | ||
"errors": [], | ||
"messages": [] | ||
}`) | ||
} | ||
|
||
mux.HandleFunc("/zones/"+testZoneID+"/snippets/rules", handler) | ||
toUpdate := []SnippetRule{ | ||
{ | ||
Expression: "true", | ||
Enabled: BoolPtr(false), | ||
Description: "some description", | ||
SnippetName: "snippet_1", | ||
}, | ||
{ | ||
Expression: "true", | ||
Enabled: BoolPtr(false), | ||
Description: "some description", | ||
SnippetName: "snippet_2", | ||
}, | ||
} | ||
want := []SnippetRule{ | ||
{ | ||
ID: "some_id_1", | ||
Expression: "true", | ||
Enabled: BoolPtr(false), | ||
Description: "some description", | ||
SnippetName: "snippet_1", | ||
}, | ||
{ | ||
ID: "some_id_2", | ||
Expression: "true", | ||
Enabled: BoolPtr(false), | ||
Description: "some description", | ||
SnippetName: "snippet_2", | ||
}, | ||
} | ||
zoneActual, err := client.UpdateZoneSnippetsRules(context.Background(), ZoneIdentifier(testZoneID), toUpdate) | ||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, zoneActual) | ||
} | ||
} |
Oops, something went wrong.