github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/cloudlets/v3/policy.go (about) 1 package v3 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/url" 9 "regexp" 10 "strconv" 11 "time" 12 13 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr" 14 validation "github.com/go-ozzo/ozzo-validation/v4" 15 ) 16 17 type ( 18 // ListPoliciesRequest contains request parameters for ListPolicies 19 ListPoliciesRequest struct { 20 Page int 21 Size int 22 } 23 24 // CreatePolicyRequest contains request parameters for CreatePolicy 25 CreatePolicyRequest struct { 26 CloudletType CloudletType `json:"cloudletType"` 27 Description *string `json:"description,omitempty"` 28 GroupID int64 `json:"groupId"` 29 Name string `json:"name"` 30 PolicyType PolicyType `json:"policyType,omitempty"` 31 } 32 33 // DeletePolicyRequest contains request parameters for DeletePolicy 34 DeletePolicyRequest struct { 35 PolicyID int64 36 } 37 38 // GetPolicyRequest contains request parameters for GetPolicy 39 GetPolicyRequest struct { 40 PolicyID int64 41 } 42 43 // UpdatePolicyRequest contains request parameters for UpdatePolicy 44 UpdatePolicyRequest struct { 45 PolicyID int64 46 BodyParams UpdatePolicyBodyParams 47 } 48 49 // ClonePolicyRequest contains request parameters for ClonePolicy 50 ClonePolicyRequest struct { 51 PolicyID int64 52 BodyParams ClonePolicyBodyParams 53 } 54 55 // ClonePolicyBodyParams contains request body parameters used in ClonePolicy operation 56 // GroupID is required only when cloning v2 57 ClonePolicyBodyParams struct { 58 AdditionalVersions []int64 `json:"additionalVersions,omitempty"` 59 GroupID int64 `json:"groupId,omitempty"` 60 NewName string `json:"newName"` 61 } 62 63 // UpdatePolicyBodyParams contains request body parameters used in UpdatePolicy operation 64 UpdatePolicyBodyParams struct { 65 GroupID int64 `json:"groupId"` 66 Description *string `json:"description,omitempty"` 67 } 68 69 // PolicyType represents the type of the policy 70 PolicyType string 71 72 // CloudletType represents the type of the cloudlet 73 CloudletType string 74 75 // ListPoliciesResponse contains the response data from ListPolicies operation 76 ListPoliciesResponse struct { 77 Content []Policy `json:"content"` 78 Links []Link `json:"links"` 79 Page Page `json:"page"` 80 } 81 82 // Policy contains information about shared policy 83 Policy struct { 84 CloudletType CloudletType `json:"cloudletType"` 85 CreatedBy string `json:"createdBy"` 86 CreatedDate time.Time `json:"createdDate"` 87 CurrentActivations CurrentActivations `json:"currentActivations"` 88 Description *string `json:"description"` 89 GroupID int64 `json:"groupId"` 90 ID int64 `json:"id"` 91 Links []Link `json:"links"` 92 ModifiedBy string `json:"modifiedBy"` 93 ModifiedDate *time.Time `json:"modifiedDate,omitempty"` 94 Name string `json:"name"` 95 PolicyType PolicyType `json:"policyType"` 96 } 97 98 // CurrentActivations contains information about the active policy version that's currently in use and the status of the most recent activation 99 // or deactivation operation on the policy's versions for the production and staging networks 100 CurrentActivations struct { 101 Production ActivationInfo `json:"production"` 102 Staging ActivationInfo `json:"staging"` 103 } 104 105 // ActivationInfo contains information about effective and latest activations 106 ActivationInfo struct { 107 Effective *PolicyActivation `json:"effective"` 108 Latest *PolicyActivation `json:"latest"` 109 } 110 ) 111 112 const ( 113 // PolicyTypeShared represents policy of type SHARED 114 PolicyTypeShared = PolicyType("SHARED") 115 // CloudletTypeAP represents cloudlet of type AP 116 CloudletTypeAP = CloudletType("AP") 117 // CloudletTypeAS represents cloudlet of type AS 118 CloudletTypeAS = CloudletType("AS") 119 // CloudletTypeCD represents cloudlet of type CD 120 CloudletTypeCD = CloudletType("CD") 121 // CloudletTypeER represents cloudlet of type ER 122 CloudletTypeER = CloudletType("ER") 123 // CloudletTypeFR represents cloudlet of type FR 124 CloudletTypeFR = CloudletType("FR") 125 // CloudletTypeIG represents cloudlet of type IG 126 CloudletTypeIG = CloudletType("IG") 127 ) 128 129 var ( 130 // ErrListPolicies is returned when ListPolicies fails 131 ErrListPolicies = errors.New("list shared policies") 132 // ErrCreatePolicy is returned when CreatePolicy fails 133 ErrCreatePolicy = errors.New("create shared policy") 134 // ErrDeletePolicy is returned when DeletePolicy fails 135 ErrDeletePolicy = errors.New("delete shared policy") 136 // ErrGetPolicy is returned when GetPolicy fails 137 ErrGetPolicy = errors.New("get shared policy") 138 // ErrUpdatePolicy is returned when UpdatePolicy fails 139 ErrUpdatePolicy = errors.New("update shared policy") 140 // ErrClonePolicy is returned when ClonePolicy fails 141 ErrClonePolicy = errors.New("clone policy") 142 ) 143 144 // Validate validates ListPoliciesRequest 145 func (r ListPoliciesRequest) Validate() error { 146 return edgegriderr.ParseValidationErrors(validation.Errors{ 147 "Page": validation.Validate(r.Page, validation.Min(0)), 148 "Size": validation.Validate(r.Size, validation.Min(10)), 149 }) 150 } 151 152 // Validate validates CreatePolicyRequest 153 func (r CreatePolicyRequest) Validate() error { 154 return edgegriderr.ParseValidationErrors(validation.Errors{ 155 "CloudletType": validation.Validate(r.CloudletType, validation.Required, validation.In(CloudletTypeAP, CloudletTypeAS, CloudletTypeCD, CloudletTypeER, CloudletTypeFR, CloudletTypeIG). 156 Error(fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s', '%s', '%s', '%s', '%s'", r.CloudletType, CloudletTypeAP, CloudletTypeAS, CloudletTypeCD, CloudletTypeER, CloudletTypeFR, CloudletTypeIG))), 157 "Name": validation.Validate(r.Name, validation.Required, validation.Length(0, 64), validation.Match(regexp.MustCompile("^[a-z_A-Z0-9]+$")). 158 Error(fmt.Sprintf("value '%s' is invalid. Must be of format: ^[a-z_A-Z0-9]+$", r.Name))), 159 "GroupID": validation.Validate(r.GroupID, validation.Required), 160 "Description": validation.Validate(r.Description, validation.Length(0, 255)), 161 "PolicyType": validation.Validate(r.PolicyType, validation.In(PolicyTypeShared).Error(fmt.Sprintf("value '%s' is invalid. Must be '%s'", r.PolicyType, PolicyTypeShared))), 162 }) 163 } 164 165 // Validate validates DeletePolicyRequest 166 func (r DeletePolicyRequest) Validate() error { 167 return edgegriderr.ParseValidationErrors(validation.Errors{ 168 "PolicyID": validation.Validate(r.PolicyID, validation.Required), 169 }) 170 } 171 172 // Validate validates GetPolicyRequest 173 func (r GetPolicyRequest) Validate() error { 174 return edgegriderr.ParseValidationErrors(validation.Errors{ 175 "PolicyID": validation.Validate(r.PolicyID, validation.Required), 176 }) 177 } 178 179 // Validate validates UpdatePolicyRequest 180 func (r UpdatePolicyRequest) Validate() error { 181 return edgegriderr.ParseValidationErrors(validation.Errors{ 182 "PolicyID": validation.Validate(r.PolicyID, validation.Required), 183 "BodyParams": validation.Validate(r.BodyParams, validation.Required), 184 }) 185 } 186 187 // Validate validates UpdatePolicyBodyParams 188 func (b UpdatePolicyBodyParams) Validate() error { 189 return validation.Errors{ 190 "GroupID": validation.Validate(b.GroupID, validation.Required), 191 "Description": validation.Validate(b.Description, validation.Length(0, 255)), 192 }.Filter() 193 } 194 195 // Validate validates ClonePolicyRequest 196 func (r ClonePolicyRequest) Validate() error { 197 return edgegriderr.ParseValidationErrors(validation.Errors{ 198 "PolicyID": validation.Validate(r.PolicyID, validation.Required), 199 "BodyParams": validation.Validate(r.BodyParams, validation.Required), 200 }) 201 } 202 203 // Validate validates ClonePolicyBodyParams 204 func (b ClonePolicyBodyParams) Validate() error { 205 return validation.Errors{ 206 "NewName": validation.Validate(b.NewName, validation.Required, validation.Length(0, 64), validation.Match(regexp.MustCompile("^[a-z_A-Z0-9]+$")). 207 Error(fmt.Sprintf("value '%s' is invalid. Must be of format: ^[a-z_A-Z0-9]+$", b.NewName))), 208 }.Filter() 209 } 210 211 func (c *cloudlets) ListPolicies(ctx context.Context, params ListPoliciesRequest) (*ListPoliciesResponse, error) { 212 logger := c.Log(ctx) 213 logger.Debug("ListPolicies") 214 215 if err := params.Validate(); err != nil { 216 return nil, fmt.Errorf("%s: %w: %s", ErrListPolicies, ErrStructValidation, err) 217 } 218 219 uri, err := url.Parse("/cloudlets/v3/policies") 220 if err != nil { 221 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrListPolicies, err) 222 } 223 224 q := uri.Query() 225 if params.Size != 0 { 226 q.Add("size", strconv.Itoa(params.Size)) 227 } 228 if params.Page != 0 { 229 q.Add("page", strconv.Itoa(params.Page)) 230 } 231 232 uri.RawQuery = q.Encode() 233 234 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil) 235 if err != nil { 236 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListPolicies, err) 237 } 238 239 var result ListPoliciesResponse 240 resp, err := c.Exec(req, &result) 241 if err != nil { 242 return nil, fmt.Errorf("%w: request failed: %s", ErrListPolicies, err) 243 } 244 245 if resp.StatusCode != http.StatusOK { 246 return nil, fmt.Errorf("%s: %w", ErrListPolicies, c.Error(resp)) 247 } 248 249 return &result, nil 250 } 251 252 func (c *cloudlets) CreatePolicy(ctx context.Context, params CreatePolicyRequest) (*Policy, error) { 253 logger := c.Log(ctx) 254 logger.Debug("CreatePolicy") 255 256 if err := params.Validate(); err != nil { 257 return nil, fmt.Errorf("%s: %w: %s", ErrCreatePolicy, ErrStructValidation, err) 258 } 259 260 uri := "/cloudlets/v3/policies" 261 262 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil) 263 if err != nil { 264 return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreatePolicy, err) 265 } 266 267 var result Policy 268 resp, err := c.Exec(req, &result, params) 269 if err != nil { 270 return nil, fmt.Errorf("%w: request failed: %s", ErrCreatePolicy, err) 271 } 272 273 if resp.StatusCode != http.StatusCreated { 274 return nil, fmt.Errorf("%s: %w", ErrCreatePolicy, c.Error(resp)) 275 } 276 277 return &result, nil 278 } 279 280 func (c *cloudlets) DeletePolicy(ctx context.Context, params DeletePolicyRequest) error { 281 logger := c.Log(ctx) 282 logger.Debug("DeletePolicy") 283 284 if err := params.Validate(); err != nil { 285 return fmt.Errorf("%s: %w: %s", ErrDeletePolicy, ErrStructValidation, err) 286 } 287 288 uri := fmt.Sprintf("/cloudlets/v3/policies/%d", params.PolicyID) 289 290 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil) 291 if err != nil { 292 return fmt.Errorf("%w: failed to create request: %s", ErrDeletePolicy, err) 293 } 294 295 resp, err := c.Exec(req, nil) 296 if err != nil { 297 return fmt.Errorf("%w: request failed: %s", ErrDeletePolicy, err) 298 } 299 300 if resp.StatusCode != http.StatusNoContent { 301 return fmt.Errorf("%s: %w", ErrDeletePolicy, c.Error(resp)) 302 } 303 304 return nil 305 } 306 307 func (c *cloudlets) GetPolicy(ctx context.Context, params GetPolicyRequest) (*Policy, error) { 308 logger := c.Log(ctx) 309 logger.Debug("GetPolicy") 310 311 if err := params.Validate(); err != nil { 312 return nil, fmt.Errorf("%s: %w: %s", ErrGetPolicy, ErrStructValidation, err) 313 } 314 315 uri := fmt.Sprintf("/cloudlets/v3/policies/%d", params.PolicyID) 316 317 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 318 if err != nil { 319 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetPolicy, err) 320 } 321 322 var result Policy 323 resp, err := c.Exec(req, &result) 324 if err != nil { 325 return nil, fmt.Errorf("%w: request failed: %s", ErrGetPolicy, err) 326 } 327 328 if resp.StatusCode == http.StatusNotFound { 329 return nil, fmt.Errorf("%s: %w: %s", ErrGetPolicy, ErrPolicyNotFound, c.Error(resp)) 330 } 331 332 if resp.StatusCode != http.StatusOK { 333 return nil, fmt.Errorf("%s: %w", ErrGetPolicy, c.Error(resp)) 334 } 335 336 return &result, nil 337 } 338 339 func (c *cloudlets) UpdatePolicy(ctx context.Context, params UpdatePolicyRequest) (*Policy, error) { 340 logger := c.Log(ctx) 341 logger.Debug("UpdatePolicy") 342 343 if err := params.Validate(); err != nil { 344 return nil, fmt.Errorf("%s: %w: %s", ErrUpdatePolicy, ErrStructValidation, err) 345 } 346 347 uri := fmt.Sprintf("/cloudlets/v3/policies/%d", params.PolicyID) 348 349 req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil) 350 if err != nil { 351 return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdatePolicy, err) 352 } 353 354 var result Policy 355 resp, err := c.Exec(req, &result, params.BodyParams) 356 if err != nil { 357 return nil, fmt.Errorf("%w: request failed: %s", ErrUpdatePolicy, err) 358 } 359 360 if resp.StatusCode != http.StatusOK { 361 return nil, fmt.Errorf("%s: %w", ErrUpdatePolicy, c.Error(resp)) 362 } 363 364 return &result, nil 365 } 366 367 func (c *cloudlets) ClonePolicy(ctx context.Context, params ClonePolicyRequest) (*Policy, error) { 368 logger := c.Log(ctx) 369 logger.Debug("ClonePolicy") 370 371 if err := params.Validate(); err != nil { 372 return nil, fmt.Errorf("%s: %w: %s", ErrClonePolicy, ErrStructValidation, err) 373 } 374 375 uri := fmt.Sprintf("/cloudlets/v3/policies/%d/clone", params.PolicyID) 376 377 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil) 378 if err != nil { 379 return nil, fmt.Errorf("%w: failed to create request: %s", ErrClonePolicy, err) 380 } 381 382 var result Policy 383 resp, err := c.Exec(req, &result, params.BodyParams) 384 if err != nil { 385 return nil, fmt.Errorf("%w: request failed: %s", ErrClonePolicy, err) 386 } 387 388 if resp.StatusCode != http.StatusOK { 389 return nil, fmt.Errorf("%s: %w", ErrClonePolicy, c.Error(resp)) 390 } 391 392 return &result, nil 393 }