github.com/fastly/go-fastly/v6@v6.8.0/fastly/vcl_snippets.go (about) 1 package fastly 2 3 import ( 4 "fmt" 5 "net/url" 6 "sort" 7 "time" 8 ) 9 10 const ( 11 // SnippetTypeInit sets the type to init 12 SnippetTypeInit SnippetType = "init" 13 14 // SnippetTypeRecv sets the type to recv 15 SnippetTypeRecv SnippetType = "recv" 16 17 // SnippetTypeHash sets the type to hash 18 SnippetTypeHash SnippetType = "hash" 19 20 // SnippetTypeHit sets the type to hit 21 SnippetTypeHit SnippetType = "hit" 22 23 // SnippetTypeMiss sets the type to miss 24 SnippetTypeMiss SnippetType = "miss" 25 26 // SnippetTypePass sets the type to pass 27 SnippetTypePass SnippetType = "pass" 28 29 // SnippetTypeFetch sets the type to fetch 30 SnippetTypeFetch SnippetType = "fetch" 31 32 // SnippetTypeError sets the type to error 33 SnippetTypeError SnippetType = "error" 34 35 // SnippetTypeDeliver sets the type to deliver 36 SnippetTypeDeliver SnippetType = "deliver" 37 38 // SnippetTypeLog sets the type to log 39 SnippetTypeLog SnippetType = "log" 40 41 // SnippetTypeNone sets the type to none 42 SnippetTypeNone SnippetType = "none" 43 ) 44 45 // SnippetType is the type of VCL Snippet 46 type SnippetType string 47 48 // Helper function to get a pointer to string 49 func SnippetTypeToString(b string) *SnippetType { 50 p := SnippetType(b) 51 return &p 52 } 53 54 // Snippet is the Fastly Snippet object 55 type Snippet struct { 56 ServiceID string `mapstructure:"service_id"` 57 ServiceVersion int `mapstructure:"version"` 58 59 Name string `mapstructure:"name"` 60 ID string `mapstructure:"id"` 61 Priority int `mapstructure:"priority"` 62 Dynamic int `mapstructure:"dynamic"` 63 Content string `mapstructure:"content"` 64 Type SnippetType `mapstructure:"type"` 65 CreatedAt *time.Time `mapstructure:"created_at"` 66 UpdatedAt *time.Time `mapstructure:"updated_at"` 67 DeletedAt *time.Time `mapstructure:"deleted_at"` 68 } 69 70 // CreateSnippetInput is the input for CreateSnippet 71 type CreateSnippetInput struct { 72 // ServiceID is the ID of the service to add the snippet to (required). 73 ServiceID string 74 75 // ServiceVersion is the editable configuration version (required). 76 ServiceVersion int 77 78 // Name is the name for the snippet. 79 Name string `url:"name"` 80 81 // Priority determines the ordering for multiple snippets. Lower numbers execute first. 82 Priority *int `url:"priority,omitempty"` 83 84 // Dynamic sets the snippet version to regular (0) or dynamic (1). 85 Dynamic int `url:"dynamic"` 86 87 // Content is the VCL code that specifies exactly what the snippet does. 88 Content string `url:"content"` 89 90 // Type is the location in generated VCL where the snippet should be placed. 91 Type SnippetType `url:"type"` 92 } 93 94 // CreateSnippet creates a new snippet or dynamic snippet on a unlocked version 95 func (c *Client) CreateSnippet(i *CreateSnippetInput) (*Snippet, error) { 96 if i.ServiceID == "" { 97 return nil, ErrMissingServiceID 98 } 99 100 if i.ServiceVersion == 0 { 101 return nil, ErrMissingServiceVersion 102 } 103 104 if i.Name == "" { 105 return nil, ErrMissingName 106 } 107 108 // 0 = versioned snippet 109 // 1 = dynamic snippet 110 if i.Dynamic == 0 && i.Content == "" { 111 return nil, ErrMissingContent 112 } 113 114 if i.Type == "" { 115 return nil, ErrMissingType 116 } 117 118 path := fmt.Sprintf("/service/%s/version/%d/snippet", i.ServiceID, i.ServiceVersion) 119 resp, err := c.PostForm(path, i, nil) 120 if err != nil { 121 return nil, err 122 } 123 defer resp.Body.Close() 124 125 var snippet *Snippet 126 if err := decodeBodyMap(resp.Body, &snippet); err != nil { 127 return nil, err 128 } 129 return snippet, err 130 } 131 132 // UpdateSnippetInput is the input for UpdateSnippet 133 type UpdateSnippetInput struct { 134 // ServiceID is the ID of the service to add the snippet to (required). 135 ServiceID string 136 137 // ServiceVersion is the editable configuration version (required). 138 ServiceVersion int 139 140 Name string 141 142 // Name is the name for the snippet. 143 NewName *string `url:"name,omitempty"` 144 145 // Priority determines the ordering for multiple snippets. Lower numbers execute first. 146 Priority *int `url:"priority,omitempty"` 147 148 // Content is the VCL code that specifies exactly what the snippet does. 149 Content *string `url:"content,omitempty"` 150 151 // Type is the location in generated VCL where the snippet should be placed. 152 Type *SnippetType `url:"type,omitempty"` 153 } 154 155 // UpdateSnippet updates a snippet on a unlocked version 156 func (c *Client) UpdateSnippet(i *UpdateSnippetInput) (*Snippet, error) { 157 if i.ServiceID == "" { 158 return nil, ErrMissingServiceID 159 } 160 161 if i.ServiceVersion == 0 { 162 return nil, ErrMissingServiceVersion 163 } 164 165 if i.Name == "" { 166 return nil, ErrMissingName 167 } 168 169 path := fmt.Sprintf("/service/%s/version/%d/snippet/%s", i.ServiceID, i.ServiceVersion, url.PathEscape(i.Name)) 170 resp, err := c.PutForm(path, i, nil) 171 if err != nil { 172 return nil, err 173 } 174 defer resp.Body.Close() 175 176 var snippet *Snippet 177 if err := decodeBodyMap(resp.Body, &snippet); err != nil { 178 return nil, err 179 } 180 return snippet, err 181 } 182 183 // DynamicSnippet is the object returned when updating or retrieving a Dynamic Snippet 184 type DynamicSnippet struct { 185 ServiceID string `mapstructure:"service_id"` 186 ID string `mapstructure:"snippet_id"` 187 188 Content string `mapstructure:"content"` 189 CreatedAt *time.Time `mapstructure:"created_at"` 190 UpdatedAt *time.Time `mapstructure:"updated_at"` 191 } 192 193 // UpdateDynamicSnippetInput is the input for UpdateDynamicSnippet 194 type UpdateDynamicSnippetInput struct { 195 // ServiceID is the ID of the Service to add the snippet to. 196 ServiceID string 197 198 // ID is the ID of the Snippet to modify 199 ID string 200 201 // Content is the VCL code that specifies exactly what the snippet does. 202 Content *string `url:"content,omitempty"` 203 } 204 205 // UpdateDynamicSnippet replaces the content of a Dynamic Snippet 206 func (c *Client) UpdateDynamicSnippet(i *UpdateDynamicSnippetInput) (*DynamicSnippet, error) { 207 if i.ServiceID == "" { 208 return nil, ErrMissingServiceID 209 } 210 211 if i.ID == "" { 212 return nil, ErrMissingID 213 } 214 215 path := fmt.Sprintf("/service/%s/snippet/%s", i.ServiceID, i.ID) 216 resp, err := c.PutForm(path, i, nil) 217 if err != nil { 218 return nil, err 219 } 220 defer resp.Body.Close() 221 222 var updateSnippet *DynamicSnippet 223 if err := decodeBodyMap(resp.Body, &updateSnippet); err != nil { 224 return nil, err 225 } 226 return updateSnippet, err 227 } 228 229 type DeleteSnippetInput struct { 230 // ServiceID is the ID of the Service to add the snippet to. 231 ServiceID string 232 233 // Name is the Name of the Snippet to Delete 234 Name string 235 236 // ServiceVersion is the editable configuration version (required). 237 ServiceVersion int 238 } 239 240 func (c *Client) DeleteSnippet(i *DeleteSnippetInput) error { 241 if i.ServiceID == "" { 242 return ErrMissingServiceID 243 } 244 245 if i.ServiceVersion == 0 { 246 return ErrMissingServiceVersion 247 } 248 249 if i.Name == "" { 250 return ErrMissingName 251 } 252 253 path := fmt.Sprintf("/service/%s/version/%d/snippet/%s", i.ServiceID, i.ServiceVersion, url.PathEscape(i.Name)) 254 resp, err := c.Delete(path, nil) 255 if err != nil { 256 return err 257 } 258 defer resp.Body.Close() 259 260 var r *statusResp 261 if err := decodeBodyMap(resp.Body, &r); err != nil { 262 return err 263 } 264 if !r.Ok() { 265 return ErrNotOK 266 } 267 return nil 268 } 269 270 // ListSnippetsInput is used as input to the ListSnippets function. 271 type ListSnippetsInput struct { 272 // ServiceID is the ID of the service (required). 273 ServiceID string 274 275 // ServiceVersion is the specific configuration version (required). 276 ServiceVersion int 277 } 278 279 // snippetsByName is a sortable list of Snippets. 280 type snippetsByName []*Snippet 281 282 // Len, Swap, and Less implement the sortable interface. 283 func (s snippetsByName) Len() int { return len(s) } 284 func (s snippetsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 285 func (s snippetsByName) Less(i, j int) bool { 286 return s[i].Name < s[j].Name 287 } 288 289 // ListSnippets returns the list of Snippets for the configuration version. Content is not displayed for Dynmanic Snippets due to them being 290 // versionless, use the GetDynamicSnippet function to show current content. 291 func (c *Client) ListSnippets(i *ListSnippetsInput) ([]*Snippet, error) { 292 if i.ServiceID == "" { 293 return nil, ErrMissingServiceID 294 } 295 296 if i.ServiceVersion == 0 { 297 return nil, ErrMissingServiceVersion 298 } 299 300 path := fmt.Sprintf("/service/%s/version/%d/snippet", i.ServiceID, i.ServiceVersion) 301 resp, err := c.Get(path, nil) 302 if err != nil { 303 return nil, err 304 } 305 defer resp.Body.Close() 306 307 var snippets []*Snippet 308 if err := decodeBodyMap(resp.Body, &snippets); err != nil { 309 return nil, err 310 } 311 sort.Stable(snippetsByName(snippets)) 312 return snippets, nil 313 } 314 315 // GetSnippetInput is used as input to the GetSnippet function. 316 type GetSnippetInput struct { 317 // ServiceID is the ID of the service (required). 318 ServiceID string 319 320 // ServiceVersion is the specific configuration version (required). 321 ServiceVersion int 322 323 // Name is the name of the Snippet to fetch. 324 Name string 325 } 326 327 // GetSnippet gets the Snippet configuration with the given parameters. Dynamic Snippets will not show content due to them 328 // being versionless, use GetDynamicSnippet to see content. 329 func (c *Client) GetSnippet(i *GetSnippetInput) (*Snippet, error) { 330 if i.ServiceID == "" { 331 return nil, ErrMissingServiceID 332 } 333 334 if i.ServiceVersion == 0 { 335 return nil, ErrMissingServiceVersion 336 } 337 338 if i.Name == "" { 339 return nil, ErrMissingName 340 } 341 342 path := fmt.Sprintf("/service/%s/version/%d/snippet/%s", i.ServiceID, i.ServiceVersion, url.PathEscape(i.Name)) 343 resp, err := c.Get(path, nil) 344 if err != nil { 345 return nil, err 346 } 347 defer resp.Body.Close() 348 349 var snippet *Snippet 350 if err := decodeBodyMap(resp.Body, &snippet); err != nil { 351 return nil, err 352 } 353 return snippet, nil 354 } 355 356 // GetDynamicSnippetInput is used as input to the GetDynamicSnippet function. 357 type GetDynamicSnippetInput struct { 358 // ServiceID is the ID of the service (required). 359 ServiceID string 360 361 // ID is the ID of the Snippet to fetch. 362 ID string 363 } 364 365 // GetDynamicSnippet gets the Snippet configuration with the given parameters. This will show the current content 366 // associated with a Dynamic Snippet. 367 func (c *Client) GetDynamicSnippet(i *GetDynamicSnippetInput) (*DynamicSnippet, error) { 368 if i.ServiceID == "" { 369 return nil, ErrMissingServiceID 370 } 371 372 if i.ID == "" { 373 return nil, ErrMissingID 374 } 375 376 path := fmt.Sprintf("/service/%s/snippet/%s", i.ServiceID, i.ID) 377 resp, err := c.Get(path, nil) 378 if err != nil { 379 return nil, err 380 } 381 defer resp.Body.Close() 382 383 var snippet *DynamicSnippet 384 if err := decodeBodyMap(resp.Body, &snippet); err != nil { 385 return nil, err 386 } 387 return snippet, nil 388 }