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  }