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 }