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

     1  package papi
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  	"strconv"
    10  
    11  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr"
    12  	validation "github.com/go-ozzo/ozzo-validation/v4"
    13  )
    14  
    15  type (
    16  	// IncludeRules contains operations available on IncludeRule resource
    17  	IncludeRules interface {
    18  		// GetIncludeRuleTree gets the entire rule tree for an include version
    19  		//
    20  		// See: https://techdocs.akamai.com/property-mgr/reference/get-include-version-rules
    21  		GetIncludeRuleTree(context.Context, GetIncludeRuleTreeRequest) (*GetIncludeRuleTreeResponse, error)
    22  
    23  		// UpdateIncludeRuleTree updates the rule tree for an include version
    24  		//
    25  		// See: https://techdocs.akamai.com/property-mgr/reference/patch-include-version-rules
    26  		UpdateIncludeRuleTree(context.Context, UpdateIncludeRuleTreeRequest) (*UpdateIncludeRuleTreeResponse, error)
    27  	}
    28  
    29  	// GetIncludeRuleTreeRequest contains path and query params necessary to perform GetIncludeRuleTree
    30  	GetIncludeRuleTreeRequest struct {
    31  		ContractID     string
    32  		GroupID        string
    33  		IncludeID      string
    34  		IncludeVersion int
    35  		RuleFormat     string
    36  		ValidateMode   string
    37  		ValidateRules  bool
    38  	}
    39  
    40  	// GetIncludeRuleTreeResponse contains data returned by performing GetIncludeRuleTree request
    41  	GetIncludeRuleTreeResponse struct {
    42  		Response
    43  		Comments       string      `json:"comments,omitempty"`
    44  		Etag           string      `json:"etag"`
    45  		IncludeID      string      `json:"includeId"`
    46  		IncludeName    string      `json:"includeName"`
    47  		IncludeType    IncludeType `json:"includeType"`
    48  		IncludeVersion int         `json:"includeVersion"`
    49  		RuleFormat     string      `json:"ruleFormat"`
    50  		Rules          Rules       `json:"rules"`
    51  	}
    52  
    53  	// UpdateIncludeRuleTreeRequest contains path and query params, as well as request body necessary to perform UpdateIncludeRuleTree
    54  	UpdateIncludeRuleTreeRequest struct {
    55  		ContractID     string
    56  		DryRun         bool
    57  		GroupID        string
    58  		IncludeID      string
    59  		IncludeVersion int
    60  		Rules          RulesUpdate
    61  		ValidateMode   string
    62  		ValidateRules  bool
    63  	}
    64  
    65  	// UpdateIncludeRuleTreeResponse contains data returned by performing UpdateIncludeRuleTree request
    66  	UpdateIncludeRuleTreeResponse struct {
    67  		Response
    68  		ResponseHeaders UpdateIncludeResponseHeaders
    69  		Comments        string      `json:"comments,omitempty"`
    70  		Etag            string      `json:"etag"`
    71  		IncludeID       string      `json:"includeId"`
    72  		IncludeName     string      `json:"includeName"`
    73  		IncludeType     IncludeType `json:"includeType"`
    74  		IncludeVersion  int         `json:"includeVersion"`
    75  		RuleFormat      string      `json:"ruleFormat"`
    76  		Rules           Rules       `json:"rules"`
    77  	}
    78  
    79  	// UpdateIncludeResponseHeaders contains information received in response headers when making a UpdateIncludeRuleTree request
    80  	UpdateIncludeResponseHeaders struct {
    81  		ElementsPerPropertyRemaining      string
    82  		ElementsPerPropertyTotal          string
    83  		MaxNestedRulesPerIncludeRemaining string
    84  		MaxNestedRulesPerIncludeTotal     string
    85  	}
    86  )
    87  
    88  // Validate validates GetIncludeRuleTreeRequest struct
    89  func (i GetIncludeRuleTreeRequest) Validate() error {
    90  	errs := validation.Errors{
    91  		"ContractID":     validation.Validate(i.ContractID, validation.Required),
    92  		"GroupID":        validation.Validate(i.GroupID, validation.Required),
    93  		"IncludeID":      validation.Validate(i.IncludeID, validation.Required),
    94  		"IncludeVersion": validation.Validate(i.IncludeVersion, validation.Required),
    95  		"RuleFormat":     validation.Validate(i.RuleFormat, validation.Match(validRuleFormat)),
    96  		"ValidateMode":   validation.Validate(i.ValidateMode, validation.In(RuleValidateModeFast, RuleValidateModeFull)),
    97  	}
    98  	return edgegriderr.ParseValidationErrors(errs)
    99  }
   100  
   101  // Validate validates UpdateIncludeRuleTreeRequest struct
   102  func (i UpdateIncludeRuleTreeRequest) Validate() error {
   103  	errs := validation.Errors{
   104  		"ContractID":     validation.Validate(i.ContractID, validation.Required),
   105  		"GroupID":        validation.Validate(i.GroupID, validation.Required),
   106  		"IncludeID":      validation.Validate(i.IncludeID, validation.Required),
   107  		"IncludeVersion": validation.Validate(i.IncludeVersion, validation.Required),
   108  		"Rules":          validation.Validate(i.Rules),
   109  		"ValidateMode":   validation.Validate(i.ValidateMode, validation.In(RuleValidateModeFast, RuleValidateModeFull)),
   110  	}
   111  	return edgegriderr.ParseValidationErrors(errs)
   112  }
   113  
   114  var (
   115  	// ErrGetIncludeRuleTree represents error when fetching rule tree fails
   116  	ErrGetIncludeRuleTree = errors.New("fetching include rule tree")
   117  	// ErrUpdateIncludeRuleTree represents error when updating rule tree fails
   118  	ErrUpdateIncludeRuleTree = errors.New("updating include rule tree")
   119  )
   120  
   121  func (p *papi) GetIncludeRuleTree(ctx context.Context, params GetIncludeRuleTreeRequest) (*GetIncludeRuleTreeResponse, error) {
   122  	logger := p.Log(ctx)
   123  	logger.Debug("GetIncludeRuleTree")
   124  
   125  	if err := params.Validate(); err != nil {
   126  		return nil, fmt.Errorf("%s: %w: %s", ErrGetIncludeRuleTree, ErrStructValidation, err)
   127  	}
   128  
   129  	uri, err := url.Parse(fmt.Sprintf("/papi/v1/includes/%s/versions/%d/rules", params.IncludeID, params.IncludeVersion))
   130  	if err != nil {
   131  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetIncludeRuleTree, err)
   132  	}
   133  
   134  	q := uri.Query()
   135  	q.Add("contractId", params.ContractID)
   136  	q.Add("groupId", params.GroupID)
   137  	if params.ValidateMode != "" {
   138  		q.Add("validateMode", params.ValidateMode)
   139  	}
   140  	if !params.ValidateRules {
   141  		q.Add("validateRules", strconv.FormatBool(params.ValidateRules))
   142  	}
   143  	uri.RawQuery = q.Encode()
   144  
   145  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   146  	if err != nil {
   147  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetIncludeRuleTree, err)
   148  	}
   149  
   150  	if params.RuleFormat != "" {
   151  		req.Header.Set("Accept", fmt.Sprintf("application/vnd.akamai.papirules.%s+json", params.RuleFormat))
   152  	}
   153  
   154  	var result GetIncludeRuleTreeResponse
   155  	resp, err := p.Exec(req, &result)
   156  	if err != nil {
   157  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetIncludeRuleTree, err)
   158  	}
   159  
   160  	if resp.StatusCode != http.StatusOK {
   161  		return nil, fmt.Errorf("%s: %w", ErrGetIncludeRuleTree, p.Error(resp))
   162  	}
   163  
   164  	return &result, nil
   165  }
   166  
   167  func (p *papi) UpdateIncludeRuleTree(ctx context.Context, params UpdateIncludeRuleTreeRequest) (*UpdateIncludeRuleTreeResponse, error) {
   168  	logger := p.Log(ctx)
   169  	logger.Debug("UpdateIncludeRuleTree")
   170  
   171  	if err := params.Validate(); err != nil {
   172  		return nil, fmt.Errorf("%s: %w: %s", ErrUpdateIncludeRuleTree, ErrStructValidation, err)
   173  	}
   174  
   175  	uri, err := url.Parse(fmt.Sprintf("/papi/v1/includes/%s/versions/%d/rules", params.IncludeID, params.IncludeVersion))
   176  	if err != nil {
   177  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrUpdateIncludeRuleTree, err)
   178  	}
   179  
   180  	q := uri.Query()
   181  	q.Add("contractId", params.ContractID)
   182  	q.Add("groupId", params.GroupID)
   183  	if params.ValidateMode != "" {
   184  		q.Add("validateMode", params.ValidateMode)
   185  	}
   186  	if !params.ValidateRules {
   187  		q.Add("validateRules", strconv.FormatBool(params.ValidateRules))
   188  	}
   189  	if params.DryRun {
   190  		q.Add("dryRun", strconv.FormatBool(params.DryRun))
   191  	}
   192  	uri.RawQuery = q.Encode()
   193  
   194  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri.String(), nil)
   195  	if err != nil {
   196  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateIncludeRuleTree, err)
   197  	}
   198  
   199  	var result UpdateIncludeRuleTreeResponse
   200  	resp, err := p.Exec(req, &result, params.Rules)
   201  	if err != nil {
   202  		return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateIncludeRuleTree, err)
   203  	}
   204  	if resp.StatusCode != http.StatusOK {
   205  		return nil, fmt.Errorf("%s: %w", ErrUpdateIncludeRuleTree, p.Error(resp))
   206  	}
   207  
   208  	result.ResponseHeaders.ElementsPerPropertyRemaining = resp.Header.Get("x-limit-elements-per-property-remaining")
   209  	result.ResponseHeaders.ElementsPerPropertyTotal = resp.Header.Get("x-limit-elements-per-property-limit")
   210  	result.ResponseHeaders.MaxNestedRulesPerIncludeRemaining = resp.Header.Get("x-limit-max-nested-rules-per-include-remaining")
   211  	result.ResponseHeaders.MaxNestedRulesPerIncludeTotal = resp.Header.Get("x-limit-max-nested-rules-per-include-limit")
   212  
   213  	return &result, nil
   214  }