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  }