Skip to content

Commit

Permalink
Merge pull request #1232 from hunts/hunts/add-support-for-address-map…
Browse files Browse the repository at this point in the history
…s-apis

addressing: add support for Address Map resource
  • Loading branch information
jacobbednarz committed Mar 13, 2023
2 parents 16f15a2 + dfb4848 commit 3a67d01
Show file tree
Hide file tree
Showing 9 changed files with 728 additions and 19 deletions.
3 changes: 3 additions & 0 deletions .changelog/1232.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
addressing: Add `Address Map` support
```
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,6 @@ This library is starting to ship with experimental improvements that are not yet
ready for production but will be introduced before the next major version. See
[experimental README](/docs/experimental.md) for full details.

# License
## License

BSD licensed. See the [LICENSE](LICENSE) file for details.
284 changes: 284 additions & 0 deletions addressing_address_map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
package cloudflare

import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
)

// AddressMap contains information about an address map.
type AddressMap struct {
ID string `json:"id"`
Description *string `json:"description,omitempty"`
DefaultSNI *string `json:"default_sni"`
Enabled *bool `json:"enabled"`
Deletable *bool `json:"can_delete"`
CanModifyIPs *bool `json:"can_modify_ips"`
Memberships []AddressMapMembership `json:"memberships"`
IPs []AddressMapIP `json:"ips"`
CreatedAt time.Time `json:"created_at"`
ModifiedAt time.Time `json:"modified_at"`
}

type AddressMapIP struct {
IP string `json:"ip"`
CreatedAt time.Time `json:"created_at"`
}

type AddressMapMembershipContainer struct {
Identifier string `json:"identifier"`
Kind AddressMapMembershipKind `json:"kind"`
}

type AddressMapMembership struct {
Identifier string `json:"identifier"`
Kind AddressMapMembershipKind `json:"kind"`
Deletable *bool `json:"can_delete"`
CreatedAt time.Time `json:"created_at"`
}

func (ammb *AddressMapMembershipContainer) URLFragment() string {
switch ammb.Kind {
case AddressMapMembershipAccount:
return fmt.Sprintf("accounts/%s", ammb.Identifier)
case AddressMapMembershipZone:
return fmt.Sprintf("zones/%s", ammb.Identifier)
default:
return fmt.Sprintf("%s/%s", ammb.Kind, ammb.Identifier)
}
}

type AddressMapMembershipKind string

const (
AddressMapMembershipZone AddressMapMembershipKind = "zone"
AddressMapMembershipAccount AddressMapMembershipKind = "account"
)

// ListAddressMapResponse contains a slice of address maps.
type ListAddressMapResponse struct {
Response
Result []AddressMap `json:"result"`
}

// GetAddressMapResponse contains a specific address map's API Response.
type GetAddressMapResponse struct {
Response
Result AddressMap `json:"result"`
}

// CreateAddressMapParams contains information about an address map to be created.
type CreateAddressMapParams struct {
Description *string `json:"description"`
Enabled *bool `json:"enabled"`
IPs []string `json:"ips"`
Memberships []AddressMapMembershipContainer `json:"memberships"`
}

// UpdateAddressMapParams contains information about an address map to be updated.
type UpdateAddressMapParams struct {
ID string `json:"id"`
Description *string `json:"description,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
DefaultSNI *string `json:"default_sni,omitempty"`
}

// AddressMapFilter contains filter parameters for finding a list of address maps.
type ListAddressMapsParams struct {
IP *string `url:"ip,omitempty"`
CIDR *string `url:"cidr,omitempty"`
}

// CreateIPAddressToAddressMapParams contains request parameters to add/remove IP address to/from an address map.
type CreateIPAddressToAddressMapParams struct {
// ID represents the target address map for adding the IP address.
ID string
// The IP address.
IP string
}

// CreateMembershipToAddressMapParams contains request parameters to add/remove membership from an address map.
type CreateMembershipToAddressMapParams struct {
// ID represents the target address map for adding the membershp.
ID string
Membership AddressMapMembershipContainer
}

type DeleteMembershipFromAddressMapParams struct {
// ID represents the target address map for removing the IP address.
ID string
Membership AddressMapMembershipContainer
}

type DeleteIPAddressFromAddressMapParams struct {
// ID represents the target address map for adding the membershp.
ID string
IP string
}

// ListAddressMaps lists all address maps owned by the account.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-list-address-maps
func (api *API) ListAddressMaps(ctx context.Context, rc *ResourceContainer, params ListAddressMapsParams) ([]AddressMap, error) {
if rc.Level != AccountRouteLevel {
return []AddressMap{}, ErrRequiredAccountLevelResourceContainer
}

uri := buildURI(fmt.Sprintf("/%s/addressing/address_maps", rc.URLFragment()), params)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return []AddressMap{}, err
}

