Skip to content

Commit

Permalink
Feat/scheduled autoscale (#54)
Browse files Browse the repository at this point in the history
* feat: scheduled autoscale

* test: scheduled autoscale

* refactor: review suggestions
  • Loading branch information
crgisch authored Dec 20, 2023
1 parent ada92ae commit 7d1ec8f
Show file tree
Hide file tree
Showing 4 changed files with 399 additions and 10 deletions.
31 changes: 30 additions & 1 deletion docs/resources/app_autoscale.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ resource "tsuru_app_autoscale" "web" {
min_units = 3
max_units = 10
cpu_average = "60%"
schedule {
min_replicas = 5
start = "0 18 * * *"
end = "0 0 * * *"
timezone = "America/Sao_Paulo"
}
schedule {
min_replicas = 10
start = "0 18 * * *"
end = "0 19 * * *"
timezone = "UTC"
}
}
```

Expand All @@ -28,19 +42,34 @@ resource "tsuru_app_autoscale" "web" {
### Required

- `app` (String) Application name
- `cpu_average` (String) CPU average, for example: 20%, mean that we trigger autoscale when the average of CPU Usage of units is 20%.
- `max_units` (Number) maximum number of units
- `process` (String) Application process

### Optional

- `cpu_average` (String) CPU average, for example: 20%, mean that we trigger autoscale when the average of CPU Usage of units is 20%.
- `min_units` (Number) minimum number of units
- `schedule` (Block List) List of schedules that determine scheduled up/downscales (see [below for nested schema](#nestedblock--schedule))
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--schedule"></a>
### Nested Schema for `schedule`

Required:

- `end` (String)
- `min_replicas` (Number)
- `start` (String)

Optional:

- `timezone` (String)


<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Expand Down
14 changes: 14 additions & 0 deletions examples/resources/tsuru_app_autoscale/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,18 @@ resource "tsuru_app_autoscale" "web" {
min_units = 3
max_units = 10
cpu_average = "60%"

schedule {
min_replicas = 5
start = "0 18 * * *"
end = "0 0 * * *"
timezone = "America/Sao_Paulo"
}

schedule {
min_replicas = 10
start = "0 18 * * *"
end = "0 19 * * *"
timezone = "UTC"
}
}
108 changes: 99 additions & 9 deletions internal/provider/resource_tsuru_app_autoscale.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,36 @@ func resourceTsuruApplicationAutoscale() *schema.Resource {
Required: true,
},
"cpu_average": {
Type: schema.TypeString,
Description: "CPU average, for example: 20%, mean that we trigger autoscale when the average of CPU Usage of units is 20%.",
Required: true,
Type: schema.TypeString,
Description: "CPU average, for example: 20%, mean that we trigger autoscale when the average of CPU Usage of units is 20%.",
Optional: true,
AtLeastOneOf: []string{"cpu_average", "schedule"},
},
"schedule": {
Type: schema.TypeList,
Description: "List of schedules that determine scheduled up/downscales",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"min_replicas": {
Type: schema.TypeInt,
Required: true,
},
"start": {
Type: schema.TypeString,
Required: true,
},
"end": {
Type: schema.TypeString,
Required: true,
},
"timezone": {
Type: schema.TypeString,
Optional: true,
},
},
},
Optional: true,
AtLeastOneOf: []string{"cpu_average", "schedule"},
},
},
}
Expand Down Expand Up @@ -100,13 +127,22 @@ func resourceTsuruApplicationAutoscaleSet(ctx context.Context, d *schema.Resourc
if minUnits > maxUnits {
minUnits = maxUnits
}
cpu := d.Get("cpu_average").(string)

autoscale := tsuru_client.AutoScaleSpec{
Process: process,
MinUnits: int32(minUnits),
MaxUnits: int32(maxUnits),
AverageCPU: cpu,
Process: process,
MinUnits: int32(minUnits),
MaxUnits: int32(maxUnits),
}

if cpu, ok := d.GetOk("cpu_average"); ok {
autoscale.AverageCPU = cpu.(string)
}

if m, ok := d.GetOk("schedule"); ok {
schedules := schedulesFromResourceData(m)
if schedules != nil {
autoscale.Schedules = schedules
}
}

err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
Expand Down Expand Up @@ -170,9 +206,12 @@ func resourceTsuruApplicationAutoscaleRead(ctx context.Context, d *schema.Resour
d.Set("cpu_average", autoscale.AverageCPU)
} else if strings.HasSuffix(autoscale.AverageCPU, "m") {
d.Set("cpu_average", milliToPercentage(autoscale.AverageCPU))
} else {
} else if currentCPUAverage != "" {
d.Set("cpu_average", autoscale.AverageCPU)
}

d.Set("schedule", flattenSchedules(autoscale.Schedules))

return nil
}

Expand Down Expand Up @@ -240,3 +279,54 @@ func milliToPercentage(milli string) string {

return fmt.Sprintf("%.2g", milliInt/10)
}

func schedulesFromResourceData(meta interface{}) []tsuru_client.AutoScaleSchedule {
scheduleMeta := meta.([]interface{})

if len(scheduleMeta) == 0 {
return nil
}

schedules := []tsuru_client.AutoScaleSchedule{}

for _, iface := range scheduleMeta {
schedule := tsuru_client.AutoScaleSchedule{}
sm := iface.(map[string]interface{})

if v, ok := sm["min_replicas"]; ok {
minReplicas := v.(int)
schedule.MinReplicas = int32(minReplicas)
}

if v, ok := sm["start"]; ok {
schedule.Start = v.(string)
}

if v, ok := sm["end"]; ok {
schedule.End = v.(string)
}

if v, ok := sm["timezone"]; ok {
schedule.Timezone = v.(string)
}

schedules = append(schedules, schedule)
}

return schedules
}

func flattenSchedules(schedules []tsuru_client.AutoScaleSchedule) []interface{} {
result := []interface{}{}

for _, schedule := range schedules {
result = append(result, map[string]interface{}{
"min_replicas": schedule.MinReplicas,
"start": schedule.Start,
"end": schedule.End,
"timezone": schedule.Timezone,
})
}

return result
}
Loading

0 comments on commit 7d1ec8f

Please sign in to comment.