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  }