github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/cpcode.go (about) 1 package papi 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 9 validation "github.com/go-ozzo/ozzo-validation/v4" 10 ) 11 12 type ( 13 // CPCodes contains operations available on CPCode resource 14 CPCodes interface { 15 // GetCPCodes lists all available CP codes 16 // 17 // See: https://techdocs.akamai.com/property-mgr/reference/get-cpcodes 18 GetCPCodes(context.Context, GetCPCodesRequest) (*GetCPCodesResponse, error) 19 20 // GetCPCode gets the CP code with provided ID 21 // 22 // See: https://techdocs.akamai.com/property-mgr/reference/get-cpcode 23 GetCPCode(context.Context, GetCPCodeRequest) (*GetCPCodesResponse, error) 24 25 // GetCPCodeDetail lists detailed information about a specific CP code 26 // 27 // See: https://techdocs.akamai.com/cp-codes/reference/get-cpcode 28 GetCPCodeDetail(context.Context, int) (*CPCodeDetailResponse, error) 29 30 // CreateCPCode creates a new CP code 31 // 32 // See: https://techdocs.akamai.com/property-mgr/reference/post-cpcodes 33 CreateCPCode(context.Context, CreateCPCodeRequest) (*CreateCPCodeResponse, error) 34 35 // UpdateCPCode modifies a specific CP code. You should only modify a CP code's name, time zone, and purgeable member 36 // 37 // See: https://techdocs.akamai.com/cp-codes/reference/put-cpcode 38 UpdateCPCode(context.Context, UpdateCPCodeRequest) (*CPCodeDetailResponse, error) 39 } 40 41 // CPCode contains CP code resource data 42 CPCode struct { 43 ID string `json:"cpcodeId"` 44 Name string `json:"cpcodeName"` 45 CreatedDate string `json:"createdDate"` 46 ProductIDs []string `json:"productIds"` 47 } 48 49 // CPCodeContract contains contract data used in CPRG API calls 50 CPCodeContract struct { 51 ContractID string `json:"contractId"` 52 Status string `json:"status,omitempty"` 53 } 54 55 // CPCodeDetailResponse is a response returned while fetching CP code details using CPRG API call 56 CPCodeDetailResponse struct { 57 ID int `json:"cpcodeId"` 58 Name string `json:"cpcodeName"` 59 Purgeable bool `json:"purgeable"` 60 AccountID string `json:"accountId"` 61 DefaultTimeZone string `json:"defaultTimezone"` 62 OverrideTimeZone CPCodeTimeZone `json:"overrideTimezone"` 63 Type string `json:"type"` 64 Contracts []CPCodeContract `json:"contracts"` 65 Products []CPCodeProduct `json:"products"` 66 } 67 68 // CPCodeItems contains a list of CPCode items 69 CPCodeItems struct { 70 Items []CPCode `json:"items"` 71 } 72 73 // CPCodeProduct contains product data used in CPRG API calls 74 CPCodeProduct struct { 75 ProductID string `json:"productId"` 76 ProductName string `json:"productName,omitempty"` 77 } 78 79 // GetCPCodesResponse is a response returned while fetching CP codes 80 GetCPCodesResponse struct { 81 AccountID string `json:"accountId"` 82 ContractID string `json:"contractId"` 83 GroupID string `json:"groupId"` 84 CPCodes CPCodeItems `json:"cpcodes"` 85 CPCode CPCode 86 } 87 88 // CPCodeTimeZone contains time zone data used in CPRG API calls 89 CPCodeTimeZone struct { 90 TimeZoneID string `json:"timezoneId"` 91 TimeZoneValue string `json:"timezoneValue,omitempty"` 92 } 93 94 // CreateCPCodeRequest contains data required to create CP code (both request body and group/contract information 95 CreateCPCodeRequest struct { 96 ContractID string 97 GroupID string 98 CPCode CreateCPCode 99 } 100 101 // CreateCPCode contains the request body for CP code creation 102 CreateCPCode struct { 103 ProductID string `json:"productId"` 104 CPCodeName string `json:"cpcodeName"` 105 } 106 107 // CreateCPCodeResponse contains the response from CP code creation as well as the ID of created resource 108 CreateCPCodeResponse struct { 109 CPCodeLink string `json:"cpcodeLink"` 110 CPCodeID string `json:"-"` 111 } 112 113 // GetCPCodeRequest gets details about a CP code. 114 GetCPCodeRequest struct { 115 CPCodeID string 116 ContractID string 117 GroupID string 118 } 119 120 // GetCPCodesRequest contains parameters required to list/create CP codes 121 // GroupID and ContractID are required as part of every CP code operation, ID is required only for operating on specific CP code 122 GetCPCodesRequest struct { 123 ContractID string 124 GroupID string 125 } 126 127 // UpdateCPCodeRequest contains parameters required to update CP code, using CPRG API call 128 UpdateCPCodeRequest struct { 129 ID int `json:"cpcodeId"` 130 Name string `json:"cpcodeName"` 131 Purgeable *bool `json:"purgeable,omitempty"` 132 OverrideTimeZone *CPCodeTimeZone `json:"overrideTimezone,omitempty"` 133 Contracts []CPCodeContract `json:"contracts"` 134 Products []CPCodeProduct `json:"products"` 135 } 136 ) 137 138 // Validate validates GetCPCodesRequest 139 func (cp GetCPCodesRequest) Validate() error { 140 return validation.Errors{ 141 "ContractID": validation.Validate(cp.ContractID, validation.Required), 142 "GroupID": validation.Validate(cp.GroupID, validation.Required), 143 }.Filter() 144 } 145 146 // Validate validates GetCPCodeRequest 147 func (cp GetCPCodeRequest) Validate() error { 148 return validation.Errors{ 149 "ContractID": validation.Validate(cp.ContractID, validation.Required), 150 "GroupID": validation.Validate(cp.GroupID, validation.Required), 151 "CPCodeID": validation.Validate(cp.CPCodeID, validation.Required), 152 }.Filter() 153 } 154 155 // Validate validates CPCodeContract 156 func (contract CPCodeContract) Validate() error { 157 return validation.Errors{ 158 "ContractID": validation.Validate(contract.ContractID, validation.Required), 159 }.Filter() 160 } 161 162 // Validate validates CPCodeProduct 163 func (product CPCodeProduct) Validate() error { 164 return validation.Errors{ 165 "ProductID": validation.Validate(product.ProductID, validation.Required), 166 }.Filter() 167 } 168 169 // Validate validates CPCodeTimeZone 170 func (timeZone CPCodeTimeZone) Validate() error { 171 return validation.Errors{ 172 "TimeZoneID": validation.Validate(timeZone.TimeZoneID, validation.Required), 173 }.Filter() 174 } 175 176 // Validate validates CreateCPCodeRequest 177 func (cp CreateCPCodeRequest) Validate() error { 178 return validation.Errors{ 179 "ContractID": validation.Validate(cp.ContractID, validation.Required), 180 "GroupID": validation.Validate(cp.GroupID, validation.Required), 181 "CPCode": validation.Validate(cp.CPCode, validation.Required), 182 }.Filter() 183 } 184 185 // Validate validates CreateCPCode 186 func (cp CreateCPCode) Validate() error { 187 return validation.Errors{ 188 "ProductID": validation.Validate(cp.ProductID, validation.Required), 189 "CPCodeName": validation.Validate(cp.CPCodeName, validation.Required), 190 }.Filter() 191 } 192 193 // Validate validates UpdateCPCodeRequest 194 func (cp UpdateCPCodeRequest) Validate() error { 195 return validation.Errors{ 196 "ID": validation.Validate(cp.ID, validation.Required), 197 "Name": validation.Validate(cp.Name, validation.Required), 198 "Contracts": validation.Validate(cp.Contracts, validation.Required), 199 "Products": validation.Validate(cp.Products, validation.Required), 200 "OverrideTimeZone": validation.Validate(cp.OverrideTimeZone), 201 }.Filter() 202 } 203 204 var ( 205 // ErrGetCPCodes represents error when fetching CP Codes fails 206 ErrGetCPCodes = errors.New("fetching CP Codes") 207 // ErrGetCPCode represents error when fetching CP Code fails 208 ErrGetCPCode = errors.New("fetching CP Code") 209 // ErrGetCPCodeDetail represents error when fetching CP Code Details fails 210 ErrGetCPCodeDetail = errors.New("fetching CP Code Detail") 211 // ErrCreateCPCode represents error when creating CP Code fails 212 ErrCreateCPCode = errors.New("creating CP Code") 213 // ErrUpdateCPCode represents error when updating CP Code 214 ErrUpdateCPCode = errors.New("updating CP Code") 215 ) 216 217 // GetCPCodes is used to list all available CP codes for given group and contract 218 func (p *papi) GetCPCodes(ctx context.Context, params GetCPCodesRequest) (*GetCPCodesResponse, error) { 219 if err := params.Validate(); err != nil { 220 return nil, fmt.Errorf("%s: %w: %s", ErrGetCPCodes, ErrStructValidation, err) 221 } 222 223 logger := p.Log(ctx) 224 logger.Debug("GetCPCodes") 225 226 getURL := fmt.Sprintf( 227 "/papi/v1/cpcodes?contractId=%s&groupId=%s", 228 params.ContractID, 229 params.GroupID, 230 ) 231 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 232 if err != nil { 233 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetCPCodes, err) 234 } 235 236 var cpCodes GetCPCodesResponse 237 resp, err := p.Exec(req, &cpCodes) 238 if err != nil { 239 return nil, fmt.Errorf("%w: request failed: %s", ErrGetCPCodes, err) 240 } 241 242 if resp.StatusCode != http.StatusOK { 243 return nil, fmt.Errorf("%s: %w", ErrGetCPCodes, p.Error(resp)) 244 } 245 246 return &cpCodes, nil 247 } 248 249 // GetCPCode is used to fetch a CP code with provided ID 250 func (p *papi) GetCPCode(ctx context.Context, params GetCPCodeRequest) (*GetCPCodesResponse, error) { 251 if err := params.Validate(); err != nil { 252 return nil, fmt.Errorf("%s: %w: %s", ErrGetCPCode, ErrStructValidation, err) 253 } 254 255 logger := p.Log(ctx) 256 logger.Debug("GetCPCode") 257 258 getURL := fmt.Sprintf("/papi/v1/cpcodes/%s?contractId=%s&groupId=%s", params.CPCodeID, params.ContractID, params.GroupID) 259 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 260 if err != nil { 261 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetCPCode, err) 262 } 263 264 var cpCodes GetCPCodesResponse 265 resp, err := p.Exec(req, &cpCodes) 266 if err != nil { 267 return nil, fmt.Errorf("%w: request failed: %s", ErrGetCPCode, err) 268 } 269 270 if resp.StatusCode != http.StatusOK { 271 return nil, fmt.Errorf("%s: %w", ErrGetCPCode, p.Error(resp)) 272 } 273 if len(cpCodes.CPCodes.Items) == 0 { 274 return nil, fmt.Errorf("%s: %w: CPCodeID: %s", ErrGetCPCode, ErrNotFound, params.CPCodeID) 275 } 276 cpCodes.CPCode = cpCodes.CPCodes.Items[0] 277 278 return &cpCodes, nil 279 } 280 281 // GetCPCodeDetail is used to fetch CP code detail with provided ID using CPRG API 282 func (p *papi) GetCPCodeDetail(ctx context.Context, ID int) (*CPCodeDetailResponse, error) { 283 logger := p.Log(ctx) 284 logger.Debug("GetCPCodeDetail") 285 286 getURL := fmt.Sprintf("/cprg/v1/cpcodes/%d", ID) 287 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 288 if err != nil { 289 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetCPCodeDetail, err) 290 } 291 292 var cpCodeDetail CPCodeDetailResponse 293 resp, err := p.Exec(req, &cpCodeDetail) 294 if err != nil { 295 return nil, fmt.Errorf("%w: request failed: %s", ErrGetCPCodeDetail, err) 296 } 297 298 if resp.StatusCode != http.StatusOK { 299 return nil, fmt.Errorf("%s: %w", ErrGetCPCodeDetail, p.Error(resp)) 300 } 301 302 return &cpCodeDetail, nil 303 } 304 305 // CreateCPCode creates a new CP code with provided CreateCPCodeRequest data 306 func (p *papi) CreateCPCode(ctx context.Context, r CreateCPCodeRequest) (*CreateCPCodeResponse, error) { 307 if err := r.Validate(); err != nil { 308 return nil, fmt.Errorf("%s: %w: %v", ErrCreateCPCode, ErrStructValidation, err) 309 } 310 311 logger := p.Log(ctx) 312 logger.Debug("CreateCPCode") 313 314 createURL := fmt.Sprintf("/papi/v1/cpcodes?contractId=%s&groupId=%s", r.ContractID, r.GroupID) 315 req, err := http.NewRequestWithContext(ctx, http.MethodPost, createURL, nil) 316 if err != nil { 317 return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateCPCode, err) 318 } 319 320 var createResponse CreateCPCodeResponse 321 resp, err := p.Exec(req, &createResponse, r.CPCode) 322 if err != nil { 323 return nil, fmt.Errorf("%w: request failed: %s", ErrCreateCPCode, err) 324 } 325 if resp.StatusCode != http.StatusCreated { 326 return nil, fmt.Errorf("%s: %w", ErrCreateCPCode, p.Error(resp)) 327 } 328 id, err := ResponseLinkParse(createResponse.CPCodeLink) 329 if err != nil { 330 return nil, fmt.Errorf("%s: %w: %s", ErrCreateCPCode, ErrInvalidResponseLink, err) 331 } 332 createResponse.CPCodeID = id 333 return &createResponse, nil 334 } 335 336 // UpdateCPCode is used to update CP code using CPRG API 337 func (p *papi) UpdateCPCode(ctx context.Context, r UpdateCPCodeRequest) (*CPCodeDetailResponse, error) { 338 if err := r.Validate(); err != nil { 339 return nil, fmt.Errorf("%s: %w: %v", ErrUpdateCPCode, ErrStructValidation, err) 340 } 341 342 logger := p.Log(ctx) 343 logger.Debug("UpdateCPCode") 344 345 updateURL := fmt.Sprintf("/cprg/v1/cpcodes/%d", r.ID) 346 req, err := http.NewRequestWithContext(ctx, http.MethodPut, updateURL, nil) 347 if err != nil { 348 return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateCPCode, err) 349 } 350 351 var cpCodeDetail CPCodeDetailResponse 352 resp, err := p.Exec(req, &cpCodeDetail, r) 353 if err != nil { 354 return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateCPCode, err) 355 } 356 357 if resp.StatusCode != http.StatusOK { 358 return nil, fmt.Errorf("%s: %w", ErrUpdateCPCode, p.Error(resp)) 359 } 360 361 return &cpCodeDetail, nil 362 }