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