Skip to content

Commit 9370443

Browse files
feat: add autoscaling configuration for prebuilds
1 parent cfa101d commit 9370443

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed

provider/workspace_preset.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,23 @@ type WorkspacePrebuild struct {
2929
// for utilities that parse our terraform output using this type. To remain compatible
3030
// with those cases, we use a slice here.
3131
ExpirationPolicy []ExpirationPolicy `mapstructure:"expiration_policy"`
32+
Autoscaling []Autoscaling `json:"autoscaling,omitempty"`
3233
}
3334

3435
type ExpirationPolicy struct {
3536
TTL int `mapstructure:"ttl"`
3637
}
3738

39+
type Autoscaling struct {
40+
Timezone string `json:"timezone"`
41+
Schedule []Schedule `json:"schedule"`
42+
}
43+
44+
type Schedule struct {
45+
Cron string `json:"cron"`
46+
Instances int `json:"instances"`
47+
}
48+
3849
func workspacePresetDataSource() *schema.Resource {
3950
return &schema.Resource{
4051
SchemaVersion: 1,
@@ -119,6 +130,36 @@ func workspacePresetDataSource() *schema.Resource {
119130
},
120131
},
121132
},
133+
"autoscaling": {
134+
Type: schema.TypeList,
135+
Optional: true,
136+
MaxItems: 1,
137+
Elem: &schema.Resource{
138+
Schema: map[string]*schema.Schema{
139+
"timezone": {
140+
Type: schema.TypeString,
141+
Required: true,
142+
},
143+
"schedule": {
144+
Type: schema.TypeList,
145+
Required: true,
146+
MinItems: 1,
147+
Elem: &schema.Resource{
148+
Schema: map[string]*schema.Schema{
149+
"cron": {
150+
Type: schema.TypeString,
151+
Required: true,
152+
},
153+
"instances": {
154+
Type: schema.TypeInt,
155+
Required: true,
156+
},
157+
},
158+
},
159+
},
160+
},
161+
},
162+
},
122163
},
123164
},
124165
},

