-
Notifications
You must be signed in to change notification settings - Fork 611
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1494 from hwrdprkns/cloudflare_images_variants
Add CRUD support for Images Variants
- Loading branch information
Showing
5 changed files
with
397 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 | ||
images_variants: Add support for Images Variants CRUD operations | ||
``` |
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,163 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/goccy/go-json" | ||
) | ||
|
||
type ImagesVariant struct { | ||
ID string `json:"id,omitempty"` | ||
NeverRequireSignedURLs *bool `json:"neverRequireSignedURLs,omitempty"` | ||
Options ImagesVariantsOptions `json:"options,omitempty"` | ||
} | ||
|
||
type ImagesVariantsOptions struct { | ||
Fit string `json:"fit,omitempty"` | ||
Height int `json:"height,omitempty"` | ||
Metadata string `json:"metadata,omitempty"` | ||
Width int `json:"width,omitempty"` | ||
} | ||
|
||
type ListImageVariantsParams struct{} | ||
|
||
type ListImagesVariantsResponse struct { | ||
Result ListImageVariantsResult `json:"result,omitempty"` | ||
Response | ||
} | ||
|
||
type ListImageVariantsResult struct { | ||
ImagesVariants map[string]ImagesVariant `json:"variants,omitempty"` | ||
} | ||
|
||
type CreateImagesVariantParams struct { | ||
ID string `json:"id,omitempty"` | ||
NeverRequireSignedURLs *bool `json:"neverRequireSignedURLs,omitempty"` | ||
Options ImagesVariantsOptions `json:"options,omitempty"` | ||
} | ||
|
||
type UpdateImagesVariantParams struct { | ||
ID string `json:"-"` | ||
NeverRequireSignedURLs *bool `json:"neverRequireSignedURLs,omitempty"` | ||
Options ImagesVariantsOptions `json:"options,omitempty"` | ||
} | ||
|
||
type ImagesVariantResult struct { | ||
Variant ImagesVariant `json:"variant,omitempty"` | ||
} | ||
|
||
type ImagesVariantResponse struct { | ||
Result ImagesVariantResult `json:"result,omitempty"` | ||
Response | ||
} | ||
|
||
// Lists existing variants. | ||
// | ||
// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-variants-list-variants | ||
func (api *API) ListImagesVariants(ctx context.Context, rc *ResourceContainer, params ListImageVariantsParams) (ListImageVariantsResult, error) { | ||
if rc.Identifier == "" { | ||
return ListImageVariantsResult{}, ErrMissingAccountID | ||
} | ||
|
||
baseURL := fmt.Sprintf("/accounts/%s/images/v1/variants", rc.Identifier) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, baseURL, nil) | ||
if err != nil { | ||
return ListImageVariantsResult{}, err | ||
} | ||
|
||
var listImageVariantsResponse ListImagesVariantsResponse | ||
err = json.Unmarshal(res, &listImageVariantsResponse) | ||
if err != nil { | ||
return ListImageVariantsResult{}, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return listImageVariantsResponse.Result, nil | ||
} | ||
|
||
// Fetch details for a single variant. | ||
// | ||
// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-variants-variant-details | ||
func (api *API) GetImagesVariant(ctx context.Context, rc *ResourceContainer, variantID string) (ImagesVariant, error) { | ||
if rc.Identifier == "" { | ||
return ImagesVariant{}, ErrMissingAccountID | ||
} | ||
|
||
baseURL := fmt.Sprintf("/accounts/%s/images/v1/variants/%s", rc.Identifier, variantID) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, baseURL, nil) | ||
if err != nil { | ||
return ImagesVariant{}, err | ||
} | ||
|
||
var imagesVariantDetailResponse ImagesVariantResponse | ||
err = json.Unmarshal(res, &imagesVariantDetailResponse) | ||
if err != nil { | ||
return ImagesVariant{}, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return imagesVariantDetailResponse.Result.Variant, nil | ||
} | ||
|
||
// Specify variants that allow you to resize images for different use cases. | ||
// | ||
// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-variants-create-a-variant | ||
func (api *API) CreateImagesVariant(ctx context.Context, rc *ResourceContainer, params CreateImagesVariantParams) (ImagesVariant, error) { | ||
if rc.Identifier == "" { | ||
return ImagesVariant{}, ErrMissingAccountID | ||
} | ||
|
||
baseURL := fmt.Sprintf("/accounts/%s/images/v1/variants", rc.Identifier) | ||
res, err := api.makeRequestContext(ctx, http.MethodPost, baseURL, params) | ||
if err != nil { | ||
return ImagesVariant{}, err | ||
} | ||
|
||
var createImagesVariantResponse ImagesVariantResponse | ||
err = json.Unmarshal(res, &createImagesVariantResponse) | ||
if err != nil { | ||
return ImagesVariant{}, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return createImagesVariantResponse.Result.Variant, nil | ||
} | ||
|
||
// Deleting a variant purges the cache for all images associated with the variant. | ||
// | ||
// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-variants-variant-details | ||
func (api *API) DeleteImagesVariant(ctx context.Context, rc *ResourceContainer, variantID string) error { | ||
if rc.Identifier == "" { | ||
return ErrMissingAccountID | ||
} | ||
|
||
baseURL := fmt.Sprintf("/accounts/%s/images/v1/variants/%s", rc.Identifier, variantID) | ||
_, err := api.makeRequestContext(ctx, http.MethodDelete, baseURL, nil) | ||
if err != nil { | ||
return fmt.Errorf("%s: %w", errMakeRequestError, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Updating a variant purges the cache for all images associated with the variant. | ||
// | ||
// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-variants-variant-details | ||
func (api *API) UpdateImagesVariant(ctx context.Context, rc *ResourceContainer, params UpdateImagesVariantParams) (ImagesVariant, error) { | ||
if rc.Identifier == "" { | ||
return ImagesVariant{}, ErrMissingAccountID | ||
} | ||
|
||
baseURL := fmt.Sprintf("/accounts/%s/images/v1/variants/%s", rc.Identifier, params.ID) | ||
res, err := api.makeRequestContext(ctx, http.MethodPatch, baseURL, params) | ||
if err != nil { | ||
return ImagesVariant{}, err | ||
} | ||
|
||
var imagesVariantDetailResponse ImagesVariantResponse | ||
err = json.Unmarshal(res, &imagesVariantDetailResponse) | ||
if err != nil { | ||
return ImagesVariant{}, fmt.Errorf("%s: %w", errUnmarshalError, err) | ||
} | ||
|
||
return imagesVariantDetailResponse.Result.Variant, 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,195 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
const ( | ||
testImagesVariantID = "hero" | ||
) | ||
|
||
func TestImageVariants_List(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, loadFixture("images_variants", "single_list")) | ||
} | ||
|
||
mux.HandleFunc("/accounts/"+testAccountID+"/images/v1/variants", handler) | ||
|
||
want := ListImageVariantsResult{ | ||
ImagesVariants: map[string]ImagesVariant{ | ||
"hero": { | ||
ID: "hero", | ||
NeverRequireSignedURLs: BoolPtr(true), | ||
Options: ImagesVariantsOptions{ | ||
Fit: "scale-down", | ||
Height: 768, | ||
Width: 1366, | ||
Metadata: "none", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
got, err := client.ListImagesVariants(context.Background(), AccountIdentifier(testAccountID), ListImageVariantsParams{}) | ||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, got) | ||
} | ||
} | ||
|
||
func TestImageVariants_Delete(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
assert.Equal(t, http.MethodDelete, r.Method, "Expected method '%s', got %s", http.MethodDelete, r.Method) | ||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, `{ | ||
"success": true, | ||
"errors": [], | ||
"messages": [], | ||
"result": {} | ||
}`) | ||
} | ||
|
||
url := fmt.Sprintf("/accounts/%s/images/v1/variants/%s", testAccountID, testImagesVariantID) | ||
mux.HandleFunc(url, handler) | ||
|
||
err := client.DeleteImagesVariant(context.Background(), AccountIdentifier(testAccountID), testImagesVariantID) | ||
assert.NoError(t, err) | ||
} | ||
|
||
func TestImagesVariants_Get(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
assert.Equal(t, http.MethodGet, r.Method, "Expected method '%s', got %s", http.MethodGet, r.Method) | ||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, loadFixture("images_variants", "single_full")) | ||
} | ||
|
||
url := fmt.Sprintf("/accounts/%s/images/v1/variants/%s", testAccountID, testImagesVariantID) | ||
mux.HandleFunc(url, handler) | ||
|
||
want := ImagesVariant{ | ||
ID: "hero", | ||
NeverRequireSignedURLs: BoolPtr(true), | ||
Options: ImagesVariantsOptions{ | ||
Fit: "scale-down", | ||
Height: 768, | ||
Width: 1366, | ||
Metadata: "none", | ||
}, | ||
} | ||
|
||
got, err := client.GetImagesVariant(context.Background(), AccountIdentifier(testAccountID), testImagesVariantID) | ||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, got) | ||
} | ||
} | ||
|
||
func TestImagesVariants_Create(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
assert.Equal(t, http.MethodPost, r.Method, "Expected method '%s', got %s", http.MethodPost, r.Method) | ||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, loadFixture("images_variants", "single_full")) | ||
} | ||
|
||
url := fmt.Sprintf("/accounts/%s/images/v1/variants", testAccountID) | ||
mux.HandleFunc(url, handler) | ||
|
||
want := ImagesVariant{ | ||
ID: "hero", | ||
NeverRequireSignedURLs: BoolPtr(true), | ||
Options: ImagesVariantsOptions{ | ||
Fit: "scale-down", | ||
Height: 768, | ||
Width: 1366, | ||
Metadata: "none", | ||
}, | ||
} | ||
|
||
got, err := client.CreateImagesVariant(context.Background(), AccountIdentifier(testAccountID), CreateImagesVariantParams{ | ||
ID: testImagesVariantID, | ||
NeverRequireSignedURLs: BoolPtr(true), | ||
Options: ImagesVariantsOptions{ | ||
Fit: "scale-down", | ||
Height: 768, | ||
Width: 1366, | ||
Metadata: "none", | ||
}, | ||
}) | ||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, got) | ||
} | ||
} | ||
|
||
func TestImagesVariants_Update(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
assert.Equal(t, http.MethodPatch, r.Method, "Expected method '%s', got %s", http.MethodPatch, r.Method) | ||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, loadFixture("images_variants", "single_full")) | ||
} | ||
|
||
url := fmt.Sprintf("/accounts/%s/images/v1/variants/%s", testAccountID, testImagesVariantID) | ||
mux.HandleFunc(url, handler) | ||
|
||
want := ImagesVariant{ | ||
ID: "hero", | ||
NeverRequireSignedURLs: BoolPtr(true), | ||
Options: ImagesVariantsOptions{ | ||
Fit: "scale-down", | ||
Height: 768, | ||
Width: 1366, | ||
Metadata: "none", | ||
}, | ||
} | ||
|
||
got, err := client.UpdateImagesVariant(context.Background(), AccountIdentifier(testAccountID), UpdateImagesVariantParams{ | ||
ID: "hero", | ||
NeverRequireSignedURLs: BoolPtr(true), | ||
Options: ImagesVariantsOptions{ | ||
Fit: "scale-down", | ||
Height: 768, | ||
Width: 1366, | ||
Metadata: "none", | ||
}, | ||
}) | ||
|
||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, got) | ||
} | ||
} | ||
|
||
func TestImageVariants_MissingAccountId(t *testing.T) { | ||
_, err := client.ListImagesVariants(context.Background(), AccountIdentifier(""), ListImageVariantsParams{}) | ||
assert.Equal(t, ErrMissingAccountID, err) | ||
|
||
_, err = client.GetImagesVariant(context.Background(), AccountIdentifier(""), testImagesVariantID) | ||
assert.Equal(t, ErrMissingAccountID, err) | ||
|
||
_, err = client.CreateImagesVariant(context.Background(), AccountIdentifier(""), CreateImagesVariantParams{}) | ||
assert.Equal(t, ErrMissingAccountID, err) | ||
|
||
err = client.DeleteImagesVariant(context.Background(), AccountIdentifier(""), testImagesVariantID) | ||
assert.Equal(t, ErrMissingAccountID, err) | ||
|
||
_, err = client.UpdateImagesVariant(context.Background(), AccountIdentifier(""), UpdateImagesVariantParams{}) | ||
assert.Equal(t, ErrMissingAccountID, err) | ||
} |
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,17 @@ | ||
{ | ||
"errors": [], | ||
"messages": [], | ||
"result": { | ||
"variant": { | ||
"id": "hero", | ||
"neverRequireSignedURLs": true, | ||
"options": { | ||
"fit": "scale-down", | ||
"height": 768, | ||
"metadata": "none", | ||
"width": 1366 | ||
} | ||
} | ||
}, | ||
"success": true | ||
} |
Oops, something went wrong.