github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/include.go (about)

     1  package papi
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  
    10  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr"
    11  
    12  	validation "github.com/go-ozzo/ozzo-validation/v4"
    13  )
    14  
    15  type (
    16  	// Includes contains operations available on Include resource
    17  	Includes interface {
    18  		// ListIncludes lists Includes available for the current contract and group
    19  		//
    20  		// See: https://techdocs.akamai.com/property-mgr/reference/get-includes
    21  		ListIncludes(context.Context, ListIncludesRequest) (*ListIncludesResponse, error)
    22  
    23  		// ListIncludeParents lists parents of a specific Include
    24  		//
    25  		// See: https://techdocs.akamai.com/property-mgr/reference/get-include-parents
    26  		ListIncludeParents(context.Context, ListIncludeParentsRequest) (*ListIncludeParentsResponse, error)
    27  
    28  		// GetInclude gets information about a specific Include
    29  		//
    30  		// See: https://techdocs.akamai.com/property-mgr/reference/get-include
    31  		GetInclude(context.Context, GetIncludeRequest) (*GetIncludeResponse, error)
    32  
    33  		// CreateInclude creates a new Include
    34  		//
    35  		// See: https://techdocs.akamai.com/property-mgr/reference/post-includes
    36  		CreateInclude(context.Context, CreateIncludeRequest) (*CreateIncludeResponse, error)
    37  
    38  		// DeleteInclude deletes an Include
    39  		//
    40  		// See: https://techdocs.akamai.com/property-mgr/reference/delete-include
    41  		DeleteInclude(context.Context, DeleteIncludeRequest) (*DeleteIncludeResponse, error)
    42  	}
    43  
    44  	// ListIncludesRequest contains parameters used to list includes
    45  	ListIncludesRequest struct {
    46  		ContractID string
    47  		GroupID    string
    48  	}
    49  
    50  	// ListIncludesResponse represents a response object returned by ListIncludes
    51  	ListIncludesResponse struct {
    52  		Includes IncludeItems `json:"includes"`
    53  	}
    54  
    55  	// ListIncludeParentsRequest contains parameters used to list parents of an include
    56  	ListIncludeParentsRequest struct {
    57  		ContractID string
    58  		GroupID    string
    59  		IncludeID  string
    60  	}
    61  
    62  	// ListIncludeParentsResponse represents a response object returned by ListIncludeParents
    63  	ListIncludeParentsResponse struct {
    64  		Properties ParentPropertyItems `json:"properties"`
    65  	}
    66  
    67  	// GetIncludeRequest contains parameters used to fetch an include
    68  	GetIncludeRequest struct {
    69  		ContractID string
    70  		GroupID    string
    71  		IncludeID  string
    72  	}
    73  
    74  	// GetIncludeResponse represents a response object returned by GetInclude
    75  	GetIncludeResponse struct {
    76  		Includes IncludeItems `json:"includes"`
    77  		Include  Include      `json:"-"`
    78  	}
    79  
    80  	// CreateIncludeRequest contains parameters used to create an include
    81  	CreateIncludeRequest struct {
    82  		ContractID       string            `json:"-"`
    83  		GroupID          string            `json:"-"`
    84  		IncludeName      string            `json:"includeName"`
    85  		IncludeType      IncludeType       `json:"includeType"`
    86  		ProductID        string            `json:"productId"`
    87  		RuleFormat       string            `json:"ruleFormat,omitempty"`
    88  		CloneIncludeFrom *CloneIncludeFrom `json:"cloneFrom,omitempty"`
    89  	}
    90  
    91  	// CreateIncludeResponse represents a response object returned by CreateInclude
    92  	CreateIncludeResponse struct {
    93  		IncludeID       string `json:"-"`
    94  		IncludeLink     string `json:"includeLink"`
    95  		ResponseHeaders CreateIncludeResponseHeaders
    96  	}
    97  
    98  	// DeleteIncludeRequest contains parameters used to delete an include
    99  	DeleteIncludeRequest struct {
   100  		ContractID string
   101  		GroupID    string
   102  		IncludeID  string
   103  	}
   104  
   105  	// DeleteIncludeResponse represents a response object returned by DeleteInclude
   106  	DeleteIncludeResponse struct {
   107  		Message string `json:"message"`
   108  	}
   109  
   110  	// CloneIncludeFrom optionally identifies another include instance to clone when making a request to create new include
   111  	CloneIncludeFrom struct {
   112  		CloneFromVersionEtag string `json:"cloneFromVersionEtag,omitempty"`
   113  		IncludeID            string `json:"includeId"`
   114  		Version              int    `json:"version"`
   115  	}
   116  
   117  	// CreateIncludeResponseHeaders contains information received in response headers when making a request to create new include
   118  	CreateIncludeResponseHeaders struct {
   119  		IncludesLimitTotal     string
   120  		IncludesLimitRemaining string
   121  	}
   122  
   123  	// Include represents an Include object
   124  	Include struct {
   125  		AccountID         string      `json:"accountId"`
   126  		AssetID           string      `json:"assetId"`
   127  		ContractID        string      `json:"contractId"`
   128  		GroupID           string      `json:"groupId"`
   129  		IncludeID         string      `json:"includeId"`
   130  		IncludeName       string      `json:"includeName"`
   131  		IncludeType       IncludeType `json:"includeType"`
   132  		LatestVersion     int         `json:"latestVersion"`
   133  		ProductionVersion *int        `json:"productionVersion"`
   134  		PropertyType      *string     `json:"propertyType"`
   135  		StagingVersion    *int        `json:"stagingVersion"`
   136  	}
   137  
   138  	// IncludeItems represents a list of Include objects
   139  	IncludeItems struct {
   140  		Items []Include `json:"items"`
   141  	}
   142  
   143  	// ParentProperty represents an include parent object
   144  	ParentProperty struct {
   145  		AccountID         string `json:"accountId"`
   146  		AssetID           string `json:"assetId"`
   147  		ContractID        string `json:"contractId"`
   148  		GroupID           string `json:"groupId"`
   149  		ProductionVersion *int   `json:"productionVersion,omitempty"`
   150  		PropertyID        string `json:"propertyId"`
   151  		PropertyName      string `json:"propertyName"`
   152  		StagingVersion    *int   `json:"stagingVersion,omitempty"`
   153  	}
   154  
   155  	// ParentPropertyItems represents a list of ParentProperty objects
   156  	ParentPropertyItems struct {
   157  		Items []ParentProperty `json:"items"`
   158  	}
   159  
   160  	// IncludeType is type of include
   161  	IncludeType string
   162  )
   163  
   164  const (
   165  	// IncludeTypeMicroServices is used for creating a new microservices include
   166  	IncludeTypeMicroServices IncludeType = "MICROSERVICES"
   167  
   168  	// IncludeTypeCommonSettings is used for creating a new common_settings include
   169  	IncludeTypeCommonSettings IncludeType = "COMMON_SETTINGS"
   170  )
   171  
   172  // Validate validates ListIncludesRequest
   173  func (i ListIncludesRequest) Validate() error {
   174  	return validation.Errors{
   175  		"ContractID": validation.Validate(i.ContractID, validation.Required),
   176  	}.Filter()
   177  }
   178  
   179  // Validate validates ListIncludeParentsRequest
   180  func (i ListIncludeParentsRequest) Validate() error {
   181  	return validation.Errors{
   182  		"IncludeID": validation.Validate(i.IncludeID, validation.Required),
   183  	}.Filter()
   184  }
   185  
   186  // Validate validates GetIncludeRequest
   187  func (i GetIncludeRequest) Validate() error {
   188  	errs := validation.Errors{
   189  		"ContractID": validation.Validate(i.ContractID, validation.Required),
   190  		"GroupID":    validation.Validate(i.GroupID, validation.Required),
   191  		"IncludeID":  validation.Validate(i.IncludeID, validation.Required),
   192  	}
   193  
   194  	return edgegriderr.ParseValidationErrors(errs)
   195  }
   196  
   197  // Validate validates CreateIncludeRequest
   198  func (i CreateIncludeRequest) Validate() error {
   199  	errs := validation.Errors{
   200  		"ContractID":                 validation.Validate(i.ContractID, validation.Required),
   201  		"GroupID":                    validation.Validate(i.GroupID, validation.Required),
   202  		"IncludeName":                validation.Validate(i.IncludeName, validation.Required),
   203  		"IncludeType":                validation.Validate(i.IncludeType, validation.Required, validation.In(IncludeTypeMicroServices, IncludeTypeCommonSettings)),
   204  		"ProductID":                  validation.Validate(i.ProductID, validation.Required),
   205  		"CloneIncludeFrom.IncludeID": validation.Validate(i.CloneIncludeFrom, validation.When(i.CloneIncludeFrom != nil, validation.By(validateCloneIncludeID))),
   206  		"CloneIncludeFrom.Version":   validation.Validate(i.CloneIncludeFrom, validation.When(i.CloneIncludeFrom != nil, validation.By(validateCloneVersion))),
   207  	}
   208  
   209  	return edgegriderr.ParseValidationErrors(errs)
   210  }
   211  
   212  // Validate validates DeleteIncludeRequest
   213  func (i DeleteIncludeRequest) Validate() error {
   214  	return validation.Errors{
   215  		"IncludeID": validation.Validate(i.IncludeID, validation.Required),
   216  	}.Filter()
   217  }
   218  
   219  // validateCloneIncludeID validates IncludeID under CloneIncludeFrom
   220  func validateCloneIncludeID(value interface{}) error {
   221  	v, ok := value.(*CloneIncludeFrom)
   222  	if !ok {
   223  		return fmt.Errorf("type %T is invalid. Must be *CloneIncludeFrom", value)
   224  	}
   225  
   226  	if v.IncludeID == "" {
   227  		return fmt.Errorf("cannot be blank")
   228  	}
   229  
   230  	return nil
   231  }
   232  
   233  // validateCloneVersion validates Version under CloneIncludeFrom
   234  func validateCloneVersion(value interface{}) error {
   235  	v, ok := value.(*CloneIncludeFrom)
   236  	if !ok {
   237  		return fmt.Errorf("type %T is invalid. Must be *CloneIncludeFrom", value)
   238  	}
   239  
   240  	if v.Version == 0 {
   241  		return fmt.Errorf("cannot be blank")
   242  	}
   243  
   244  	return nil
   245  }
   246  
   247  var (
   248  	// ErrListIncludes is returned in case an error occurs on ListIncludes operation
   249  	ErrListIncludes = errors.New("list Includes")
   250  	// ErrListIncludeParents is returned in case an error occurs on ListIncludeParents operation
   251  	ErrListIncludeParents = errors.New("list Include Parents")
   252  	// ErrGetInclude is returned in case an error occurs on GetInclude operation
   253  	ErrGetInclude = errors.New("get an Include")
   254  	// ErrCreateInclude is returned in case an error occurs on CreateInclude operation
   255  	ErrCreateInclude = errors.New("create an Include")
   256  	// ErrDeleteInclude is returned in case an error occurs on DeleteInclude operation
   257  	ErrDeleteInclude = errors.New("delete an Include")
   258  )
   259  
   260  func (p *papi) ListIncludes(ctx context.Context, params ListIncludesRequest) (*ListIncludesResponse, error) {
   261  	logger := p.Log(ctx)
   262  	logger.Debug("ListIncludes")
   263  
   264  	if err := params.Validate(); err != nil {
   265  		return nil, fmt.Errorf("%s: %w: %s", ErrListIncludes, ErrStructValidation, err)
   266  	}
   267  
   268  	uri, err := url.Parse("/papi/v1/includes")
   269  	if err != nil {
   270  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrListIncludes, err)
   271  	}
   272  
   273  	q := uri.Query()
   274  	q.Add("contractId", params.ContractID)
   275  	if params.GroupID != "" {
   276  		q.Add("groupId", params.GroupID)
   277  	}
   278  	uri.RawQuery = q.Encode()
   279  
   280  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   281  	if err != nil {
   282  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListIncludes, err)
   283  	}
   284  
   285  	var result ListIncludesResponse
   286  	resp, err := p.Exec(req, &result)
   287  	if err != nil {
   288  		return nil, fmt.Errorf("%s: request failed: %w", ErrListIncludes, err)
   289  	}
   290  
   291  	if resp.StatusCode != http.StatusOK {
   292  		return nil, fmt.Errorf("%s: %w", ErrListIncludes, p.Error(resp))
   293  	}
   294  
   295  	return &result, nil
   296  }
   297  
   298  func (p *papi) ListIncludeParents(ctx context.Context, params ListIncludeParentsRequest) (*ListIncludeParentsResponse, error) {
   299  	logger := p.Log(ctx)
   300  	logger.Debug("ListIncludeParents")
   301  
   302  	if err := params.Validate(); err != nil {
   303  		return nil, fmt.Errorf("%s: %w: %s", ErrListIncludeParents, ErrStructValidation, err)
   304  	}
   305  
   306  	uri, err := url.Parse(fmt.Sprintf("/papi/v1/includes/%s/parents", params.IncludeID))
   307  	if err != nil {
   308  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrListIncludeParents, err)
   309  	}
   310  
   311  	q := uri.Query()
   312  	if params.ContractID != "" {
   313  		q.Add("contractId", params.ContractID)
   314  	}
   315  	if params.GroupID != "" {
   316  		q.Add("groupId", params.GroupID)
   317  	}
   318  	uri.RawQuery = q.Encode()
   319  
   320  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   321  	if err != nil {
   322  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListIncludeParents, err)
   323  	}
   324  
   325  	var result ListIncludeParentsResponse
   326  	resp, err := p.Exec(req, &result)
   327  	if err != nil {
   328  		return nil, fmt.Errorf("%w: request failed: %s", ErrListIncludeParents, err)
   329  	}
   330  
   331  	if resp.StatusCode != http.StatusOK {
   332  		return nil, fmt.Errorf("%s: %w", ErrListIncludeParents, p.Error(resp))
   333  	}
   334  
   335  	return &result, nil
   336  }
   337  
   338  func (p *papi) GetInclude(ctx context.Context, params GetIncludeRequest) (*GetIncludeResponse, error) {
   339  	logger := p.Log(ctx)
   340  	logger.Debug("GetInclude")
   341  
   342  	if err := params.Validate(); err != nil {
   343  		return nil, fmt.Errorf("%s: %w: %s", ErrGetInclude, ErrStructValidation, err)
   344  	}
   345  
   346  	uri, err := url.Parse(fmt.Sprintf("/papi/v1/includes/%s", params.IncludeID))
   347  	if err != nil {
   348  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetInclude, err)
   349  	}
   350  
   351  	q := uri.Query()
   352  	q.Add("contractId", params.ContractID)
   353  	q.Add("groupId", params.GroupID)
   354  	uri.RawQuery = q.Encode()
   355  
   356  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   357  	if err != nil {
   358  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetInclude, err)
   359  	}
   360  
   361  	var result GetIncludeResponse
   362  	resp, err := p.Exec(req, &result)
   363  	if err != nil {
   364  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetInclude, err)
   365  	}
   366  
   367  	if resp.StatusCode != http.StatusOK {
   368  		return nil, fmt.Errorf("%s: %w", ErrGetInclude, p.Error(resp))
   369  	}
   370  
   371  	if len(result.Includes.Items) == 0 {
   372  		return nil, fmt.Errorf("%s: %w: IncludeID: %s", ErrGetInclude, ErrNotFound, params.IncludeID)
   373  	}
   374  	result.Include = result.Includes.Items[0]
   375  
   376  	return &result, nil
   377  }
   378  
   379  func (p *papi) CreateInclude(ctx context.Context, params CreateIncludeRequest) (*CreateIncludeResponse, error) {
   380  	logger := p.Log(ctx)
   381  	logger.Debug("CreateInclude")
   382  
   383  	if err := params.Validate(); err != nil {
   384  		return nil, fmt.Errorf("%s: %w: %s", ErrCreateInclude, ErrStructValidation, err)
   385  	}
   386  
   387  	uri, err := url.Parse("/papi/v1/includes")
   388  	if err != nil {
   389  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrCreateInclude, err)
   390  	}
   391  
   392  	q := uri.Query()
   393  	q.Add("contractId", params.ContractID)
   394  	q.Add("groupId", params.GroupID)
   395  	uri.RawQuery = q.Encode()
   396  
   397  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri.String(), nil)
   398  	if err != nil {
   399  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateInclude, err)
   400  	}
   401  
   402  	var result CreateIncludeResponse
   403  	resp, err := p.Exec(req, &result, params)
   404  	if err != nil {
   405  		return nil, fmt.Errorf("%w: request failed: %s", ErrCreateInclude, err)
   406  	}
   407  
   408  	if resp.StatusCode != http.StatusCreated {
   409  		return nil, fmt.Errorf("%s: %w", ErrCreateInclude, p.Error(resp))
   410  	}
   411  
   412  	result.ResponseHeaders.IncludesLimitTotal = resp.Header.Get("x-limit-includes-per-contract-limit")
   413  	result.ResponseHeaders.IncludesLimitRemaining = resp.Header.Get("x-limit-includes-per-contract-remaining")
   414  
   415  	id, err := ResponseLinkParse(result.IncludeLink)
   416  	if err != nil {
   417  		return nil, fmt.Errorf("%s: %w: %s", ErrCreateInclude, ErrInvalidResponseLink, err)
   418  	}
   419  	result.IncludeID = id
   420  
   421  	return &result, nil
   422  }
   423  
   424  func (p *papi) DeleteInclude(ctx context.Context, params DeleteIncludeRequest) (*DeleteIncludeResponse, error) {
   425  	logger := p.Log(ctx)
   426  	logger.Debug("DeleteInclude")
   427  
   428  	if err := params.Validate(); err != nil {
   429  		return nil, fmt.Errorf("%s: %w: %s", ErrDeleteInclude, ErrStructValidation, err)
   430  	}
   431  
   432  	uri, err := url.Parse(fmt.Sprintf("/papi/v1/includes/%s", params.IncludeID))
   433  	if err != nil {
   434  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrDeleteInclude, err)
   435  	}
   436  
   437  	q := uri.Query()
   438  	if params.ContractID != "" {
   439  		q.Add("contractId", params.ContractID)
   440  	}
   441  	if params.GroupID != "" {
   442  		q.Add("groupId", params.GroupID)
   443  	}
   444  	uri.RawQuery = q.Encode()
   445  
   446  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri.String(), nil)
   447  	if err != nil {
   448  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrDeleteInclude, err)
   449  	}
   450  
   451  	var result DeleteIncludeResponse
   452  	resp, err := p.Exec(req, &result)
   453  	if err != nil {
   454  		return nil, fmt.Errorf("%w: request failed: %s", ErrDeleteInclude, err)
   455  	}
   456  
   457  	if resp.StatusCode != http.StatusOK {
   458  		return nil, fmt.Errorf("%s: %w", ErrDeleteInclude, p.Error(resp))
   459  	}
   460  
   461  	return &result, nil
   462  }