provider/workspace_preset_test.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,167 @@ func TestWorkspacePreset(t *testing.T) {
265265
}`,
266266
ExpectError: regexp.MustCompile("An argument named \"invalid_argument\" is not expected here."),
267267
},
268+
{
269+
Name: "Prebuilds is set with an empty autoscaling field",
270+
Config: `
271+
data "coder_workspace_preset" "preset_1" {
272+
name = "preset_1"
273+
prebuilds {
274+
instances = 1
275+
autoscaling {}
276+
}
277+
}`,
278+
ExpectError: regexp.MustCompile(`The argument "[^"]+" is required, but no definition was found.`),
279+
},
280+
{
281+
Name: "Prebuilds is set with an autoscaling field, but without timezone",
282+
Config: `
283+
data "coder_workspace_preset" "preset_1" {
284+
name = "preset_1"
285+
prebuilds {
286+
instances = 1
287+
autoscaling {
288+
schedule {
289+
cron = "* 8-18 * * 1-5"
290+
instances = 3
291+
}
292+
}
293+
}
294+
}`,
295+
ExpectError: regexp.MustCompile(`The argument "timezone" is required, but no definition was found.`),
296+
},
297+
{
298+
Name: "Prebuilds is set with an autoscaling field, but without schedule",
299+
Config: `
300+
data "coder_workspace_preset" "preset_1" {
301+
name = "preset_1"
302+
prebuilds {
303+
instances = 1
304+
autoscaling {
305+
timezone = "UTC"
306+
}
307+
}
308+
}`,
309+
ExpectError: regexp.MustCompile(`At least 1 "schedule" blocks are required.`),
310+
},
311+
{
312+
Name: "Prebuilds is set with an autoscaling.schedule field, but without cron",
313+
Config: `
314+
data "coder_workspace_preset" "preset_1" {
315+
name = "preset_1"
316+
prebuilds {
317+
instances = 1
318+
autoscaling {
319+
timezone = "UTC"
320+
schedule {
321+
instances = 3
322+
}
323+
}
324+
}
325+
}`,
326+
ExpectError: regexp.MustCompile(`The argument "cron" is required, but no definition was found.`),
327+
},
328+
{
329+
Name: "Prebuilds is set with an autoscaling.schedule field, but without cron",
330+
Config: `
331+
data "coder_workspace_preset" "preset_1" {
332+
name = "preset_1"
333+
prebuilds {
334+
instances = 1
335+
autoscaling {
336+
timezone = "UTC"
337+
schedule {
338+
cron = "* 8-18 * * 1-5"
339+
}
340+
}
341+
}
342+
}`,
343+
ExpectError: regexp.MustCompile(`The argument "instances" is required, but no definition was found.`),
344+
},
345+
{
346+
Name: "Prebuilds is set with an autoscaling.schedule field, but with invalid type for instances",
347+
Config: `
348+
data "coder_workspace_preset" "preset_1" {
349+
name = "preset_1"
350+
prebuilds {
351+
instances = 1
352+
autoscaling {
353+
timezone = "UTC"
354+
schedule {
355+
cron = "* 8-18 * * 1-5"
356+
instances = "not_a_number"
357+
}
358+
}
359+
}
360+
}`,
361+
ExpectError: regexp.MustCompile(`Inappropriate value for attribute "instances": a number is required`),
362+
},
363+
{
364+
Name: "Prebuilds is set with an autoscaling field with 1 schedule",
365+
Config: `
366+
data "coder_workspace_preset" "preset_1" {
367+
name = "preset_1"
368+
prebuilds {
369+
instances = 1
370+
autoscaling {
371+
timezone = "UTC"
372+
schedule {
373+
cron = "* 8-18 * * 1-5"
374+
instances = 3
375+
}
376+
}
377+
}
378+
}`,
379+
ExpectError: nil,
380+
Check: func(state *terraform.State) error {
381+
require.Len(t, state.Modules, 1)
382+
require.Len(t, state.Modules[0].Resources, 1)
383+
resource := state.Modules[0].Resources["data.coder_workspace_preset.preset_1"]
384+
require.NotNil(t, resource)
385+
attrs := resource.Primary.Attributes
386+
require.Equal(t, attrs["name"], "preset_1")
387+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.timezone"], "UTC")
388+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.schedule.0.cron"], "* 8-18 * * 1-5")
389+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.schedule.0.instances"], "3")
390+
return nil
391+
},
392+
},
393+
{
394+
Name: "Prebuilds is set with an autoscaling field with 2 schedules",
395+
Config: `
396+
data "coder_workspace_preset" "preset_1" {
397+
name = "preset_1"
398+
prebuilds {
399+
instances = 1
400+
autoscaling {
401+
timezone = "UTC"
402+
schedule {
403+
cron = "* 8-18 * * 1-5"
404+
instances = 3
405+
}
406+
schedule {
407+
cron = "* 8-14 * * 6"
408+
instances = 1
409+
}
410+
}
411+
}
412+
}`,
413+
ExpectError: nil,
414+
Check: func(state *terraform.State) error {
415+
require.Len(t, state.Modules, 1)
416+
require.Len(t, state.Modules[0].Resources, 1)
417+
resource := state.Modules[0].Resources["data.coder_workspace_preset.preset_1"]
418+
require.NotNil(t, resource)
419+
attrs := resource.Primary.Attributes
420+
require.Equal(t, attrs["name"], "preset_1")
421+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.timezone"], "UTC")
422+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.schedule.0.cron"], "* 8-18 * * 1-5")
423+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.schedule.0.instances"], "3")
424+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.schedule.1.cron"], "* 8-14 * * 6")
425+
require.Equal(t, attrs["prebuilds.0.autoscaling.0.schedule.1.instances"], "1")
426+
return nil
427+
},
428+
},
268429
}
269430

270431
for _, testcase := range testcases {

0 commit comments

Comments
 (0)