mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: implement expiration policy logic for prebuilds (#17996)
## Summary This PR introduces support for expiration policies in prebuilds. The TTL (time-to-live) is retrieved from the Terraform configuration ([terraform-provider-coder PR](https://github.com/coder/terraform-provider-coder/pull/404)): ``` prebuilds = { instances = 2 expiration_policy { ttl = 86400 } } ``` **Note**: Since there is no need for precise TTL enforcement down to the second, in this implementation expired prebuilds are handled in a single reconciliation cycle: they are deleted, and new instances are created only if needed to match the desired count. ## Changes * The outcome of a reconciliation cycle is now expressed as a slice of reconciliation actions, instead of a single aggregated action. * Adjusted reconciliation logic to delete expired prebuilds and guarantee that the number of desired instances is correct. * Updated relevant data structures and methods to support expiration policies parameters. * Added documentation to `Prebuilt workspaces` page * Update `terraform-provider-coder` to version 2.5.0: https://github.com/coder/terraform-provider-coder/releases/tag/v2.5.0 Depends on: https://github.com/coder/terraform-provider-coder/pull/404 Fixes: https://github.com/coder/coder/issues/17916
This commit is contained in:
@@ -897,14 +897,21 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
|
||||
)
|
||||
}
|
||||
var prebuildInstances int32
|
||||
var expirationPolicy *proto.ExpirationPolicy
|
||||
if len(preset.Prebuilds) > 0 {
|
||||
prebuildInstances = int32(math.Min(math.MaxInt32, float64(preset.Prebuilds[0].Instances)))
|
||||
if len(preset.Prebuilds[0].ExpirationPolicy) > 0 {
|
||||
expirationPolicy = &proto.ExpirationPolicy{
|
||||
Ttl: int32(math.Min(math.MaxInt32, float64(preset.Prebuilds[0].ExpirationPolicy[0].TTL))),
|
||||
}
|
||||
}
|
||||
}
|
||||
protoPreset := &proto.Preset{
|
||||
Name: preset.Name,
|
||||
Parameters: presetParameters,
|
||||
Prebuild: &proto.Prebuild{
|
||||
Instances: prebuildInstances,
|
||||
Instances: prebuildInstances,
|
||||
ExpirationPolicy: expirationPolicy,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -786,6 +786,7 @@ func TestConvertResources(t *testing.T) {
|
||||
Name: "dev",
|
||||
OperatingSystem: "windows",
|
||||
Architecture: "arm64",
|
||||
ApiKeyScope: "all",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
DisplayApps: &displayApps,
|
||||
@@ -830,6 +831,9 @@ func TestConvertResources(t *testing.T) {
|
||||
}},
|
||||
Prebuild: &proto.Prebuild{
|
||||
Instances: 4,
|
||||
ExpirationPolicy: &proto.ExpirationPolicy{
|
||||
Ttl: 86400,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
|
||||
@@ -25,6 +25,9 @@ data "coder_workspace_preset" "MyFirstProject" {
|
||||
}
|
||||
prebuilds {
|
||||
instances = 4
|
||||
expiration_policy {
|
||||
ttl = 86400
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-1
@@ -12,6 +12,7 @@
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"schema_version": 1,
|
||||
"values": {
|
||||
"api_key_scope": "all",
|
||||
"arch": "arm64",
|
||||
"auth": "token",
|
||||
"connection_timeout": 120,
|
||||
@@ -62,6 +63,7 @@
|
||||
],
|
||||
"before": null,
|
||||
"after": {
|
||||
"api_key_scope": "all",
|
||||
"arch": "arm64",
|
||||
"auth": "token",
|
||||
"connection_timeout": 120,
|
||||
@@ -134,6 +136,7 @@
|
||||
"description": "blah blah",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "57ccea62-8edf-41d1-a2c1-33f365e27567",
|
||||
"mutable": false,
|
||||
@@ -141,6 +144,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "ok"
|
||||
@@ -164,6 +168,11 @@
|
||||
},
|
||||
"prebuilds": [
|
||||
{
|
||||
"expiration_policy": [
|
||||
{
|
||||
"ttl": 86400
|
||||
}
|
||||
],
|
||||
"instances": 4
|
||||
}
|
||||
]
|
||||
@@ -171,7 +180,11 @@
|
||||
"sensitive_values": {
|
||||
"parameters": {},
|
||||
"prebuilds": [
|
||||
{}
|
||||
{
|
||||
"expiration_policy": [
|
||||
{}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -191,6 +204,7 @@
|
||||
"description": "First parameter from module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "1774175f-0efd-4a79-8d40-dbbc559bf7c1",
|
||||
"mutable": true,
|
||||
@@ -198,6 +212,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "abcdef"
|
||||
@@ -218,6 +233,7 @@
|
||||
"description": "Second parameter from module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "23d6841f-bb95-42bb-b7ea-5b254ce6c37d",
|
||||
"mutable": true,
|
||||
@@ -225,6 +241,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "ghijkl"
|
||||
@@ -250,6 +267,7 @@
|
||||
"description": "First parameter from child module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "9d629df2-9846-47b2-ab1f-e7c882f35117",
|
||||
"mutable": true,
|
||||
@@ -257,6 +275,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "abcdef"
|
||||
@@ -277,6 +296,7 @@
|
||||
"description": "Second parameter from child module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "52ca7b77-42a1-4887-a2f5-7a728feebdd5",
|
||||
"mutable": true,
|
||||
@@ -284,6 +304,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "ghijkl"
|
||||
@@ -388,6 +409,13 @@
|
||||
},
|
||||
"prebuilds": [
|
||||
{
|
||||
"expiration_policy": [
|
||||
{
|
||||
"ttl": {
|
||||
"constant_value": 86400
|
||||
}
|
||||
}
|
||||
],
|
||||
"instances": {
|
||||
"constant_value": 4
|
||||
}
|
||||
|
||||
+21
-1
@@ -16,6 +16,7 @@
|
||||
"description": "blah blah",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "491d202d-5658-40d9-9adc-fd3a67f6042b",
|
||||
"mutable": false,
|
||||
@@ -23,6 +24,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "ok"
|
||||
@@ -46,6 +48,11 @@
|
||||
},
|
||||
"prebuilds": [
|
||||
{
|
||||
"expiration_policy": [
|
||||
{
|
||||
"ttl": 86400
|
||||
}
|
||||
],
|
||||
"instances": 4
|
||||
}
|
||||
]
|
||||
@@ -53,7 +60,11 @@
|
||||
"sensitive_values": {
|
||||
"parameters": {},
|
||||
"prebuilds": [
|
||||
{}
|
||||
{
|
||||
"expiration_policy": [
|
||||
{}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -65,6 +76,7 @@
|
||||
"provider_name": "registry.terraform.io/coder/coder",
|
||||
"schema_version": 1,
|
||||
"values": {
|
||||
"api_key_scope": "all",
|
||||
"arch": "arm64",
|
||||
"auth": "token",
|
||||
"connection_timeout": 120,
|
||||
@@ -133,6 +145,7 @@
|
||||
"description": "First parameter from module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "0a4d1299-b174-43b0-91ad-50c1ca9a4c25",
|
||||
"mutable": true,
|
||||
@@ -140,6 +153,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "abcdef"
|
||||
@@ -160,6 +174,7 @@
|
||||
"description": "Second parameter from module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "f0812474-29fd-4c3c-ab40-9e66e36d4017",
|
||||
"mutable": true,
|
||||
@@ -167,6 +182,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "ghijkl"
|
||||
@@ -192,6 +208,7 @@
|
||||
"description": "First parameter from child module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "27b5fae3-7671-4e61-bdfe-c940627a21b8",
|
||||
"mutable": true,
|
||||
@@ -199,6 +216,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "abcdef"
|
||||
@@ -219,6 +237,7 @@
|
||||
"description": "Second parameter from child module",
|
||||
"display_name": null,
|
||||
"ephemeral": false,
|
||||
"form_type": "input",
|
||||
"icon": null,
|
||||
"id": "d285bb17-27ff-4a49-a12b-28582264b4d9",
|
||||
"mutable": true,
|
||||
@@ -226,6 +245,7 @@
|
||||
"option": null,
|
||||
"optional": true,
|
||||
"order": null,
|
||||
"styling": "{}",
|
||||
"type": "string",
|
||||
"validation": [],
|
||||
"value": "ghijkl"
|
||||
|
||||
Reference in New Issue
Block a user