github.com/gophercloud/gophercloud@v1.11.0/openstack/cdn/v1/services/requests.go (about)

     1  package services
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/gophercloud/gophercloud"
     8  	"github.com/gophercloud/gophercloud/pagination"
     9  )
    10  
    11  // ListOptsBuilder allows extensions to add additional parameters to the
    12  // List request.
    13  type ListOptsBuilder interface {
    14  	ToCDNServiceListQuery() (string, error)
    15  }
    16  
    17  // ListOpts allows the filtering and sorting of paginated collections through
    18  // the API. Marker and Limit are used for pagination.
    19  type ListOpts struct {
    20  	Marker string `q:"marker"`
    21  	Limit  int    `q:"limit"`
    22  }
    23  
    24  // ToCDNServiceListQuery formats a ListOpts into a query string.
    25  func (opts ListOpts) ToCDNServiceListQuery() (string, error) {
    26  	q, err := gophercloud.BuildQueryString(opts)
    27  	return q.String(), err
    28  }
    29  
    30  // List returns a Pager which allows you to iterate over a collection of
    31  // CDN services. It accepts a ListOpts struct, which allows for pagination via
    32  // marker and limit.
    33  func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
    34  	url := listURL(c)
    35  	if opts != nil {
    36  		query, err := opts.ToCDNServiceListQuery()
    37  		if err != nil {
    38  			return pagination.Pager{Err: err}
    39  		}
    40  		url += query
    41  	}
    42  	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
    43  		p := ServicePage{pagination.MarkerPageBase{PageResult: r}}
    44  		p.MarkerPageBase.Owner = p
    45  		return p
    46  	})
    47  }
    48  
    49  // CreateOptsBuilder is the interface options structs have to satisfy in order
    50  // to be used in the main Create operation in this package. Since many
    51  // extensions decorate or modify the common logic, it is useful for them to
    52  // satisfy a basic interface in order for them to be used.
    53  type CreateOptsBuilder interface {
    54  	ToCDNServiceCreateMap() (map[string]interface{}, error)
    55  }
    56  
    57  // CreateOpts is the common options struct used in this package's Create
    58  // operation.
    59  type CreateOpts struct {
    60  	// Specifies the name of the service. The minimum length for name is
    61  	// 3. The maximum length is 256.
    62  	Name string `json:"name" required:"true"`
    63  	// Specifies a list of domains used by users to access their website.
    64  	Domains []Domain `json:"domains" required:"true"`
    65  	// Specifies a list of origin domains or IP addresses where the
    66  	// original assets are stored.
    67  	Origins []Origin `json:"origins" required:"true"`
    68  	// Specifies the CDN provider flavor ID to use. For a list of
    69  	// flavors, see the operation to list the available flavors. The minimum
    70  	// length for flavor_id is 1. The maximum length is 256.
    71  	FlavorID string `json:"flavor_id" required:"true"`
    72  	// Specifies the TTL rules for the assets under this service. Supports wildcards for fine-grained control.
    73  	Caching []CacheRule `json:"caching,omitempty"`
    74  	// Specifies the restrictions that define who can access assets (content from the CDN cache).
    75  	Restrictions []Restriction `json:"restrictions,omitempty"`
    76  }
    77  
    78  // ToCDNServiceCreateMap casts a CreateOpts struct to a map.
    79  func (opts CreateOpts) ToCDNServiceCreateMap() (map[string]interface{}, error) {
    80  	return gophercloud.BuildRequestBody(opts, "")
    81  }
    82  
    83  // Create accepts a CreateOpts struct and creates a new CDN service using the
    84  // values provided.
    85  func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
    86  	b, err := opts.ToCDNServiceCreateMap()
    87  	if err != nil {
    88  		r.Err = err
    89  		return r
    90  	}
    91  	resp, err := c.Post(createURL(c), &b, nil, nil)
    92  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
    93  	return
    94  }
    95  
    96  // Get retrieves a specific service based on its URL or its unique ID. For
    97  // example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
    98  // "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
    99  // are valid options for idOrURL.
   100  func Get(c *gophercloud.ServiceClient, idOrURL string) (r GetResult) {
   101  	var url string
   102  	if strings.Contains(idOrURL, "/") {
   103  		url = idOrURL
   104  	} else {
   105  		url = getURL(c, idOrURL)
   106  	}
   107  	resp, err := c.Get(url, &r.Body, nil)
   108  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   109  	return
   110  }
   111  
   112  // Path is a JSON pointer location that indicates which service parameter is being added, replaced,
   113  // or removed.
   114  type Path struct {
   115  	baseElement string
   116  }
   117  
   118  func (p Path) renderRoot() string {
   119  	return "/" + p.baseElement
   120  }
   121  
   122  func (p Path) renderDash() string {
   123  	return fmt.Sprintf("/%s/-", p.baseElement)
   124  }
   125  
   126  func (p Path) renderIndex(index int64) string {
   127  	return fmt.Sprintf("/%s/%d", p.baseElement, index)
   128  }
   129  
   130  var (
   131  	// PathDomains indicates that an update operation is to be performed on a Domain.
   132  	PathDomains = Path{baseElement: "domains"}
   133  
   134  	// PathOrigins indicates that an update operation is to be performed on an Origin.
   135  	PathOrigins = Path{baseElement: "origins"}
   136  
   137  	// PathCaching indicates that an update operation is to be performed on a CacheRule.
   138  	PathCaching = Path{baseElement: "caching"}
   139  )
   140  
   141  type value interface {
   142  	toPatchValue() interface{}
   143  	appropriatePath() Path
   144  	renderRootOr(func(p Path) string) string
   145  }
   146  
   147  // Patch represents a single update to an existing Service. Multiple updates to a service can be
   148  // submitted at the same time.
   149  type Patch interface {
   150  	ToCDNServiceUpdateMap() map[string]interface{}
   151  }
   152  
   153  // Insertion is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to
   154  // a Service at a fixed index. Use an Append instead to append the new value to the end of its
   155  // collection. Pass it to the Update function as part of the Patch slice.
   156  type Insertion struct {
   157  	Index int64
   158  	Value value
   159  }
   160  
   161  // ToCDNServiceUpdateMap converts an Insertion into a request body fragment suitable for the
   162  // Update call.
   163  func (opts Insertion) ToCDNServiceUpdateMap() map[string]interface{} {
   164  	return map[string]interface{}{
   165  		"op":    "add",
   166  		"path":  opts.Value.renderRootOr(func(p Path) string { return p.renderIndex(opts.Index) }),
   167  		"value": opts.Value.toPatchValue(),
   168  	}
   169  }
   170  
   171  // Append is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to a
   172  // Service at the end of its respective collection. Use an Insertion instead to insert the value
   173  // at a fixed index within the collection. Pass this to the Update function as part of its
   174  // Patch slice.
   175  type Append struct {
   176  	Value value
   177  }
   178  
   179  // ToCDNServiceUpdateMap converts an Append into a request body fragment suitable for the
   180  // Update call.
   181  func (a Append) ToCDNServiceUpdateMap() map[string]interface{} {
   182  	return map[string]interface{}{
   183  		"op":    "add",
   184  		"path":  a.Value.renderRootOr(func(p Path) string { return p.renderDash() }),
   185  		"value": a.Value.toPatchValue(),
   186  	}
   187  }
   188  
   189  // Replacement is a Patch that alters a specific service parameter (Domain, Origin, or CacheRule)
   190  // in-place by index. Pass it to the Update function as part of the Patch slice.
   191  type Replacement struct {
   192  	Value value
   193  	Index int64
   194  }
   195  
   196  // ToCDNServiceUpdateMap converts a Replacement into a request body fragment suitable for the
   197  // Update call.
   198  func (r Replacement) ToCDNServiceUpdateMap() map[string]interface{} {
   199  	return map[string]interface{}{
   200  		"op":    "replace",
   201  		"path":  r.Value.renderRootOr(func(p Path) string { return p.renderIndex(r.Index) }),
   202  		"value": r.Value.toPatchValue(),
   203  	}
   204  }
   205  
   206  // NameReplacement specifically updates the Service name. Pass it to the Update function as part
   207  // of the Patch slice.
   208  type NameReplacement struct {
   209  	NewName string
   210  }
   211  
   212  // ToCDNServiceUpdateMap converts a NameReplacement into a request body fragment suitable for the
   213  // Update call.
   214  func (r NameReplacement) ToCDNServiceUpdateMap() map[string]interface{} {
   215  	return map[string]interface{}{
   216  		"op":    "replace",
   217  		"path":  "/name",
   218  		"value": r.NewName,
   219  	}
   220  }
   221  
   222  // Removal is a Patch that requests the removal of a service parameter (Domain, Origin, or
   223  // CacheRule) by index. Pass it to the Update function as part of the Patch slice.
   224  type Removal struct {
   225  	Path  Path
   226  	Index int64
   227  	All   bool
   228  }
   229  
   230  // ToCDNServiceUpdateMap converts a Removal into a request body fragment suitable for the
   231  // Update call.
   232  func (opts Removal) ToCDNServiceUpdateMap() map[string]interface{} {
   233  	b := map[string]interface{}{"op": "remove"}
   234  	if opts.All {
   235  		b["path"] = opts.Path.renderRoot()
   236  	} else {
   237  		b["path"] = opts.Path.renderIndex(opts.Index)
   238  	}
   239  	return b
   240  }
   241  
   242  // UpdateOpts is a slice of Patches used to update a CDN service
   243  type UpdateOpts []Patch
   244  
   245  // Update accepts a slice of Patch operations (Insertion, Append, Replacement or Removal) and
   246  // updates an existing CDN service using the values provided. idOrURL can be either the service's
   247  // URL or its ID. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
   248  // "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
   249  // are valid options for idOrURL.
   250  func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) (r UpdateResult) {
   251  	var url string
   252  	if strings.Contains(idOrURL, "/") {
   253  		url = idOrURL
   254  	} else {
   255  		url = updateURL(c, idOrURL)
   256  	}
   257  
   258  	b := make([]map[string]interface{}, len(opts))
   259  	for i, patch := range opts {
   260  		b[i] = patch.ToCDNServiceUpdateMap()
   261  	}
   262  
   263  	resp, err := c.Request("PATCH", url, &gophercloud.RequestOpts{
   264  		JSONBody: &b,
   265  		OkCodes:  []int{202},
   266  	})
   267  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   268  	return
   269  }
   270  
   271  // Delete accepts a service's ID or its URL and deletes the CDN service
   272  // associated with it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
   273  // "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
   274  // are valid options for idOrURL.
   275  func Delete(c *gophercloud.ServiceClient, idOrURL string) (r DeleteResult) {
   276  	var url string
   277  	if strings.Contains(idOrURL, "/") {
   278  		url = idOrURL
   279  	} else {
   280  		url = deleteURL(c, idOrURL)
   281  	}
   282  	resp, err := c.Delete(url, nil)
   283  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   284  	return
   285  }