github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/edgeworkers/edgekv_namespaces.go (about)

     1  package edgeworkers
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  
    10  	validation "github.com/go-ozzo/ozzo-validation/v4"
    11  )
    12  
    13  type (
    14  	// EdgeKVNamespaces is an EdgeKV namespaces API interface
    15  	EdgeKVNamespaces interface {
    16  		// ListEdgeKVNamespaces lists all namespaces in the given network
    17  		//
    18  		// See: https://techdocs.akamai.com/edgekv/reference/get-namespaces
    19  		ListEdgeKVNamespaces(context.Context, ListEdgeKVNamespacesRequest) (*ListEdgeKVNamespacesResponse, error)
    20  
    21  		// GetEdgeKVNamespace fetches a namespace by name
    22  		//
    23  		// See: https://techdocs.akamai.com/edgekv/reference/get-namespace
    24  		GetEdgeKVNamespace(context.Context, GetEdgeKVNamespaceRequest) (*Namespace, error)
    25  
    26  		// CreateEdgeKVNamespace creates a namespace on the given network
    27  		//
    28  		// See: https://techdocs.akamai.com/edgekv/reference/post-namespace
    29  		CreateEdgeKVNamespace(context.Context, CreateEdgeKVNamespaceRequest) (*Namespace, error)
    30  
    31  		// UpdateEdgeKVNamespace updates a namespace
    32  		//
    33  		// See: https://techdocs.akamai.com/edgekv/reference/put-namespace
    34  		UpdateEdgeKVNamespace(context.Context, UpdateEdgeKVNamespaceRequest) (*Namespace, error)
    35  	}
    36  
    37  	// ListEdgeKVNamespacesRequest contains path parameters used to list namespaces
    38  	ListEdgeKVNamespacesRequest struct {
    39  		Network NamespaceNetwork
    40  		Details bool
    41  	}
    42  
    43  	// GetEdgeKVNamespaceRequest contains path parameters used to feth a namespace
    44  	GetEdgeKVNamespaceRequest struct {
    45  		Network NamespaceNetwork
    46  		Name    string
    47  	}
    48  
    49  	// CreateEdgeKVNamespaceRequest contains path parameter and request body used to create a namespace
    50  	CreateEdgeKVNamespaceRequest struct {
    51  		Network NamespaceNetwork
    52  		Namespace
    53  	}
    54  
    55  	// UpdateEdgeKVNamespaceRequest contains path parameters and request body used to update a namespace
    56  	UpdateEdgeKVNamespaceRequest struct {
    57  		Network NamespaceNetwork
    58  		UpdateNamespace
    59  	}
    60  
    61  	// ListEdgeKVNamespacesResponse represents a response object returned when listing namespaces
    62  	ListEdgeKVNamespacesResponse struct {
    63  		Namespaces []Namespace `json:"namespaces"`
    64  	}
    65  
    66  	// Namespace represents a namespace object and a request body used to create a namespace
    67  	Namespace struct {
    68  		Name        string `json:"namespace"`
    69  		GeoLocation string `json:"geoLocation,omitempty"`
    70  		Retention   *int   `json:"retentionInSeconds,omitempty"`
    71  		GroupID     *int   `json:"groupId,omitempty"`
    72  	}
    73  
    74  	// UpdateNamespace represents a request body used to update a namespace
    75  	UpdateNamespace struct {
    76  		Name      string `json:"namespace"`
    77  		Retention *int   `json:"retentionInSeconds"`
    78  		GroupID   *int   `json:"groupId"`
    79  	}
    80  
    81  	// NamespaceNetwork represents available namespace network types
    82  	NamespaceNetwork string
    83  )
    84  
    85  const (
    86  	// NamespaceStagingNetwork is the staging network
    87  	NamespaceStagingNetwork NamespaceNetwork = "staging"
    88  	// NamespaceProductionNetwork is the production network
    89  	NamespaceProductionNetwork NamespaceNetwork = "production"
    90  )
    91  
    92  // Validate validates ListEdgeKVNamespacesRequest
    93  func (r ListEdgeKVNamespacesRequest) Validate() error {
    94  	return validation.Errors{
    95  		"Network": validation.Validate(r.Network, validation.Required, validation.In(NamespaceStagingNetwork, NamespaceProductionNetwork).Error(
    96  			fmt.Sprintf("value '%s' is invalid. Must be one of: '%s' or '%s'", r.Network, NamespaceStagingNetwork, NamespaceProductionNetwork))),
    97  	}.Filter()
    98  }
    99  
   100  // Validate validates GetEdgeKVNamespaceRequest
   101  func (r GetEdgeKVNamespaceRequest) Validate() error {
   102  	return validation.Errors{
   103  		"Network": validation.Validate(r.Network, validation.Required, validation.In(NamespaceStagingNetwork, NamespaceProductionNetwork).Error(
   104  			fmt.Sprintf("value '%s' is invalid. Must be one of: '%s' or '%s'", r.Network, NamespaceStagingNetwork, NamespaceProductionNetwork))),
   105  		"Name": validation.Validate(r.Name, validation.Required, validation.Length(1, 32)),
   106  	}.Filter()
   107  }
   108  
   109  // Validate validates CreateEdgeKVNamespaceRequest
   110  func (r CreateEdgeKVNamespaceRequest) Validate() error {
   111  	return validation.Errors{
   112  		"Network": validation.Validate(r.Network, validation.Required, validation.In(NamespaceStagingNetwork, NamespaceProductionNetwork).Error(
   113  			fmt.Sprintf("value '%s' is invalid. Must be one of: '%s' or '%s'", r.Network, NamespaceStagingNetwork, NamespaceProductionNetwork))),
   114  		"Name":      validation.Validate(r.Name, validation.Required, validation.Length(1, 32)),
   115  		"Retention": validation.Validate(r.Retention, validation.By(validateRetention)),
   116  		"GroupID":   validation.Validate(r.GroupID, validation.By(validateGroupID)),
   117  	}.Filter()
   118  }
   119  
   120  // Validate validates UpdateEdgeKVNamespaceRequest
   121  func (r UpdateEdgeKVNamespaceRequest) Validate() error {
   122  	return validation.Errors{
   123  		"Network": validation.Validate(r.Network, validation.Required, validation.In(NamespaceStagingNetwork, NamespaceProductionNetwork).Error(
   124  			fmt.Sprintf("value '%s' is invalid. Must be one of: '%s' or '%s'", r.Network, NamespaceStagingNetwork, NamespaceProductionNetwork))),
   125  		"Name":      validation.Validate(r.Name, validation.Required, validation.Length(1, 32)),
   126  		"Retention": validation.Validate(r.Retention, validation.By(validateRetention)),
   127  		"GroupID":   validation.Validate(r.GroupID, validation.By(validateGroupID)),
   128  	}.Filter()
   129  }
   130  
   131  func validateRetention(value interface{}) error {
   132  	v, ok := value.(*int)
   133  	if !ok {
   134  		return fmt.Errorf("type %T is invalid. Must be *int", value)
   135  	}
   136  	if v == nil {
   137  		return fmt.Errorf("cannot be blank")
   138  	}
   139  	if (*v < 86400 && *v != 0) || *v > 315360000 {
   140  		return fmt.Errorf("a non zero value specified for retention period cannot be less than 86400 or more than 315360000")
   141  	}
   142  	return nil
   143  }
   144  
   145  func validateGroupID(value interface{}) error {
   146  	v, ok := value.(*int)
   147  	if !ok {
   148  		return fmt.Errorf("type %T is invalid. Must be *int", value)
   149  	}
   150  	if v == nil {
   151  		return fmt.Errorf("cannot be blank")
   152  	}
   153  	if *v < 0 {
   154  		return fmt.Errorf("cannot be less than 0")
   155  	}
   156  	return nil
   157  }
   158  
   159  var (
   160  	// ErrListEdgeKVNamespace is returned when ListEdgeKVNamespaces fails
   161  	ErrListEdgeKVNamespace = errors.New("list EdgeKV namespaces")
   162  	// ErrGetEdgeKVNamespace is returned when GetEdgeKVNamespace fails
   163  	ErrGetEdgeKVNamespace = errors.New("get an EdgeKV namespace")
   164  	// ErrCreateEdgeKVNamespace is returned when CreateEdgeKVNamespace fails
   165  	ErrCreateEdgeKVNamespace = errors.New("create an EdgeKV namespace")
   166  	// ErrUpdateEdgeKVNamespace is returned when UpdateEdgeKVNamespace fails
   167  	ErrUpdateEdgeKVNamespace = errors.New("update an EdgeKV namespace")
   168  )
   169  
   170  func (e *edgeworkers) ListEdgeKVNamespaces(ctx context.Context, params ListEdgeKVNamespacesRequest) (*ListEdgeKVNamespacesResponse, error) {
   171  	logger := e.Log(ctx)
   172  	logger.Debug("ListEdgeKVNamespaces")
   173  
   174  	if err := params.Validate(); err != nil {
   175  		return nil, fmt.Errorf("%s: %w: %s", ErrListEdgeKVNamespace, ErrStructValidation, err.Error())
   176  	}
   177  
   178  	uri, err := url.Parse(fmt.Sprintf("/edgekv/v1/networks/%s/namespaces", params.Network))
   179  	if err != nil {
   180  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrListEdgeKVNamespace, err.Error())
   181  	}
   182  
   183  	if params.Details {
   184  		q := uri.Query()
   185  		q.Add("details", "on")
   186  		uri.RawQuery = q.Encode()
   187  	}
   188  
   189  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   190  	if err != nil {
   191  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListEdgeKVNamespace, err.Error())
   192  	}
   193  
   194  	var result ListEdgeKVNamespacesResponse
   195  	resp, err := e.Exec(req, &result)
   196  	if err != nil {
   197  		return nil, fmt.Errorf("%w: request failed: %s", ErrListEdgeKVNamespace, err.Error())
   198  	}
   199  
   200  	if resp.StatusCode != http.StatusOK {
   201  		return nil, fmt.Errorf("%s: %w", ErrListEdgeKVNamespace, e.Error(resp))
   202  	}
   203  
   204  	return &result, nil
   205  }
   206  
   207  func (e *edgeworkers) GetEdgeKVNamespace(ctx context.Context, params GetEdgeKVNamespaceRequest) (*Namespace, error) {
   208  	logger := e.Log(ctx)
   209  	logger.Debug("GetEdgeKVNamespace")
   210  
   211  	if err := params.Validate(); err != nil {
   212  		return nil, fmt.Errorf("%s: %w: %s", ErrGetEdgeKVNamespace, ErrStructValidation, err.Error())
   213  	}
   214  
   215  	uri := fmt.Sprintf("/edgekv/v1/networks/%s/namespaces/%s", params.Network, params.Name)
   216  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
   217  	if err != nil {
   218  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetEdgeKVNamespace, err.Error())
   219  	}
   220  
   221  	var result Namespace
   222  	resp, err := e.Exec(req, &result)
   223  	if err != nil {
   224  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetEdgeKVNamespace, err.Error())
   225  	}
   226  
   227  	if resp.StatusCode != http.StatusOK {
   228  		return nil, fmt.Errorf("%s: %w", ErrGetEdgeKVNamespace, e.Error(resp))
   229  	}
   230  
   231  	return &result, nil
   232  }
   233  
   234  func (e *edgeworkers) CreateEdgeKVNamespace(ctx context.Context, params CreateEdgeKVNamespaceRequest) (*Namespace, error) {
   235  	logger := e.Log(ctx)
   236  	logger.Debug("CreateEdgeKVNamespace")
   237  
   238  	if err := params.Validate(); err != nil {
   239  		return nil, fmt.Errorf("%s: %w: %s", ErrCreateEdgeKVNamespace, ErrStructValidation, err.Error())
   240  	}
   241  
   242  	uri := fmt.Sprintf("/edgekv/v1/networks/%s/namespaces", params.Network)
   243  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil)
   244  	if err != nil {
   245  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateEdgeKVNamespace, err.Error())
   246  	}
   247  
   248  	var result Namespace
   249  	resp, err := e.Exec(req, &result, params.Namespace)
   250  	if err != nil {
   251  		return nil, fmt.Errorf("%w: request failed: %s", ErrCreateEdgeKVNamespace, err.Error())
   252  	}
   253  
   254  	if resp.StatusCode != http.StatusOK {
   255  		return nil, fmt.Errorf("%s: %w", ErrCreateEdgeKVNamespace, e.Error(resp))
   256  	}
   257  
   258  	return &result, nil
   259  }
   260  
   261  func (e *edgeworkers) UpdateEdgeKVNamespace(ctx context.Context, params UpdateEdgeKVNamespaceRequest) (*Namespace, error) {
   262  	logger := e.Log(ctx)
   263  	logger.Debug("UpdateEdgeKVNamespace")
   264  
   265  	if err := params.Validate(); err != nil {
   266  		return nil, fmt.Errorf("%s: %w: %s", ErrUpdateEdgeKVNamespace, ErrStructValidation, err.Error())
   267  	}
   268  
   269  	uri := fmt.Sprintf("/edgekv/v1/networks/%s/namespaces/%s", params.Network, params.Name)
   270  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil)
   271  	if err != nil {
   272  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateEdgeKVNamespace, err.Error())
   273  	}
   274  
   275  	var result Namespace
   276  	resp, err := e.Exec(req, &result, params.UpdateNamespace)
   277  	if err != nil {
   278  		return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateEdgeKVNamespace, err.Error())
   279  	}
   280  
   281  	if resp.StatusCode != http.StatusOK {
   282  		return nil, fmt.Errorf("%s: %w", ErrUpdateEdgeKVNamespace, e.Error(resp))
   283  	}
   284  
   285  	return &result, nil
   286  }