-
Notifications
You must be signed in to change notification settings - Fork 615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds implementation for (IP) Rules Lists #507
Merged
Merged
Changes from 8 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
20f4afa
Adds implementation for Rules Lists
efbe4d8
Adds Cursors to ResultInfo
b56960c
golint
1244339
Returns an IPList struct from UpdateIPList() instead of the full resp…
c10b32b
Returns an IPList struct from CreateIPList() instead of the full resp…
66a1429
Removes Debug Output
378caaa
Adds acceptance tests
4d5c8ed
Renames BulkOperation to IPListBulkOperation
eb25a11
Adds synchronous behavior for asynchronous endpoints
d23a335
golint
db994f5
Apply suggestions from code review
cehrig a3acbed
Returns an error if BulkOperation returns an unexpected status
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,357 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
const ( | ||
// IPListTypeIP specifies a list containing IP addresses | ||
IPListTypeIP = "ip" | ||
) | ||
|
||
// IPListBulkOperation contains information about a Bulk Operation | ||
type IPListBulkOperation struct { | ||
ID string `json:"id"` | ||
Status string `json:"status"` | ||
Error string `json:"error"` | ||
Completed *time.Time `json:"completed"` | ||
} | ||
|
||
// IPList contains information about an IP List | ||
type IPList struct { | ||
ID string `json:"id"` | ||
Name string `json:"name"` | ||
Description string `json:"description"` | ||
Kind string `json:"kind"` | ||
NumItems int `json:"num_items"` | ||
NumReferencingFilters int `json:"num_referencing_filters"` | ||
CreatedOn *time.Time `json:"created_on"` | ||
ModifiedOn *time.Time `json:"modified_on"` | ||
} | ||
|
||
// IPListItem contains information about a single IP List Item | ||
type IPListItem struct { | ||
ID string `json:"id"` | ||
IP string `json:"ip"` | ||
Comment string `json:"comment"` | ||
CreatedOn *time.Time `json:"created_on"` | ||
ModifiedOn *time.Time `json:"modified_on"` | ||
} | ||
|
||
// IPListCreateRequest contains data for a new IP List | ||
type IPListCreateRequest struct { | ||
Name string `json:"name"` | ||
Description string `json:"description"` | ||
Kind string `json:"kind"` | ||
} | ||
|
||
// IPListItemCreateRequest contains data for a new IP List Item | ||
type IPListItemCreateRequest struct { | ||
IP string `json:"ip"` | ||
Comment string `json:"comment"` | ||
} | ||
|
||
// IPListItemDeleteRequest wraps IP List Items that shall be deleted | ||
type IPListItemDeleteRequest struct { | ||
Items []IPListItemDeleteItemRequest `json:"items"` | ||
} | ||
|
||
// IPListItemDeleteItemRequest contains single IP List Items that shall be deleted | ||
type IPListItemDeleteItemRequest struct { | ||
ID string `json:"id"` | ||
} | ||
|
||
// IPListUpdateRequest contains data for an IP List update | ||
type IPListUpdateRequest struct { | ||
Description string `json:"description"` | ||
} | ||
|
||
// IPListResponse contains a single IP Lists | ||
type IPListResponse struct { | ||
Response | ||
Result IPList `json:"result"` | ||
} | ||
|
||
// IPListItemResponse contains information about the creation of an IP List Item | ||
type IPListItemResponse struct { | ||
Response | ||
Result struct { | ||
OperationID string `json:"operation_id"` | ||
} `json:"result"` | ||
} | ||
|
||
// IPListListResponse contains a slice of IP Lists | ||
type IPListListResponse struct { | ||
Response | ||
Result []IPList `json:"result"` | ||
} | ||
|
||
// IPListBulkOperationResponse contains information about a Bulk Operation | ||
type IPListBulkOperationResponse struct { | ||
Response | ||
Result IPListBulkOperation `json:"result"` | ||
} | ||
|
||
// IPListDeleteResponse contains information about the deletion of an IP List | ||
type IPListDeleteResponse struct { | ||
Response | ||
Result struct { | ||
ID string `json:"id"` | ||
} `json:"result"` | ||
} | ||
|
||
// IPListItemsListResponse contains information about IP List Items | ||
type IPListItemsListResponse struct { | ||
Response | ||
ResultInfo `json:"result_info"` | ||
Result []IPListItem `json:"result"` | ||
} | ||
|
||
// IPListItemDeleteResponse contains information about the deletion of an IP List Item | ||
type IPListItemDeleteResponse struct { | ||
Response | ||
Result struct { | ||
OperationID string `json:"operation_id"` | ||
} `json:"result"` | ||
} | ||
|
||
// IPListItemsGetResponse contains information about a single IP List Item | ||
type IPListItemsGetResponse struct { | ||
Response | ||
Result IPListItem `json:"result"` | ||
} | ||
|
||
// ListIPLists lists all IP Lists | ||
// API reference: https://api.cloudflare.com/#rules-lists-list-lists | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) ListIPLists(ctx context.Context) ([]IPList, error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists", api.AccountID) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return []IPList{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListListResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return []IPList{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
// CreateIPList creates a new IP List | ||
// API reference: https://api.cloudflare.com/#rules-lists-create-list | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) CreateIPList(ctx context.Context, name string, description string, kind string) (IPList, | ||
error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists", api.AccountID) | ||
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, | ||
IPListCreateRequest{Name: name, Description: description, Kind: kind}) | ||
if err != nil { | ||
return IPList{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPList{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
// GetIPList returns a single IP List | ||
// API reference: https://api.cloudflare.com/#rules-lists-get-list | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) GetIPList(ctx context.Context, id string) (IPList, error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return IPList{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPList{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
// UpdateIPList updates the description of an existing IP List | ||
// API reference: https://api.cloudflare.com/#rules-lists-update-list | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) UpdateIPList(ctx context.Context, id string, description string) (IPList, error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, IPListUpdateRequest{Description: description}) | ||
if err != nil { | ||
return IPList{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPList{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
// DeleteIPList deletes an IP List | ||
// API reference: https://api.cloudflare.com/#rules-lists-delete-list | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) DeleteIPList(ctx context.Context, id string) (IPListDeleteResponse, error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) | ||
if err != nil { | ||
return IPListDeleteResponse{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListDeleteResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListDeleteResponse{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// ListIPListItems returns a list with all items in an IP List | ||
// API reference: https://api.cloudflare.com/#rules-lists-list-list-items | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) ListIPListItems(ctx context.Context, id string) ([]IPListItem, error) { | ||
var list []IPListItem | ||
var cursor string | ||
var cursorQuery string | ||
|
||
for { | ||
if len(cursor) > 0 { | ||
cursorQuery = fmt.Sprintf("?cursor=%s", cursor) | ||
} | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s/items%s", api.AccountID, id, cursorQuery) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return []IPListItem{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListItemsListResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return []IPListItem{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
list = append(list, result.Result...) | ||
if cursor = result.ResultInfo.Cursors.After; cursor == "" { | ||
break | ||
} | ||
} | ||
|
||
return list, nil | ||
} | ||
|
||
// CreateIPListItem creates a new IP List Item | ||
// TODO Responses won't contain an error code if we are trying to create more IPs than allowed | ||
// TODO shall we keep the method asynchronously or poll the bulk operations endpoint? | ||
// API reference: https://api.cloudflare.com/#rules-lists-create-list-items | ||
func (api *API) CreateIPListItem(ctx context.Context, id string, ip string, comment string) (IPListItemResponse, | ||
error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s/items", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, []IPListItemCreateRequest{{IP: ip, Comment: comment}}) | ||
if err != nil { | ||
return IPListItemResponse{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListItemResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListItemResponse{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// CreateIPListItems bulk creates many IP List Items | ||
// TODO shall we keep the method asynchronously or poll the bulk operations endpoint? | ||
// API reference: https://api.cloudflare.com/#rules-lists-create-list-items | ||
func (api *API) CreateIPListItems(ctx context.Context, id string, items []IPListItemCreateRequest) (IPListItemResponse, | ||
error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s/items", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, items) | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
return IPListItemResponse{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListItemResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListItemResponse{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// ReplaceIPListItems replace all IP List items with a new set | ||
// TODO shall we keep the method asynchronously or poll the bulk operations endpoint? | ||
// API reference: https://api.cloudflare.com/#rules-lists-replace-list-items | ||
func (api *API) ReplaceIPListItems(ctx context.Context, id string, items []IPListItemCreateRequest) (IPListItemResponse, | ||
error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s/items", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, items) | ||
if err != nil { | ||
return IPListItemResponse{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListItemResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListItemResponse{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// DeleteIPListItems removes specific Items of an IP List by their ID | ||
// TODO shall we keep the method asynchronously or poll the bulk operations endpoint? | ||
// API reference: https://api.cloudflare.com/#rules-lists-delete-list-items | ||
func (api *API) DeleteIPListItems(ctx context.Context, id string, items IPListItemDeleteRequest) (IPListItemDeleteResponse, | ||
error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s/items", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, items) | ||
if err != nil { | ||
return IPListItemDeleteResponse{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListItemDeleteResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListItemDeleteResponse{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// GetIPListItem returns a single IP List Item | ||
// API reference: https://api.cloudflare.com/#rules-lists-get-list-item | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (api *API) GetIPListItem(ctx context.Context, listID string, id string) (IPListItem, error) { | ||
cehrig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
uri := fmt.Sprintf("/accounts/%s/rules/lists/%s/items/%s", api.AccountID, listID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return IPListItem{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListItemsGetResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListItem{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result.Result, nil | ||
} | ||
|
||
// GetIPListBulkOperation returns the status of a bulk operation | ||
// API reference: https://api.cloudflare.com/#rules-lists-get-list | ||
func (api *API) GetIPListBulkOperation(ctx context.Context, id string) (IPListBulkOperation, error) { | ||
uri := fmt.Sprintf("/accounts/%s/rules/lists/bulk_operations/%s", api.AccountID, id) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return IPListBulkOperation{}, errors.Wrap(err, errMakeRequestError) | ||
} | ||
|
||
result := IPListBulkOperationResponse{} | ||
if err := json.Unmarshal(res, &result); err != nil { | ||
return IPListBulkOperation{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return result.Result, nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! This would be great to see on other API endpoints 😄