diff --git a/coderd/database/migrations/000290_oom_and_ood_notification.down.sql b/coderd/database/migrations/000290_oom_and_ood_notification.down.sql
new file mode 100644
index 0000000000..a7d54ccf6e
--- /dev/null
+++ b/coderd/database/migrations/000290_oom_and_ood_notification.down.sql
@@ -0,0 +1,2 @@
+DELETE FROM notification_templates WHERE id = 'f047f6a3-5713-40f7-85aa-0394cce9fa3a';
+DELETE FROM notification_templates WHERE id = 'a9d027b4-ac49-4fb1-9f6d-45af15f64e7a';
diff --git a/coderd/database/migrations/000290_oom_and_ood_notification.up.sql b/coderd/database/migrations/000290_oom_and_ood_notification.up.sql
new file mode 100644
index 0000000000..f0489606bb
--- /dev/null
+++ b/coderd/database/migrations/000290_oom_and_ood_notification.up.sql
@@ -0,0 +1,40 @@
+INSERT INTO notification_templates
+ (id, name, title_template, body_template, "group", actions)
+VALUES (
+ 'a9d027b4-ac49-4fb1-9f6d-45af15f64e7a',
+ 'Workspace Out Of Memory',
+ E'Your workspace "{{.Labels.workspace}}" is low on memory',
+ E'Hi {{.UserName}},\n\n'||
+ E'Your workspace **{{.Labels.workspace}}** has reached the memory usage threshold set at **{{.Labels.threshold}}**.',
+ 'Workspace Events',
+ '[
+ {
+ "label": "View workspace",
+ "url": "{{base_url}}/@{{.UserUsername}}/{{.Labels.workspace}}"
+ }
+ ]'::jsonb
+);
+
+INSERT INTO notification_templates
+ (id, name, title_template, body_template, "group", actions)
+VALUES (
+ 'f047f6a3-5713-40f7-85aa-0394cce9fa3a',
+ 'Workspace Out Of Disk',
+ E'Your workspace "{{.Labels.workspace}}" is low on volume space',
+ E'Hi {{.UserName}},\n\n'||
+ E'{{ if eq (len .Data.volumes) 1 }}{{ $volume := index .Data.volumes 0 }}'||
+ E'Volume **`{{$volume.path}}`** is over {{$volume.threshold}} full in workspace **{{.Labels.workspace}}**.'||
+ E'{{ else }}'||
+ E'The following volumes are nearly full in workspace **{{.Labels.workspace}}**\n\n'||
+ E'{{ range $volume := .Data.volumes }}'||
+ E'- **`{{$volume.path}}`** is over {{$volume.threshold}} full\n'||
+ E'{{ end }}'||
+ E'{{ end }}',
+ 'Workspace Events',
+ '[
+ {
+ "label": "View workspace",
+ "url": "{{base_url}}/@{{.UserUsername}}/{{.Labels.workspace}}"
+ }
+ ]'::jsonb
+);
diff --git a/coderd/notifications/events.go b/coderd/notifications/events.go
index 754d2e5c7f..5141f0f20c 100644
--- a/coderd/notifications/events.go
+++ b/coderd/notifications/events.go
@@ -15,6 +15,8 @@ var (
TemplateWorkspaceAutoUpdated = uuid.MustParse("c34a0c09-0704-4cac-bd1c-0c0146811c2b")
TemplateWorkspaceMarkedForDeletion = uuid.MustParse("51ce2fdf-c9ca-4be1-8d70-628674f9bc42")
TemplateWorkspaceManualBuildFailed = uuid.MustParse("2faeee0f-26cb-4e96-821c-85ccb9f71513")
+ TemplateWorkspaceOutOfMemory = uuid.MustParse("a9d027b4-ac49-4fb1-9f6d-45af15f64e7a")
+ TemplateWorkspaceOutOfDisk = uuid.MustParse("f047f6a3-5713-40f7-85aa-0394cce9fa3a")
)
// Account-related events.
diff --git a/coderd/notifications/notifications_test.go b/coderd/notifications/notifications_test.go
index cec9ef1313..895fafff88 100644
--- a/coderd/notifications/notifications_test.go
+++ b/coderd/notifications/notifications_test.go
@@ -1064,6 +1064,67 @@ func TestNotificationTemplates_Golden(t *testing.T) {
},
},
},
+ {
+ name: "TemplateWorkspaceOutOfMemory",
+ id: notifications.TemplateWorkspaceOutOfMemory,
+ payload: types.MessagePayload{
+ UserName: "Bobby",
+ UserEmail: "bobby@coder.com",
+ UserUsername: "bobby",
+ Labels: map[string]string{
+ "workspace": "bobby-workspace",
+ "threshold": "90%",
+ },
+ },
+ },
+ {
+ name: "TemplateWorkspaceOutOfDisk",
+ id: notifications.TemplateWorkspaceOutOfDisk,
+ payload: types.MessagePayload{
+ UserName: "Bobby",
+ UserEmail: "bobby@coder.com",
+ UserUsername: "bobby",
+ Labels: map[string]string{
+ "workspace": "bobby-workspace",
+ },
+ Data: map[string]any{
+ "volumes": []map[string]any{
+ {
+ "path": "/home/coder",
+ "threshold": "90%",
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "TemplateWorkspaceOutOfDisk_MultipleVolumes",
+ id: notifications.TemplateWorkspaceOutOfDisk,
+ payload: types.MessagePayload{
+ UserName: "Bobby",
+ UserEmail: "bobby@coder.com",
+ UserUsername: "bobby",
+ Labels: map[string]string{
+ "workspace": "bobby-workspace",
+ },
+ Data: map[string]any{
+ "volumes": []map[string]any{
+ {
+ "path": "/home/coder",
+ "threshold": "90%",
+ },
+ {
+ "path": "/dev/coder",
+ "threshold": "80%",
+ },
+ {
+ "path": "/etc/coder",
+ "threshold": "95%",
+ },
+ },
+ },
+ },
+ },
}
// We must have a test case for every notification_template. This is enforced below:
diff --git a/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfDisk.html.golden b/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfDisk.html.golden
new file mode 100644
index 0000000000..f217fc0f85
--- /dev/null
+++ b/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfDisk.html.golden
@@ -0,0 +1,78 @@
+From: system@coder.com
+To: bobby@coder.com
+Subject: Your workspace "bobby-workspace" is low on volume space
+Message-Id: 02ee4935-73be-4fa1-a290-ff9999026b13@blush-whale-48
+Date: Fri, 11 Oct 2024 09:03:06 +0000
+Content-Type: multipart/alternative; boundary=bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+MIME-Version: 1.0
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/plain; charset=UTF-8
+
+Hi Bobby,
+
+Volume /home/coder is over 90% full in workspace bobby-workspace.
+
+
+View workspace: http://test.com/@bobby/bobby-workspace
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/html; charset=UTF-8
+
+
+
+
+
+
+ Your workspace "bobby-workspace" is low on volume space
+
+
+
+
+

+
+
+ Your workspace "bobby-workspace" is low on volume space
+
+
+
Hi Bobby,
+
+
Volume /home/coder
is over 90% full in wor=
+kspace bobby-workspace.
+
+
+
+
+
+
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4--
diff --git a/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfDisk_MultipleVolumes.html.golden b/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfDisk_MultipleVolumes.html.golden
new file mode 100644
index 0000000000..87e5dec07c
--- /dev/null
+++ b/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfDisk_MultipleVolumes.html.golden
@@ -0,0 +1,91 @@
+From: system@coder.com
+To: bobby@coder.com
+Subject: Your workspace "bobby-workspace" is low on volume space
+Message-Id: 02ee4935-73be-4fa1-a290-ff9999026b13@blush-whale-48
+Date: Fri, 11 Oct 2024 09:03:06 +0000
+Content-Type: multipart/alternative; boundary=bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+MIME-Version: 1.0
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/plain; charset=UTF-8
+
+Hi Bobby,
+
+The following volumes are nearly full in workspace bobby-workspace
+
+/home/coder is over 90% full
+/dev/coder is over 80% full
+/etc/coder is over 95% full
+
+
+View workspace: http://test.com/@bobby/bobby-workspace
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/html; charset=UTF-8
+
+
+
+
+
+
+ Your workspace "bobby-workspace" is low on volume space
+
+
+
+
+

+
+
+ Your workspace "bobby-workspace" is low on volume space
+
+
+
Hi Bobby,
+
+
The following volumes are nearly full in workspace bobby-workspa=
+ce
+
+
+/home/coder
is over 90% full
+
+/dev/coder
is over 80% full
+
+/etc/coder
is over 95% full
+
+
+
+
+
+
+
+
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4--
diff --git a/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfMemory.html.golden b/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfMemory.html.golden
new file mode 100644
index 0000000000..1aa27cb4cc
--- /dev/null
+++ b/coderd/notifications/testdata/rendered-templates/smtp/TemplateWorkspaceOutOfMemory.html.golden
@@ -0,0 +1,79 @@
+From: system@coder.com
+To: bobby@coder.com
+Subject: Your workspace "bobby-workspace" is low on memory
+Message-Id: 02ee4935-73be-4fa1-a290-ff9999026b13@blush-whale-48
+Date: Fri, 11 Oct 2024 09:03:06 +0000
+Content-Type: multipart/alternative; boundary=bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+MIME-Version: 1.0
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/plain; charset=UTF-8
+
+Hi Bobby,
+
+Your workspace bobby-workspace has reached the memory usage threshold set a=
+t 90%.
+
+
+View workspace: http://test.com/@bobby/bobby-workspace
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/html; charset=UTF-8
+
+
+
+
+
+
+ Your workspace "bobby-workspace" is low on memory
+
+
+
+
+

+
+
+ Your workspace "bobby-workspace" is low on memory
+
+
+
Hi Bobby,
+
+
Your workspace bobby-workspace has reached the memory u=
+sage threshold set at 90%.
+
+
+
+
+
+
+
+--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4--
diff --git a/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfDisk.json.golden b/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfDisk.json.golden
new file mode 100644
index 0000000000..1bc671f52b
--- /dev/null
+++ b/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfDisk.json.golden
@@ -0,0 +1,34 @@
+{
+ "_version": "1.1",
+ "msg_id": "00000000-0000-0000-0000-000000000000",
+ "payload": {
+ "_version": "1.1",
+ "notification_name": "Workspace Out Of Disk",
+ "notification_template_id": "00000000-0000-0000-0000-000000000000",
+ "user_id": "00000000-0000-0000-0000-000000000000",
+ "user_email": "bobby@coder.com",
+ "user_name": "Bobby",
+ "user_username": "bobby",
+ "actions": [
+ {
+ "label": "View workspace",
+ "url": "http://test.com/@bobby/bobby-workspace"
+ }
+ ],
+ "labels": {
+ "workspace": "bobby-workspace"
+ },
+ "data": {
+ "volumes": [
+ {
+ "path": "/home/coder",
+ "threshold": "90%"
+ }
+ ]
+ }
+ },
+ "title": "Your workspace \"bobby-workspace\" is low on volume space",
+ "title_markdown": "Your workspace \"bobby-workspace\" is low on volume space",
+ "body": "Hi Bobby,\n\nVolume /home/coder is over 90% full in workspace bobby-workspace.",
+ "body_markdown": "Hi Bobby,\n\nVolume **`/home/coder`** is over 90% full in workspace **bobby-workspace**."
+}
\ No newline at end of file
diff --git a/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfDisk_MultipleVolumes.json.golden b/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfDisk_MultipleVolumes.json.golden
new file mode 100644
index 0000000000..c876fb1754
--- /dev/null
+++ b/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfDisk_MultipleVolumes.json.golden
@@ -0,0 +1,42 @@
+{
+ "_version": "1.1",
+ "msg_id": "00000000-0000-0000-0000-000000000000",
+ "payload": {
+ "_version": "1.1",
+ "notification_name": "Workspace Out Of Disk",
+ "notification_template_id": "00000000-0000-0000-0000-000000000000",
+ "user_id": "00000000-0000-0000-0000-000000000000",
+ "user_email": "bobby@coder.com",
+ "user_name": "Bobby",
+ "user_username": "bobby",
+ "actions": [
+ {
+ "label": "View workspace",
+ "url": "http://test.com/@bobby/bobby-workspace"
+ }
+ ],
+ "labels": {
+ "workspace": "bobby-workspace"
+ },
+ "data": {
+ "volumes": [
+ {
+ "path": "/home/coder",
+ "threshold": "90%"
+ },
+ {
+ "path": "/dev/coder",
+ "threshold": "80%"
+ },
+ {
+ "path": "/etc/coder",
+ "threshold": "95%"
+ }
+ ]
+ }
+ },
+ "title": "Your workspace \"bobby-workspace\" is low on volume space",
+ "title_markdown": "Your workspace \"bobby-workspace\" is low on volume space",
+ "body": "Hi Bobby,\n\nThe following volumes are nearly full in workspace bobby-workspace\n\n/home/coder is over 90% full\n/dev/coder is over 80% full\n/etc/coder is over 95% full",
+ "body_markdown": "Hi Bobby,\n\nThe following volumes are nearly full in workspace **bobby-workspace**\n\n- **`/home/coder`** is over 90% full\n- **`/dev/coder`** is over 80% full\n- **`/etc/coder`** is over 95% full\n"
+}
\ No newline at end of file
diff --git a/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfMemory.json.golden b/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfMemory.json.golden
new file mode 100644
index 0000000000..a0fce437e3
--- /dev/null
+++ b/coderd/notifications/testdata/rendered-templates/webhook/TemplateWorkspaceOutOfMemory.json.golden
@@ -0,0 +1,28 @@
+{
+ "_version": "1.1",
+ "msg_id": "00000000-0000-0000-0000-000000000000",
+ "payload": {
+ "_version": "1.1",
+ "notification_name": "Workspace Out Of Memory",
+ "notification_template_id": "00000000-0000-0000-0000-000000000000",
+ "user_id": "00000000-0000-0000-0000-000000000000",
+ "user_email": "bobby@coder.com",
+ "user_name": "Bobby",
+ "user_username": "bobby",
+ "actions": [
+ {
+ "label": "View workspace",
+ "url": "http://test.com/@bobby/bobby-workspace"
+ }
+ ],
+ "labels": {
+ "threshold": "90%",
+ "workspace": "bobby-workspace"
+ },
+ "data": null
+ },
+ "title": "Your workspace \"bobby-workspace\" is low on memory",
+ "title_markdown": "Your workspace \"bobby-workspace\" is low on memory",
+ "body": "Hi Bobby,\n\nYour workspace bobby-workspace has reached the memory usage threshold set at 90%.",
+ "body_markdown": "Hi Bobby,\n\nYour workspace **bobby-workspace** has reached the memory usage threshold set at **90%**."
+}
\ No newline at end of file