result := ListAddressMapResponse{}
if err := json.Unmarshal(res, &result); err != nil {
return []AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return result.Result, nil
}

// CreateAddressMap creates a new address map under the account.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-create-address-map
func (api *API) CreateAddressMap(ctx context.Context, rc *ResourceContainer, params CreateAddressMapParams) (AddressMap, error) {
if rc.Level != AccountRouteLevel {
return AddressMap{}, ErrRequiredAccountLevelResourceContainer
}

uri := fmt.Sprintf("/%s/addressing/address_maps", rc.URLFragment())
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
if err != nil {
return AddressMap{}, err
}

result := GetAddressMapResponse{}
if err := json.Unmarshal(res, &result); err != nil {
return AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return result.Result, nil
}

// GetAddressMap returns a specific address map.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-address-map-details
func (api *API) GetAddressMap(ctx context.Context, rc *ResourceContainer, id string) (AddressMap, error) {
if rc.Level != AccountRouteLevel {
return AddressMap{}, ErrRequiredAccountLevelResourceContainer
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s", rc.URLFragment(), id)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return AddressMap{}, err
}

result := GetAddressMapResponse{}
if err := json.Unmarshal(res, &result); err != nil {
return AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return result.Result, nil
}

// UpdateAddressMap modifies properties of an address map owned by the account.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-update-address-map
func (api *API) UpdateAddressMap(ctx context.Context, rc *ResourceContainer, params UpdateAddressMapParams) (AddressMap, error) {
if rc.Level != AccountRouteLevel {
return AddressMap{}, ErrRequiredAccountLevelResourceContainer
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s", rc.URLFragment(), params.ID)
res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params)
if err != nil {
return AddressMap{}, err
}

result := GetAddressMapResponse{}
if err := json.Unmarshal(res, &result); err != nil {
return AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return result.Result, nil
}

// DeleteAddressMap deletes a particular address map owned by the account.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-delete-address-map
func (api *API) DeleteAddressMap(ctx context.Context, rc *ResourceContainer, id string) error {
if rc.Level != AccountRouteLevel {
return ErrRequiredAccountLevelResourceContainer
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s", rc.URLFragment(), id)
_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
return err
}

// CreateIPAddressToAddressMap adds an IP address from a prefix owned by the account to a particular address map.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-ip-to-an-address-map
func (api *API) CreateIPAddressToAddressMap(ctx context.Context, rc *ResourceContainer, params CreateIPAddressToAddressMapParams) error {
if rc.Level != AccountRouteLevel {
return ErrRequiredAccountLevelResourceContainer
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s/ips/%s", rc.URLFragment(), params.ID, params.IP)
_, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil)
return err
}

// DeleteIPAddressFromAddressMap removes an IP address from a particular address map.
//
// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-an-ip-from-an-address-map
func (api *API) DeleteIPAddressFromAddressMap(ctx context.Context, rc *ResourceContainer, params DeleteIPAddressFromAddressMapParams) error {
if rc.Level != AccountRouteLevel {
return ErrRequiredAccountLevelResourceContainer
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s/ips/%s", rc.URLFragment(), params.ID, params.IP)
_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
return err
}

// AddMembershipToAddressMap adds a zone/account as a member of a particular address map.
//
// API reference:
// - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-account-membership-to-an-address-map
// - zone: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-a-zone-membership-to-an-address-map
func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceContainer, params CreateMembershipToAddressMapParams) error {
if rc.Level != AccountRouteLevel {
return ErrRequiredAccountLevelResourceContainer
}

if params.Membership.Kind != AddressMapMembershipZone && params.Membership.Kind != AddressMapMembershipAccount {
return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind)
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment())
_, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil)
return err
}

// DeleteMembershipFromAddressMap removes a zone/account as a member of a particular address map.
//
// API reference:
// - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-an-account-membership-from-an-address-map
// - zone: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-a-zone-membership-from-an-address-map
func (api *API) DeleteMembershipFromAddressMap(ctx context.Context, rc *ResourceContainer, params DeleteMembershipFromAddressMapParams) error {
if rc.Level != AccountRouteLevel {
return ErrRequiredAccountLevelResourceContainer
}

if params.Membership.Kind != AddressMapMembershipZone && params.Membership.Kind != AddressMapMembershipAccount {
return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind)
}

uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment())
_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
return err
}

0 comments on commit 3a67d01

Please sign in to comment.