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 }