diff --git a/aptible/resource_app.go b/aptible/resource_app.go index 02e86c6..a273dbc 100644 --- a/aptible/resource_app.go +++ b/aptible/resource_app.go @@ -97,6 +97,12 @@ func resourceService() *schema.Resource { Default: false, }, "service_sizing_policy": { + Type: schema.TypeSet, + Optional: true, + Elem: resourceServiceSizingPolicy(), + Deprecated: "Please use autoscaling_policy instead. This attribute will be removed in version 1.0", + }, + "autoscaling_policy": { Type: schema.TypeSet, Optional: true, Elem: resourceServiceSizingPolicy(), @@ -220,8 +226,24 @@ func validateServiceSizingPolicy(ctx context.Context, d *schema.ResourceDiff, _ services := d.Get("service").(*schema.Set).List() for _, service := range services { serviceMap := service.(map[string]interface{}) - if policy, ok := serviceMap["service_sizing_policy"]; ok { - policies := policy.(*schema.Set).List() // should only be one, but yes it's a Set + + oldPolicies := serviceMap["service_sizing_policy"].(*schema.Set).List() + newPolicies := serviceMap["autoscaling_policy"].(*schema.Set).List() + var policies []interface{} + ok := false + if len(newPolicies) > 0 { + policies = newPolicies + ok = true + } else if len(oldPolicies) > 0 { + policies = oldPolicies + ok = true + } + + if len(newPolicies) > 0 && len(oldPolicies) > 0 { + return fmt.Errorf("only one of autoscaling_policy or service_sizing_policy may be defined by service. Please note service_sizing_policy is deprecated in favor of autoscaling_policy") + } + + if ok { if len(policies) == 1 && policies[0] != nil { policyMap := policies[0].(map[string]interface{}) autoscalingType := policyMap["autoscaling_type"].(string) @@ -258,7 +280,7 @@ func validateServiceSizingPolicy(ctx context.Context, d *schema.ResourceDiff, _ } } } else if len(policies) > 0 { - return fmt.Errorf("only one service_sizing_policy is allowed per service") + return fmt.Errorf("only one autoscaling_policy is allowed per service") } } } @@ -392,7 +414,7 @@ func resourceAppRead(d *schema.ResourceData, meta interface{}) error { serviceSizingPolicy["scale_up_step"] = policy.GetScaleUpStep() serviceSizingPolicy["scale_down_step"] = policy.GetScaleDownStep() - service["service_sizing_policy"] = []map[string]interface{}{serviceSizingPolicy} + service["autoscaling_policy"] = []map[string]interface{}{serviceSizingPolicy} } services[i] = service @@ -462,7 +484,7 @@ func resourceAppUpdate(c context.Context, d *schema.ResourceData, meta interface if err != nil { diags = append(diags, diag.Diagnostic{ Severity: diag.Error, - Summary: "There was an error when trying to update service_sizing_policy.", + Summary: "There was an error when trying to update autoscaling_policy.", Detail: err.Error(), }) return diags @@ -638,7 +660,7 @@ func scaleServices(d *schema.ResourceData, meta interface{}) error { // Check if there are changes to other keys, ignoring `force_zero_downtime` and `simple_health_check` hasOtherChanges := false for key, newValue := range serviceData { - if key == "force_zero_downtime" || key == "simple_health_check" || key == "service_sizing_policy" { + if key == "force_zero_downtime" || key == "simple_health_check" || key == "autoscaling_policy" || key == "service_sizing_policy" { continue // Skip checking these keys. Nothing to do with manual scaling } @@ -729,10 +751,21 @@ func updateServiceSizingPolicy(ctx context.Context, d *schema.ResourceData, meta services := d.Get("service").(*schema.Set).List() for _, serviceData := range services { serviceMap := serviceData.(map[string]interface{}) - policies := serviceMap["service_sizing_policy"].(*schema.Set).List() serviceName := serviceMap["process_type"].(string) - if len(policies) > 0 { + oldPolicies := serviceMap["service_sizing_policy"].(*schema.Set).List() + newPolicies := serviceMap["autoscaling_policy"].(*schema.Set).List() + var policies []interface{} + ok := false + if len(newPolicies) > 0 { + policies = newPolicies + ok = true + } else if len(oldPolicies) > 0 { + policies = oldPolicies + ok = true + } + + if ok { // There's only ever one policy, but we have to model this as a list serviceSizingPolicyMap := policies[0].(map[string]interface{}) @@ -786,7 +819,7 @@ func updateServiceSizingPolicy(ctx context.Context, d *schema.ResourceData, meta _, err = client.ServiceSizingPoliciesAPI.CreateServiceSizingPolicy(ctx, serviceId).CreateServiceSizingPolicyRequest(*payload).Execute() } if err != nil { - return fmt.Errorf("failed to create sizing policy for service %s: %w", serviceName, err) + return fmt.Errorf("failed to create autoscaling policy for service %s: %w", serviceName, err) } } else if update { serviceId, err := findServiceIdForAppByName(ctx, meta, appID, serviceName) @@ -803,7 +836,7 @@ func updateServiceSizingPolicy(ctx context.Context, d *schema.ResourceData, meta // Now delete _, err = client.ServiceSizingPoliciesAPI.DeleteServiceSizingPolicy(ctx, serviceId).Execute() if err != nil { - return fmt.Errorf("failed to delete sizing policy for service %s: %w", serviceName, err) + return fmt.Errorf("failed to delete autoscaling policy for service %s: %w", serviceName, err) } } } diff --git a/aptible/resource_app_test.go b/aptible/resource_app_test.go index edddb11..563d1ac 100644 --- a/aptible/resource_app_test.go +++ b/aptible/resource_app_test.go @@ -190,7 +190,7 @@ func TestAccResourceApp_scaleDown(t *testing.T) { }) } -func TestAccResourceApp_serviceSizingPolicy(t *testing.T) { +func TestAccResourceApp_autoscalingPolicy(t *testing.T) { rHandle := acctest.RandString(10) WithTestAccEnvironment(t, func(env aptible.Environment) { @@ -200,10 +200,10 @@ func TestAccResourceApp_serviceSizingPolicy(t *testing.T) { CheckDestroy: testAccCheckAppDestroy, Steps: []resource.TestStep{ { - Config: testAccAptibleAppServiceSizingPolicy(rHandle), + Config: testAccAptibleAppautoscalingPolicy(rHandle), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.autoscaling_type", "horizontal"), - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.min_containers", "2"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.autoscaling_type", "horizontal"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.min_containers", "2"), ), }, { @@ -216,7 +216,7 @@ func TestAccResourceApp_serviceSizingPolicy(t *testing.T) { }) } -func TestAccResourceApp_updateServiceSizingPolicy(t *testing.T) { +func TestAccResourceApp_updateautoscalingPolicy(t *testing.T) { rHandle := acctest.RandString(10) WithTestAccEnvironment(t, func(env aptible.Environment) { @@ -226,10 +226,10 @@ func TestAccResourceApp_updateServiceSizingPolicy(t *testing.T) { CheckDestroy: testAccCheckAppDestroy, Steps: []resource.TestStep{ { - Config: testAccAptibleAppServiceSizingPolicy(rHandle), + Config: testAccAptibleAppautoscalingPolicy(rHandle), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.autoscaling_type", "horizontal"), - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.min_containers", "2"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.autoscaling_type", "horizontal"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.min_containers", "2"), ), }, { @@ -238,10 +238,10 @@ func TestAccResourceApp_updateServiceSizingPolicy(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAptibleAppUpdateServiceSizingPolicy(rHandle), + Config: testAccAptibleAppUpdateautoscalingPolicy(rHandle), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.autoscaling_type", "vertical"), - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.mem_scale_down_threshold", "0.6"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.autoscaling_type", "vertical"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.mem_scale_down_threshold", "0.6"), ), }, }, @@ -249,7 +249,7 @@ func TestAccResourceApp_updateServiceSizingPolicy(t *testing.T) { }) } -func TestAccResourceApp_removeServiceSizingPolicy(t *testing.T) { +func TestAccResourceApp_removeautoscalingPolicy(t *testing.T) { rHandle := acctest.RandString(10) WithTestAccEnvironment(t, func(env aptible.Environment) { @@ -259,10 +259,10 @@ func TestAccResourceApp_removeServiceSizingPolicy(t *testing.T) { CheckDestroy: testAccCheckAppDestroy, Steps: []resource.TestStep{ { - Config: testAccAptibleAppServiceSizingPolicy(rHandle), + Config: testAccAptibleAppautoscalingPolicy(rHandle), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.autoscaling_type", "horizontal"), - resource.TestCheckResourceAttr("aptible_app.test", "service.0.service_sizing_policy.0.min_containers", "2"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.autoscaling_type", "horizontal"), + resource.TestCheckResourceAttr("aptible_app.test", "service.0.autoscaling_policy.0.min_containers", "2"), ), }, { @@ -271,10 +271,10 @@ func TestAccResourceApp_removeServiceSizingPolicy(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAptibleAppWithoutServiceSizingPolicy(rHandle), + Config: testAccAptibleAppWithoutautoscalingPolicy(rHandle), Check: resource.ComposeTestCheckFunc( - // Ensure the service_sizing_policy block is no longer present - resource.TestCheckNoResourceAttr("aptible_app.test", "service.0.service_sizing_policy"), + // Ensure the autoscaling_policy block is no longer present + resource.TestCheckNoResourceAttr("aptible_app.test", "service.0.autoscaling_policy"), ), }, }, @@ -300,6 +300,24 @@ func TestAccResourceApp_autoscalingTypeHorizontalMissingAttributes(t *testing.T) }) } +func TestAccResourceApp_autoscalingOldAndNewAttributeUsage(t *testing.T) { + rHandle := acctest.RandString(10) + + WithTestAccEnvironment(t, func(env aptible.Environment) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAptibleAppDeployAutoscalingOldAndNewPolicyAttribute(rHandle), + ExpectError: regexp.MustCompile(`only one of autoscaling_policy or service_sizing_policy may be defined by service`), + }, + }, + }) + }) +} + func TestAccResourceApp_autoscalingTypeVerticalInvalidAttributes(t *testing.T) { rHandle := acctest.RandString(10) @@ -329,7 +347,7 @@ func TestAccResourceApp_moreThanOnePolicy(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAptibleAppDeployOnlyOnePolicy(rHandle), - ExpectError: regexp.MustCompile(`only one service_sizing_policy is allowed per service`), + ExpectError: regexp.MustCompile(`only one autoscaling_policy is allowed per service`), }, }, }) @@ -504,7 +522,7 @@ func testAccAptibleAppScaleDown(handle string) string { `, handle, testOrganizationId, testStackId, handle) } -func testAccAptibleAppServiceSizingPolicy(handle string) string { +func testAccAptibleAppautoscalingPolicy(handle string) string { return fmt.Sprintf(` resource "aptible_environment" "test" { handle = "%s" @@ -523,7 +541,7 @@ func testAccAptibleAppServiceSizingPolicy(handle string) string { process_type = "cmd" container_profile = "m5" container_count = 1 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "horizontal" min_containers = 2 max_containers = 4 @@ -535,7 +553,7 @@ func testAccAptibleAppServiceSizingPolicy(handle string) string { `, handle, testOrganizationId, testStackId, handle) } -func testAccAptibleAppWithoutServiceSizingPolicy(handle string) string { +func testAccAptibleAppWithoutautoscalingPolicy(handle string) string { return fmt.Sprintf(` resource "aptible_environment" "test" { handle = "%s" @@ -559,7 +577,7 @@ func testAccAptibleAppWithoutServiceSizingPolicy(handle string) string { `, handle, testOrganizationId, testStackId, handle) } -func testAccAptibleAppUpdateServiceSizingPolicy(handle string) string { +func testAccAptibleAppUpdateautoscalingPolicy(handle string) string { return fmt.Sprintf(` resource "aptible_environment" "test" { handle = "%s" @@ -579,7 +597,7 @@ func testAccAptibleAppUpdateServiceSizingPolicy(handle string) string { container_profile = "m5" container_memory_limit = 512 container_count = 1 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "vertical" mem_scale_down_threshold = 0.6 } @@ -607,7 +625,7 @@ func testAccAptibleAppDeployAutoscalingTypeHorizontalMissingAttributes(handle st process_type = "cmd" container_memory_limit = 1024 container_count = 1 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "horizontal" } } @@ -615,6 +633,39 @@ func testAccAptibleAppDeployAutoscalingTypeHorizontalMissingAttributes(handle st `, handle, testOrganizationId, testStackId, handle) } +func testAccAptibleAppDeployAutoscalingOldAndNewPolicyAttribute(handle string) string { + return fmt.Sprintf(` + resource "aptible_environment" "test" { + handle = "%s" + org_id = "%s" + stack_id = "%v" + } + + resource "aptible_app" "test" { + env_id = aptible_environment.test.env_id + handle = "%v" + config = { + "APTIBLE_DOCKER_IMAGE" = "nginx" + "WHATEVER" = "nothing" + } + service { + process_type = "cmd" + container_profile = "m5" + container_memory_limit = 512 + container_count = 1 + autoscaling_policy { + autoscaling_type = "vertical" + mem_scale_down_threshold = 0.6 + } + service_sizing_policy { + autoscaling_type = "vertical" + mem_scale_down_threshold = 0.6 + } + } + } + `, handle, testOrganizationId, testStackId, handle) +} + func testAccAptibleAppDeployAutoscalingTypeVerticalInvalidAttributes(handle string) string { return fmt.Sprintf(` resource "aptible_environment" "test" { @@ -634,7 +685,7 @@ func testAccAptibleAppDeployAutoscalingTypeVerticalInvalidAttributes(handle stri process_type = "cmd" container_memory_limit = 512 container_count = 1 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "vertical" min_containers = 1 } @@ -662,10 +713,10 @@ func testAccAptibleAppDeployOnlyOnePolicy(handle string) string { process_type = "cmd" container_memory_limit = 512 container_count = 1 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "vertical" } - service_sizing_policy { + autoscaling_policy { autoscaling_type = "horizontal" min_containers = 2 max_containers = 4 @@ -696,7 +747,7 @@ func testAccAptibleAppDeployInvalidAutoscalingType(handle string) string { process_type = "cmd" container_memory_limit = 512 container_count = 1 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "invalid" } } diff --git a/docs/index.md b/docs/index.md index 93a903f..49e6ce1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -155,7 +155,7 @@ resource "aptible_app" "APP" { process_type = "SERVICE_NAME1" container_count = 1 container_memory_limit = 1024 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "horizontal" min_containers = 2 max_container = 5 @@ -167,7 +167,7 @@ resource "aptible_app" "APP" { process_type = "SERVICE_NAME2" container_count = 2 container_memory_limit = 2048 - service_sizing_policy { + autoscaling_policy { autoscaling_type = "vertical" mem_scale_up_threshold = 0.8 } diff --git a/docs/resources/app.md b/docs/resources/app.md index b5bb606..a133b5c 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -37,7 +37,7 @@ resource "aptible_app" "APP" { container_count = 2 container_memory_limit = 2048 force_zero_downtime = true - service_sizing_policy { + autoscaling_policy { autoscaling_type = "horizontal" min_containers = 2 max_container = 5 @@ -80,10 +80,12 @@ The `service` block supports: [For more information please see the docs](https://www.aptible.com/docs/core-concepts/apps/deploying-apps/releases/overview). - `simple_health_check` - (Default: false) For services without endpoints, if force_zero_downtime is enabled, do a simple uptime check instead of using docker healthchecks. -- `service_sizing_policy` - (Optional) A block to manage autoscaling for services. See +- `service_sizing_policy` - **Deprecated** (Optional) A block to manage autoscaling for services. See + the main provider docs for additional details. +- `autoscaling_policy` - (Optional) A block to manage autoscaling for services. See the main provider docs for additional details. -The `service_sizing_policy` block supports: +The `autoscaling_policy` block supports: - `autoscaling_type` - The type of autoscaling. Must be either `horizontal` or `vertical`. - `metric_lookback_seconds` - (Default: 1800) The duration in seconds for