-
Notifications
You must be signed in to change notification settings - Fork 22
feat: add autoscaling configuration for prebuilds #408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
15cae29
to
543a735
Compare
2f82387
to
d61894d
Compare
Schema: map[string]*schema.Schema{ | ||
"timezone": { | ||
Type: schema.TypeString, | ||
Description: "The timezone to use for the autoscaling schedule (e.g., \"UTC\", \"America/New_York\").", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: can you include a link to an acceptable list of TZs here? I think https://en.wikipedia.org/wiki/List_of_tz_database_time_zones suffices but I'm not sure.
https://pkg.go.dev/time#LoadLocation says it references the "IANA Time Zone database".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the help output of coder schedule {start|stop}
for some sample wording. The phrase "timezone" is slightly misleading here as it's the location that influences the timezone depending on wibbly wobbly timey wimey stuff.
|
||
_, err := time.LoadLocation(timezone) | ||
if err != nil { | ||
return nil, []error{fmt.Errorf("failed to load location: %w", err)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nil, []error{fmt.Errorf("failed to load location: %w", err)} | |
return nil, []error{fmt.Errorf("failed to load timezone %q: %w", timezone, err)} |
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"timezone": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love that we explicitly don't have a default value here 👍 nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend defaulting to TZ
or /etc/localtime
, and falling back to UTC. There's a helper function tz.TimezoneIANA
for this.
EDIT: given that this is for the provider, you might actually be correct in not specifying any default here as we can't assume that the timezone in which the provider is running is the same timezone as coderd.
Schema: map[string]*schema.Schema{ | ||
"cron": { | ||
Type: schema.TypeString, | ||
Description: "A cron expression that defines when this schedule should be active. The cron expression must be in the format \"* HOUR * * DAY-OF-WEEK\" where HOUR is 0-23 and DAY-OF-WEEK is 0-6 (Sunday-Saturday). The minute, day-of-month, and month fields must be \"*\".", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why must day-of-month and month be *
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming this relates to the "weekly cron schedule" concept we already use for schedules?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems so, but I think that's a strange requirement since nothing in this implementation is on a weekly cadence.
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
// validatePrebuildsCronSpec ensures that the minute, day-of-month and month options of spec are all set to * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be good to add the why here, not just the what.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to EDIT: sorry, thought this was a different project :Pcoderd/schedule/cron
autoscaling {} | ||
} | ||
}`, | ||
ExpectError: regexp.MustCompile(`The argument "[^"]+" is required, but no definition was found.`), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: let's check for a precise name to ensure we don't get false positives.
Or is it like this because we can't know which argument will show up first?
}, | ||
}, | ||
{ | ||
Name: "Prebuilds is set with an autoscaling field with 2 schedules", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do we check that these schedules are not conflicting? I didn't find any checks in coder/coder#18126 from a quick scan. I'll review that PR in more detail tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the current time matches any defined autoscaling schedule, the corresponding number of instances is used.
This makes me nervous because it introduces some non-determinism in the case of conflicting/overlapping schedules. If we don't evaluate cron schedules in the same order, we could flip back and forth between conflicting schedules, which could cause a lot of churn and confusion.
|
||
// validatePrebuildsCronSpec ensures that the minute, day-of-month and month options of spec are all set to * | ||
func validatePrebuildsCronSpec(spec string) error { | ||
parts := strings.Fields(spec) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Howcome we don't use PrebuildsCRONParser
here?
I really don't think we should call this "autoscaling" as that already has a specific meaning in Cloud circles which this is not. Autoscaling is adjusting instance counts dynamically based on measured load. This is adjusting instance counts based on a schedule. Some possible names:
|
Relates to coder/internal#312
Needed for coder/coder#18126
Exposes an
autoscaling
field undercoder_workspace_preset
: