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 }