github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/cloudwrapper/configurations.go (about) 1 package cloudwrapper 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/url" 9 "strconv" 10 11 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr" 12 validation "github.com/go-ozzo/ozzo-validation/v4" 13 ) 14 15 type ( 16 // Configurations is a CloudWrapper configurations API interface 17 Configurations interface { 18 // GetConfiguration gets a specific Cloud Wrapper configuration 19 // 20 // See: https://techdocs.akamai.com/cloud-wrapper/reference/get-configuration 21 GetConfiguration(context.Context, GetConfigurationRequest) (*Configuration, error) 22 // ListConfigurations lists all Cloud Wrapper configurations on your contract 23 // 24 // See: https://techdocs.akamai.com/cloud-wrapper/reference/get-configurations 25 ListConfigurations(context.Context) (*ListConfigurationsResponse, error) 26 // CreateConfiguration creates a Cloud Wrapper configuration 27 // 28 // See: https://techdocs.akamai.com/cloud-wrapper/reference/post-configuration 29 CreateConfiguration(context.Context, CreateConfigurationRequest) (*Configuration, error) 30 // UpdateConfiguration updates a saved or inactive configuration 31 // 32 // See: https://techdocs.akamai.com/cloud-wrapper/reference/put-configuration 33 UpdateConfiguration(context.Context, UpdateConfigurationRequest) (*Configuration, error) 34 // DeleteConfiguration deletes configuration 35 // 36 // See: https://techdocs.akamai.com/cloud-wrapper/reference/delete-configuration 37 DeleteConfiguration(context.Context, DeleteConfigurationRequest) error 38 // ActivateConfiguration activates a Cloud Wrapper configuration 39 // 40 // See: https://techdocs.akamai.com/cloud-wrapper/reference/post-configuration-activations 41 ActivateConfiguration(context.Context, ActivateConfigurationRequest) error 42 } 43 44 // GetConfigurationRequest holds parameters for GetConfiguration 45 GetConfigurationRequest struct { 46 ConfigID int64 47 } 48 49 // CreateConfigurationRequest holds parameters for CreateConfiguration 50 CreateConfigurationRequest struct { 51 Activate bool 52 Body CreateConfigurationBody 53 } 54 55 // CreateConfigurationBody holds request body parameters for CreateConfiguration 56 CreateConfigurationBody struct { 57 CapacityAlertsThreshold *int `json:"capacityAlertsThreshold,omitempty"` 58 Comments string `json:"comments"` 59 ContractID string `json:"contractId"` 60 Locations []ConfigLocationReq `json:"locations"` 61 MultiCDNSettings *MultiCDNSettings `json:"multiCdnSettings,omitempty"` 62 ConfigName string `json:"configName"` 63 NotificationEmails []string `json:"notificationEmails,omitempty"` 64 PropertyIDs []string `json:"propertyIds"` 65 RetainIdleObjects bool `json:"retainIdleObjects,omitempty"` 66 } 67 68 // UpdateConfigurationRequest holds parameters for UpdateConfiguration 69 UpdateConfigurationRequest struct { 70 ConfigID int64 71 Activate bool 72 Body UpdateConfigurationBody 73 } 74 75 // UpdateConfigurationBody holds request body parameters for UpdateConfiguration 76 UpdateConfigurationBody struct { 77 CapacityAlertsThreshold *int `json:"capacityAlertsThreshold,omitempty"` 78 Comments string `json:"comments"` 79 Locations []ConfigLocationReq `json:"locations"` 80 MultiCDNSettings *MultiCDNSettings `json:"multiCdnSettings,omitempty"` 81 NotificationEmails []string `json:"notificationEmails,omitempty"` 82 PropertyIDs []string `json:"propertyIds"` 83 RetainIdleObjects bool `json:"retainIdleObjects,omitempty"` 84 } 85 86 // DeleteConfigurationRequest holds parameters for DeleteConfiguration 87 DeleteConfigurationRequest struct { 88 ConfigID int64 89 } 90 91 // ActivateConfigurationRequest holds parameters for ActivateConfiguration 92 ActivateConfigurationRequest struct { 93 ConfigurationIDs []int `json:"configurationIds"` 94 } 95 96 // Configuration represents CloudWrapper configuration 97 Configuration struct { 98 CapacityAlertsThreshold *int `json:"capacityAlertsThreshold"` 99 Comments string `json:"comments"` 100 ContractID string `json:"contractId"` 101 ConfigID int64 `json:"configId"` 102 Locations []ConfigLocationResp `json:"locations"` 103 MultiCDNSettings *MultiCDNSettings `json:"multiCdnSettings"` 104 Status StatusType `json:"status"` 105 ConfigName string `json:"configName"` 106 LastUpdatedBy string `json:"lastUpdatedBy"` 107 LastUpdatedDate string `json:"lastUpdatedDate"` 108 LastActivatedBy *string `json:"lastActivatedBy"` 109 LastActivatedDate *string `json:"lastActivatedDate"` 110 NotificationEmails []string `json:"notificationEmails"` 111 PropertyIDs []string `json:"propertyIds"` 112 RetainIdleObjects bool `json:"retainIdleObjects"` 113 } 114 115 // ListConfigurationsResponse contains response from ListConfigurations 116 ListConfigurationsResponse struct { 117 Configurations []Configuration `json:"configurations"` 118 } 119 120 // ConfigLocationReq represents location to be configured for the configuration 121 ConfigLocationReq struct { 122 Comments string `json:"comments"` 123 TrafficTypeID int `json:"trafficTypeId"` 124 Capacity Capacity `json:"capacity"` 125 } 126 127 // ConfigLocationResp represents location to be configured for the configuration 128 ConfigLocationResp struct { 129 Comments string `json:"comments"` 130 TrafficTypeID int `json:"trafficTypeId"` 131 Capacity Capacity `json:"capacity"` 132 MapName string `json:"mapName"` 133 } 134 135 // MultiCDNSettings represents details about Multi CDN Settings 136 MultiCDNSettings struct { 137 BOCC *BOCC `json:"bocc"` 138 CDNs []CDN `json:"cdns"` 139 DataStreams *DataStreams `json:"dataStreams"` 140 EnableSoftAlerts bool `json:"enableSoftAlerts,omitempty"` 141 Origins []Origin `json:"origins"` 142 } 143 144 // BOCC represents diagnostic data beacon details 145 BOCC struct { 146 ConditionalSamplingFrequency SamplingFrequency `json:"conditionalSamplingFrequency,omitempty"` 147 Enabled bool `json:"enabled"` 148 ForwardType ForwardType `json:"forwardType,omitempty"` 149 RequestType RequestType `json:"requestType,omitempty"` 150 SamplingFrequency SamplingFrequency `json:"samplingFrequency,omitempty"` 151 } 152 153 // CDN represents a CDN added for the configuration 154 CDN struct { 155 CDNAuthKeys []CDNAuthKey `json:"cdnAuthKeys,omitempty"` 156 CDNCode string `json:"cdnCode"` 157 Enabled bool `json:"enabled"` 158 HTTPSOnly bool `json:"httpsOnly,omitempty"` 159 IPACLCIDRs []string `json:"ipAclCidrs,omitempty"` 160 } 161 162 // CDNAuthKey represents auth key configured for the CDN 163 CDNAuthKey struct { 164 AuthKeyName string `json:"authKeyName"` 165 ExpiryDate string `json:"expiryDate,omitempty"` 166 HeaderName string `json:"headerName,omitempty"` 167 Secret string `json:"secret,omitempty"` 168 } 169 170 // DataStreams represents data streams details 171 DataStreams struct { 172 DataStreamIDs []int64 `json:"dataStreamIds,omitempty"` 173 Enabled bool `json:"enabled"` 174 SamplingRate *int `json:"samplingRate,omitempty"` 175 } 176 177 // Origin represents origin corresponding to the properties selected in the configuration 178 Origin struct { 179 Hostname string `json:"hostname"` 180 OriginID string `json:"originId"` 181 PropertyID int `json:"propertyId"` 182 } 183 184 // SamplingFrequency is a type of sampling frequency. Either 'ZERO' or 'ONE_TENTH' 185 SamplingFrequency string 186 187 // ForwardType is a type of forward 188 ForwardType string 189 190 // RequestType is a type of request 191 RequestType string 192 193 // StatusType is a type of status 194 StatusType string 195 ) 196 197 const ( 198 // SamplingFrequencyZero represents SamplingFrequency value of 'ZERO' 199 SamplingFrequencyZero SamplingFrequency = "ZERO" 200 // SamplingFrequencyOneTenth represents SamplingFrequency value of 'ONE_TENTH' 201 SamplingFrequencyOneTenth SamplingFrequency = "ONE_TENTH" 202 // ForwardTypeOriginOnly represents ForwardType value of 'ORIGIN_ONLY' 203 ForwardTypeOriginOnly ForwardType = "ORIGIN_ONLY" 204 // ForwardTypeMidgressOnly represents ForwardType value of 'MIDGRESS_ONLY' 205 ForwardTypeMidgressOnly ForwardType = "MIDGRESS_ONLY" 206 // ForwardTypeOriginAndMidgress represents ForwardType value of 'ORIGIN_AND_MIDGRESS' 207 ForwardTypeOriginAndMidgress ForwardType = "ORIGIN_AND_MIDGRESS" 208 // RequestTypeEdgeOnly represents RequestType value of 'EDGE_ONLY' 209 RequestTypeEdgeOnly RequestType = "EDGE_ONLY" 210 // RequestTypeEdgeAndMidgress represents RequestType value of 'EDGE_AND_MIDGRESS' 211 RequestTypeEdgeAndMidgress RequestType = "EDGE_AND_MIDGRESS" 212 213 // StatusActive represents Status value of 'ACTIVE' 214 StatusActive StatusType = "ACTIVE" 215 // StatusSaved represents Status value of 'SAVED' 216 StatusSaved StatusType = "SAVED" 217 // StatusInProgress represents Status value of 'IN_PROGRESS' 218 StatusInProgress StatusType = "IN_PROGRESS" 219 // StatusDeleteInProgress represents Status value of 'DELETE_IN_PROGRESS' 220 StatusDeleteInProgress StatusType = "DELETE_IN_PROGRESS" 221 // StatusFailed represents Status value of 'FAILED' 222 StatusFailed StatusType = "FAILED" 223 ) 224 225 // Validate validates GetConfigurationRequest 226 func (r GetConfigurationRequest) Validate() error { 227 return edgegriderr.ParseValidationErrors(validation.Errors{ 228 "ConfigID": validation.Validate(r.ConfigID, validation.Required), 229 }) 230 } 231 232 // Validate validates CreateConfigurationRequest 233 func (r CreateConfigurationRequest) Validate() error { 234 return edgegriderr.ParseValidationErrors(validation.Errors{ 235 "Body": validation.Validate(r.Body, validation.Required), 236 }) 237 } 238 239 // Validate validates CreateConfigurationBody 240 func (b CreateConfigurationBody) Validate() error { 241 return validation.Errors{ 242 "Comments": validation.Validate(b.Comments, validation.Required), 243 "Locations": validation.Validate(b.Locations, validation.Required), 244 "ConfigName": validation.Validate(b.ConfigName, validation.Required), 245 "ContractID": validation.Validate(b.ContractID, validation.Required), 246 "PropertyIDs": validation.Validate(b.PropertyIDs, validation.Required), 247 "MultiCDNSettings": validation.Validate(b.MultiCDNSettings), 248 "CapacityAlertsThreshold": validation.Validate(b.CapacityAlertsThreshold, validation.Min(50), validation.Max(100).Error(fmt.Sprintf("value '%d' is invalid. Must be between 50 and 100", b.CapacityAlertsThreshold))), 249 }.Filter() 250 } 251 252 // Validate validates UpdateConfigurationRequest 253 func (r UpdateConfigurationRequest) Validate() error { 254 return edgegriderr.ParseValidationErrors(validation.Errors{ 255 "ConfigID": validation.Validate(r.ConfigID, validation.Required), 256 "Body": validation.Validate(r.Body, validation.Required), 257 }) 258 } 259 260 // Validate validates UpdateConfigurationBody 261 func (b UpdateConfigurationBody) Validate() error { 262 return validation.Errors{ 263 "Comments": validation.Validate(b.Comments, validation.Required), 264 "Locations": validation.Validate(b.Locations, validation.Required), 265 "PropertyIDs": validation.Validate(b.PropertyIDs, validation.Required), 266 "MultiCDNSettings": validation.Validate(b.MultiCDNSettings), 267 "CapacityAlertsThreshold": validation.Validate(b.CapacityAlertsThreshold, validation.Min(50), validation.Max(100).Error(fmt.Sprintf("value '%d' is invalid. Must be between 50 and 100", b.CapacityAlertsThreshold))), 268 }.Filter() 269 } 270 271 // Validate validates DeleteConfigurationRequest 272 func (r DeleteConfigurationRequest) Validate() error { 273 return edgegriderr.ParseValidationErrors(validation.Errors{ 274 "ConfigID": validation.Validate(r.ConfigID, validation.Required), 275 }) 276 } 277 278 // Validate validates ActivateConfigurationRequest 279 func (r ActivateConfigurationRequest) Validate() error { 280 return edgegriderr.ParseValidationErrors(validation.Errors{ 281 "ConfigurationIDs": validation.Validate(r.ConfigurationIDs, validation.Required), 282 }) 283 } 284 285 // Validate validates ConfigurationLocation 286 func (c ConfigLocationReq) Validate() error { 287 return validation.Errors{ 288 "Comments": validation.Validate(c.Comments, validation.Required), 289 "Capacity": validation.Validate(c.Capacity, validation.Required), 290 "TrafficTypeID": validation.Validate(c.TrafficTypeID, validation.Required), 291 }.Filter() 292 } 293 294 // Validate validates Capacity 295 func (c Capacity) Validate() error { 296 return validation.Errors{ 297 "Unit": validation.Validate(c.Unit, validation.Required, validation.In(UnitGB, UnitTB).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s'", c.Unit, UnitGB, UnitTB))), 298 "Value": validation.Validate(c.Value, validation.Required, validation.Min(1), validation.Max(int64(10000000000))), 299 }.Filter() 300 } 301 302 // Validate validates MultiCDNSettings 303 func (m MultiCDNSettings) Validate() error { 304 return validation.Errors{ 305 "BOCC": validation.Validate(m.BOCC, validation.Required), 306 "CDNs": validation.Validate(m.CDNs, validation.By(validateCDNs)), 307 "DataStreams": validation.Validate(m.DataStreams, validation.Required), 308 "Origins": validation.Validate(m.Origins, validation.Required), 309 }.Filter() 310 } 311 312 // Validate validates BOCC 313 func (b BOCC) Validate() error { 314 return validation.Errors{ 315 "Enabled": validation.Validate(b.Enabled, validation.NotNil), 316 "ConditionalSamplingFrequency": validation.Validate(b.ConditionalSamplingFrequency, validation.Required.When(b.Enabled), validation.In(SamplingFrequencyZero, SamplingFrequencyOneTenth).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s'", b.ConditionalSamplingFrequency, SamplingFrequencyZero, SamplingFrequencyOneTenth))), 317 "ForwardType": validation.Validate(b.ForwardType, validation.Required.When(b.Enabled), validation.In(ForwardTypeOriginOnly, ForwardTypeMidgressOnly, ForwardTypeOriginAndMidgress).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s', '%s'", b.ForwardType, ForwardTypeOriginOnly, ForwardTypeMidgressOnly, ForwardTypeOriginAndMidgress))), 318 "RequestType": validation.Validate(b.RequestType, validation.Required.When(b.Enabled), validation.In(RequestTypeEdgeOnly, RequestTypeEdgeAndMidgress).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s'", b.RequestType, RequestTypeEdgeOnly, RequestTypeEdgeAndMidgress))), 319 "SamplingFrequency": validation.Validate(b.SamplingFrequency, validation.Required.When(b.Enabled), validation.In(SamplingFrequencyZero, SamplingFrequencyOneTenth).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s'", b.RequestType, SamplingFrequencyZero, SamplingFrequencyOneTenth))), 320 }.Filter() 321 } 322 323 // Validate validates CDN 324 func (c CDN) Validate() error { 325 return validation.Errors{ 326 "CDNAuthKeys": validation.Validate(c.CDNAuthKeys), 327 "Enabled": validation.Validate(c.Enabled, validation.NotNil), 328 "CDNCode": validation.Validate(c.CDNCode, validation.Required), 329 }.Filter() 330 } 331 332 // Validate validates CDNAuthKey 333 func (c CDNAuthKey) Validate() error { 334 return validation.Errors{ 335 "AuthKeyName": validation.Validate(c.AuthKeyName, validation.Required), 336 "Secret": validation.Validate(c.Secret, validation.Length(24, 24)), 337 }.Filter() 338 } 339 340 // Validate validates DataStreams 341 func (d DataStreams) Validate() error { 342 return validation.Errors{ 343 "Enabled": validation.Validate(d.Enabled, validation.NotNil), 344 "SamplingRate": validation.Validate(d.SamplingRate, validation.When(d.SamplingRate != nil, validation.Min(1), validation.Max(100).Error(fmt.Sprintf("value '%d' is invalid. Must be between 1 and 100", d.SamplingRate)))), 345 }.Filter() 346 } 347 348 // Validate validates Origin 349 func (o Origin) Validate() error { 350 return validation.Errors{ 351 "PropertyID": validation.Validate(o.PropertyID, validation.Required), 352 "Hostname": validation.Validate(o.Hostname, validation.Required), 353 "OriginID": validation.Validate(o.OriginID, validation.Required), 354 }.Filter() 355 } 356 357 // validateCDNs validates CDNs by checking if at least one is enabled and one of authKeys or IP ACLs is specified 358 func validateCDNs(value interface{}) error { 359 v, ok := value.([]CDN) 360 if !ok { 361 return fmt.Errorf("type %T is invalid. Must be []CDN", value) 362 } 363 if v == nil { 364 return fmt.Errorf("cannot be blank") 365 } 366 var isEnabled bool 367 for _, cdn := range v { 368 if cdn.Enabled { 369 isEnabled = true 370 } 371 if cdn.CDNAuthKeys == nil && cdn.IPACLCIDRs == nil { 372 return fmt.Errorf("at least one authentication method is required for CDN. Either IP ACL or header authentication must be enabled") 373 } 374 } 375 if !isEnabled { 376 return fmt.Errorf("at least one of CDNs must be enabled") 377 } 378 379 return nil 380 } 381 382 var ( 383 // ErrGetConfiguration is returned when GetConfiguration fails 384 ErrGetConfiguration = errors.New("get configuration") 385 // ErrListConfigurations is returned when ListConfigurations fails 386 ErrListConfigurations = errors.New("list configurations") 387 // ErrCreateConfiguration is returned when CreateConfiguration fails 388 ErrCreateConfiguration = errors.New("create configuration") 389 // ErrUpdateConfiguration is returned when UpdateConfiguration fails 390 ErrUpdateConfiguration = errors.New("update configuration") 391 // ErrDeleteConfiguration is returned when DeleteConfiguration fails 392 ErrDeleteConfiguration = errors.New("delete configuration") 393 // ErrActivateConfiguration is returned when ActivateConfiguration fails 394 ErrActivateConfiguration = errors.New("activate configuration") 395 ) 396 397 func (c *cloudwrapper) GetConfiguration(ctx context.Context, params GetConfigurationRequest) (*Configuration, error) { 398 logger := c.Log(ctx) 399 logger.Debug("GetConfiguration") 400 401 if err := params.Validate(); err != nil { 402 return nil, fmt.Errorf("%s: %w: %s", ErrGetConfiguration, ErrStructValidation, err) 403 } 404 405 uri := fmt.Sprintf("/cloud-wrapper/v1/configurations/%d", params.ConfigID) 406 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 407 if err != nil { 408 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetConfiguration, err) 409 } 410 411 var result Configuration 412 resp, err := c.Exec(req, &result) 413 if err != nil { 414 return nil, fmt.Errorf("%w: request failed: %s", ErrGetConfiguration, err) 415 } 416 417 if resp.StatusCode != http.StatusOK { 418 return nil, fmt.Errorf("%s: %w", ErrGetConfiguration, c.Error(resp)) 419 } 420 421 return &result, nil 422 } 423 424 func (c *cloudwrapper) ListConfigurations(ctx context.Context) (*ListConfigurationsResponse, error) { 425 logger := c.Log(ctx) 426 logger.Debug("ListConfigurations") 427 428 uri := "/cloud-wrapper/v1/configurations" 429 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) 430 if err != nil { 431 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListConfigurations, err) 432 } 433 434 var result ListConfigurationsResponse 435 resp, err := c.Exec(req, &result) 436 if err != nil { 437 return nil, fmt.Errorf("%w: request failed: %s", ErrListConfigurations, err) 438 } 439 440 if resp.StatusCode != http.StatusOK { 441 return nil, fmt.Errorf("%s: %w", ErrListConfigurations, c.Error(resp)) 442 } 443 444 return &result, nil 445 } 446 447 func (c *cloudwrapper) CreateConfiguration(ctx context.Context, params CreateConfigurationRequest) (*Configuration, error) { 448 logger := c.Log(ctx) 449 logger.Debug("CreateConfiguration") 450 451 if err := params.Validate(); err != nil { 452 return nil, fmt.Errorf("%s: %w: %s", ErrCreateConfiguration, ErrStructValidation, err) 453 } 454 455 uri, err := url.Parse("/cloud-wrapper/v1/configurations") 456 if err != nil { 457 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrCreateConfiguration, err) 458 } 459 460 q := uri.Query() 461 q.Add("activate", strconv.FormatBool(params.Activate)) 462 uri.RawQuery = q.Encode() 463 464 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri.String(), nil) 465 if err != nil { 466 return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateConfiguration, err) 467 } 468 469 var result Configuration 470 resp, err := c.Exec(req, &result, params.Body) 471 if err != nil { 472 return nil, fmt.Errorf("%w: request failed: %s", ErrCreateConfiguration, err) 473 } 474 475 if resp.StatusCode != http.StatusCreated { 476 return nil, fmt.Errorf("%s: %w", ErrCreateConfiguration, c.Error(resp)) 477 } 478 479 return &result, nil 480 } 481 482 func (c *cloudwrapper) UpdateConfiguration(ctx context.Context, params UpdateConfigurationRequest) (*Configuration, error) { 483 logger := c.Log(ctx) 484 logger.Debug("UpdateConfiguration") 485 486 if err := params.Validate(); err != nil { 487 return nil, fmt.Errorf("%s: %w: %s", ErrUpdateConfiguration, ErrStructValidation, err) 488 } 489 490 uri, err := url.Parse(fmt.Sprintf("/cloud-wrapper/v1/configurations/%d", params.ConfigID)) 491 if err != nil { 492 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrUpdateConfiguration, err) 493 } 494 495 q := uri.Query() 496 q.Add("activate", strconv.FormatBool(params.Activate)) 497 uri.RawQuery = q.Encode() 498 499 req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri.String(), nil) 500 if err != nil { 501 return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateConfiguration, err) 502 } 503 504 var result Configuration 505 resp, err := c.Exec(req, &result, params.Body) 506 if err != nil { 507 return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateConfiguration, err) 508 } 509 510 if resp.StatusCode != http.StatusOK { 511 return nil, fmt.Errorf("%s: %w", ErrUpdateConfiguration, c.Error(resp)) 512 } 513 514 return &result, nil 515 } 516 517 func (c *cloudwrapper) DeleteConfiguration(ctx context.Context, params DeleteConfigurationRequest) error { 518 logger := c.Log(ctx) 519 logger.Debug("DeleteConfiguration") 520 521 if err := params.Validate(); err != nil { 522 return fmt.Errorf("%s: %w: %s", ErrDeleteConfiguration, ErrStructValidation, err) 523 } 524 525 uri := fmt.Sprintf("/cloud-wrapper/v1/configurations/%d", params.ConfigID) 526 527 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil) 528 if err != nil { 529 return fmt.Errorf("%w: failed to create request: %s", ErrDeleteConfiguration, err) 530 } 531 532 resp, err := c.Exec(req, nil) 533 if err != nil { 534 return fmt.Errorf("%w: request failed: %s", ErrDeleteConfiguration, err) 535 } 536 537 if resp.StatusCode != http.StatusAccepted { 538 return fmt.Errorf("%s: %w", ErrDeleteConfiguration, c.Error(resp)) 539 } 540 541 return nil 542 } 543 544 func (c *cloudwrapper) ActivateConfiguration(ctx context.Context, params ActivateConfigurationRequest) error { 545 logger := c.Log(ctx) 546 logger.Debug("ActivateConfiguration") 547 548 if err := params.Validate(); err != nil { 549 return fmt.Errorf("%s: %w: %s", ErrActivateConfiguration, ErrStructValidation, err) 550 } 551 552 uri := "/cloud-wrapper/v1/configurations/activate" 553 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil) 554 if err != nil { 555 return fmt.Errorf("%w: failed to create request: %s", ErrActivateConfiguration, err) 556 } 557 558 resp, err := c.Exec(req, nil, params) 559 if err != nil { 560 return fmt.Errorf("%w: request failed: %s", ErrActivateConfiguration, err) 561 } 562 563 if resp.StatusCode != http.StatusNoContent { 564 return fmt.Errorf("%s: %w", ErrActivateConfiguration, c.Error(resp)) 565 } 566 567 return nil 568 }