From 75ac031483057ff553756d4f0667d15cd7e42c53 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Tue, 16 Jul 2024 21:08:02 -0700 Subject: [PATCH] Move NotificationClientID to Garden - Also improve tests by using VHS for Pushover client --- deploy/docker-compose.yml | 1 - garden-app/pkg/garden.go | 16 +++- garden-app/pkg/light_schedule.go | 18 +--- garden-app/pkg/storage/client.go | 2 +- garden-app/server/garden.go | 14 +-- garden-app/server/garden_test.go | 6 +- garden-app/server/templates/garden_modal.html | 12 +-- .../testdata/fixtures/pushover_fail.yaml | 80 ++++++++++++++++ .../testdata/fixtures/pushover_success.yaml | 93 +++++++++++++++++++ .../server/water_notification_handler.go | 31 ++++--- .../server/water_notification_handler_test.go | 93 +++++++++++++++++-- garden-app/worker/notifications.go | 4 +- garden-app/worker/scheduler.go | 8 +- garden-app/worker/scheduler_test.go | 4 +- 14 files changed, 315 insertions(+), 67 deletions(-) create mode 100644 garden-app/server/testdata/fixtures/pushover_fail.yaml create mode 100644 garden-app/server/testdata/fixtures/pushover_success.yaml diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 40b77b3e..8d8669b7 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -3,7 +3,6 @@ # - run-local: run required services + extras like Grafana and Prometheus # - demo: run everything, including an instance of garden-app and garden-controller -version: "3.9" services: grafana: image: "grafana/grafana:latest" diff --git a/garden-app/pkg/garden.go b/garden-app/pkg/garden.go index 79e01c7a..bfc65dfc 100644 --- a/garden-app/pkg/garden.go +++ b/garden-app/pkg/garden.go @@ -30,6 +30,7 @@ type Garden struct { EndDate *time.Time `json:"end_date,omitempty" yaml:"end_date,omitempty"` LightSchedule *LightSchedule `json:"light_schedule,omitempty" yaml:"light_schedule,omitempty"` TemperatureHumiditySensor *bool `json:"temperature_humidity_sensor,omitempty" yaml:"temperature_humidity_sensor,omitempty"` + NotificationClientID *string `json:"notification_client_id,omitempty" yaml:"notification_client_id,omitempty"` } func (g *Garden) GetID() string { @@ -41,6 +42,14 @@ func (g *Garden) String() string { return fmt.Sprintf("%+v", *g) } +func (g *Garden) GetNotificationClientID() string { + if g.NotificationClientID == nil { + return "" + } + + return *g.NotificationClientID +} + // GardenHealth holds information about the Garden controller's health status type GardenHealth struct { Status HealthStatus `json:"status,omitempty"` @@ -117,8 +126,7 @@ func (g *Garden) Patch(newGarden *Garden) *babyapi.ErrResponse { // If both Duration and StartTime are empty, remove the schedule if newGarden.LightSchedule.Duration == nil && - newGarden.LightSchedule.StartTime == nil && - newGarden.LightSchedule.NotificationClientID == nil { + newGarden.LightSchedule.StartTime == nil { g.LightSchedule = nil } } @@ -126,6 +134,10 @@ func (g *Garden) Patch(newGarden *Garden) *babyapi.ErrResponse { g.TemperatureHumiditySensor = newGarden.TemperatureHumiditySensor } + if newGarden.NotificationClientID != nil { + g.NotificationClientID = newGarden.NotificationClientID + } + return nil } diff --git a/garden-app/pkg/light_schedule.go b/garden-app/pkg/light_schedule.go index b5c316e1..c893e8da 100644 --- a/garden-app/pkg/light_schedule.go +++ b/garden-app/pkg/light_schedule.go @@ -66,10 +66,9 @@ func (l *LightState) unmarshal(data []byte) error { // LightSchedule allows the user to control when the Garden light is turned on and off // "Time" should be in the format of LightTimeFormat constant ("15:04:05-07:00") type LightSchedule struct { - Duration *Duration `json:"duration" yaml:"duration"` - StartTime *StartTime `json:"start_time" yaml:"start_time"` - AdhocOnTime *time.Time `json:"adhoc_on_time,omitempty" yaml:"adhoc_on_time,omitempty"` - NotificationClientID *string `json:"notification_client_id,omitempty" yaml:"notification_client_id,omitempty"` + Duration *Duration `json:"duration" yaml:"duration"` + StartTime *StartTime `json:"start_time" yaml:"start_time"` + AdhocOnTime *time.Time `json:"adhoc_on_time,omitempty" yaml:"adhoc_on_time,omitempty"` } // String... @@ -77,14 +76,6 @@ func (ls *LightSchedule) String() string { return fmt.Sprintf("%+v", *ls) } -func (ls *LightSchedule) GetNotificationClientID() string { - if ls.NotificationClientID == nil { - return "" - } - - return *ls.NotificationClientID -} - // Patch allows modifying the struct in-place with values from a different instance func (ls *LightSchedule) Patch(new *LightSchedule) { if new.Duration != nil { @@ -96,7 +87,4 @@ func (ls *LightSchedule) Patch(new *LightSchedule) { if new.AdhocOnTime == nil { ls.AdhocOnTime = nil } - if new.NotificationClientID != nil { - ls.NotificationClientID = new.NotificationClientID - } } diff --git a/garden-app/pkg/storage/client.go b/garden-app/pkg/storage/client.go index 9c7c82bb..48dece1b 100644 --- a/garden-app/pkg/storage/client.go +++ b/garden-app/pkg/storage/client.go @@ -9,10 +9,10 @@ import ( "github.com/calvinmclean/babyapi" "github.com/calvinmclean/babyapi/storage/kv" + "github.com/mitchellh/mapstructure" "github.com/tarmac-project/hord" "github.com/tarmac-project/hord/drivers/hashmap" "github.com/tarmac-project/hord/drivers/redis" - "github.com/mitchellh/mapstructure" ) // Config is used to identify and configure a storage client diff --git a/garden-app/server/garden.go b/garden-app/server/garden.go index 327ffd91..846f1598 100644 --- a/garden-app/server/garden.go +++ b/garden-app/server/garden.go @@ -178,15 +178,15 @@ func (api *GardensAPI) onCreateOrUpdate(_ http.ResponseWriter, r *http.Request, } } - if garden.LightSchedule != nil { - // Validate NotificationClient exists - if garden.LightSchedule.NotificationClientID != nil { - apiErr := checkNotificationClientExists(r.Context(), api.storageClient, *garden.LightSchedule.NotificationClientID) - if apiErr != nil { - return apiErr - } + // Validate NotificationClient exists + if garden.NotificationClientID != nil { + apiErr := checkNotificationClientExists(r.Context(), api.storageClient, *garden.NotificationClientID) + if apiErr != nil { + return apiErr } + } + if garden.LightSchedule != nil { // Update the light schedule for the Garden (if it exists) logger.Info("updating/resetting LightSchedule for Garden") if err := api.worker.ResetLightSchedule(garden); err != nil { diff --git a/garden-app/server/garden_test.go b/garden-app/server/garden_test.go index cbe68c8c..8199d09d 100644 --- a/garden-app/server/garden_test.go +++ b/garden-app/server/garden_test.go @@ -437,7 +437,7 @@ func TestUpdateGarden(t *testing.T) { "AddNotificationClientIDErrorNotFound", createExampleGarden(), nil, - `{"light_schedule":{"notification_client_id":"NOTIFICATION_CLIENT_ID"}}`, + `{"notification_client_id":"NOTIFICATION_CLIENT_ID"}`, `{"status":"Invalid request.","error":"error getting NotificationClient with ID \\"NOTIFICATION_CLIENT_ID\\": resource not found"}`, http.StatusBadRequest, }, @@ -445,8 +445,8 @@ func TestUpdateGarden(t *testing.T) { "AddNotificationClientIDSuccess", createExampleGarden(), nil, - `{"light_schedule":{"notification_client_id":"c5cvhpcbcv45e8bp16dg"}}`, - `{"name":"test-garden","topic_prefix":"test-garden","id":"[0-9a-v]{20}","max_zones":2,"created_at":"\d{4}-\d{2}-\d\dT\d\d:\d\d:\d\d\.\d+(-07:00|Z)","light_schedule":{"duration":"15h0m0s","start_time":"22:00:01-07:00","notification_client_id":"c5cvhpcbcv45e8bp16dg"},"next_light_action":{"time":"0000-12-31T17:00:00-07:00","state":"OFF"},"health":{"status":"UP","details":"last contact from Garden was \d+(s|ms) ago","last_contact":"\d{4}-\d{2}-\d\dT\d\d:\d\d:\d\d\.\d+(-07:00|Z)"},"num_zones":1,"links":\[{"rel":"self","href":"/gardens/[0-9a-v]{20}"},{"rel":"zones","href":"/gardens/c5cvhpcbcv45e8bp16dg/zones"},{"rel":"action","href":"/gardens/[0-9a-v]{20}/action"}\]}`, + `{"notification_client_id":"c5cvhpcbcv45e8bp16dg"}`, + `{"name":"test-garden","topic_prefix":"test-garden","id":"[0-9a-v]{20}","max_zones":2,"created_at":"\d{4}-\d{2}-\d\dT\d\d:\d\d:\d\d\.\d+(-07:00|Z)","light_schedule":{"duration":"15h0m0s","start_time":"22:00:01-07:00"},"notification_client_id":"c5cvhpcbcv45e8bp16dg","next_light_action":{"time":"0000-12-31T17:00:00-07:00","state":"OFF"},"health":{"status":"UP","details":"last contact from Garden was \d+(s|ms) ago","last_contact":"\d{4}-\d{2}-\d\dT\d\d:\d\d:\d\d\.\d+(-07:00|Z)"},"num_zones":1,"links":\[{"rel":"self","href":"/gardens/[0-9a-v]{20}"},{"rel":"zones","href":"/gardens/c5cvhpcbcv45e8bp16dg/zones"},{"rel":"action","href":"/gardens/[0-9a-v]{20}/action"}\]}`, http.StatusOK, }, { diff --git a/garden-app/server/templates/garden_modal.html b/garden-app/server/templates/garden_modal.html index 755f97c1..cf0c30ce 100644 --- a/garden-app/server/templates/garden_modal.html +++ b/garden-app/server/templates/garden_modal.html @@ -43,17 +43,15 @@

{{ if .Name }}{{ .Name }}{{ else }}Create Garden{{ en
- {{ $noClientSelected := true }} - {{ if ne .LightSchedule nil }} - $noClientSelected = eq .LightSchedule.NotificationClientID nil - {{ end }} + $noClientSelected = eq .NotificationClientID nil - {{ $ls := .LightSchedule }} + {{ $g := . }} {{ range $i, $nc := .NotificationClients }} - {{/* check if $ls is nil before calling CompareNotificationClientID */}} - {{ $selected := and $ls (CompareNotificationClientID $nc.GetID $ls) }} + {{/* check if $g is nil before calling CompareNotificationClientID */}} + {{ $selected := and $g (CompareNotificationClientID $nc.GetID $g) }} {{ end }} diff --git a/garden-app/server/testdata/fixtures/pushover_fail.yaml b/garden-app/server/testdata/fixtures/pushover_fail.yaml new file mode 100644 index 00000000..aa565231 --- /dev/null +++ b/garden-app/server/testdata/fixtures/pushover_fail.yaml @@ -0,0 +1,80 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 131 + transfer_encoding: [] + trailer: {} + host: api.pushover.net + remote_addr: "" + request_uri: "" + body: message=watered+for+6s&priority=0&title=+finished+watering&token=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&user=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + form: + message: + - watered for 6s + priority: + - "0" + title: + - ' finished watering' + token: + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + user: + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + headers: + Content-Type: + - application/x-www-form-urlencoded + url: https://api.pushover.net/1/messages.json + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: false + body: '{"token":"invalid","errors":["application token is invalid, see https://pushover.net/api"],"status":0,"request":"85158a2e-3f89-456b-9262-d14915ad76bc"}' + headers: + Access-Control-Allow-Headers: + - X-Requested-With, X-Prototype-Version, Origin, Accept, Content-Type, X-CSRF-Token, X-Pushover-App, Authorization + Access-Control-Allow-Methods: + - POST, OPTIONS + Access-Control-Allow-Origin: + - '*' + Access-Control-Max-Age: + - "1728000" + Cache-Control: + - no-cache + Cf-Cache-Status: + - DYNAMIC + Cf-Ray: + - 8a4749a09ad07c2d-LAX + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 17 Jul 2024 03:53:54 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - cloudflare + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 85158a2e-3f89-456b-9262-d14915ad76bc + X-Runtime: + - "0.007297" + X-Xss-Protection: + - 1; mode=block + status: 400 Bad Request + code: 400 + duration: 308.7185ms diff --git a/garden-app/server/testdata/fixtures/pushover_success.yaml b/garden-app/server/testdata/fixtures/pushover_success.yaml new file mode 100644 index 00000000..20a7710c --- /dev/null +++ b/garden-app/server/testdata/fixtures/pushover_success.yaml @@ -0,0 +1,93 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 131 + transfer_encoding: [] + trailer: {} + host: api.pushover.net + remote_addr: "" + request_uri: "" + body: message=watered+for+6s&priority=0&title=+finished+watering&token=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&user=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + form: + message: + - watered for 6s + priority: + - "0" + title: + - " finished watering" + token: + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + user: + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + headers: + Content-Type: + - application/x-www-form-urlencoded + url: https://api.pushover.net/1/messages.json + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"status":1,"request":"2e1d184d-da34-414c-ae3c-05022dc4a2f9"}' + headers: + Access-Control-Allow-Headers: + - X-Requested-With, X-Prototype-Version, Origin, Accept, Content-Type, X-CSRF-Token, X-Pushover-App, Authorization + Access-Control-Allow-Methods: + - POST, OPTIONS + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - "1728000" + Cache-Control: + - max-age=0, private, must-revalidate + Cf-Cache-Status: + - DYNAMIC + Cf-Ray: + - 8a47468bac122b54-LAX + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 17 Jul 2024 03:51:48 GMT + Etag: + - W/"fbf804824a9232da76ba211e79a0cd4a" + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - cloudflare + Strict-Transport-Security: + - max-age=31536000 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + - DENY + X-Limit-App-Limit: + - "10000" + X-Limit-App-Remaining: + - "9937" + X-Limit-App-Reset: + - "1722488400" + X-Permitted-Cross-Domain-Policies: + - none + X-Po-H: + - a + X-Request-Id: + - 2e1d184d-da34-414c-ae3c-05022dc4a2f9 + X-Runtime: + - "0.056145" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 416.0575ms diff --git a/garden-app/server/water_notification_handler.go b/garden-app/server/water_notification_handler.go index 2108a7d2..13b52ada 100644 --- a/garden-app/server/water_notification_handler.go +++ b/garden-app/server/water_notification_handler.go @@ -83,12 +83,20 @@ func (h *WaterNotificationHandler) handle(topic string, payload []byte) error { if topicPrefix == "" { return fmt.Errorf("received message on invalid topic: %w", err) } + logger = logger.With("topic_prefix", topicPrefix) garden, err := h.getGarden(topicPrefix) if err != nil { return fmt.Errorf("error getting garden with topic-prefix %q: %w", topicPrefix, err) } - logger.Info("found garden with topic-prefix", "topic_prefix", topicPrefix, "garden_id", garden.GetID()) + logger = logger.With("garden_id", garden.GetID()) + logger.Info("found garden with topic-prefix") + + if garden.GetNotificationClientID() == "" { + logger.Info("garden does not have notification client", "garden_id", garden.GetID()) + return nil + } + logger = logger.With(notificationClientIDLogField, garden.GetNotificationClientID()) zone, err := h.getZone(garden.GetID(), zonePosition) if err != nil { @@ -96,10 +104,7 @@ func (h *WaterNotificationHandler) handle(topic string, payload []byte) error { } logger.Info("found zone with position", "zone_position", zonePosition, "zone_id", zone.GetID()) - // TODO: Use Garden notification client here? However, Garden Notifications only work if a lightschedule exists. - // Instead, I could move the NotificationClientID from a WaterSched - // TODO: rename this file to notification_handler or something since it's hard to find - notificationClients, err := h.storageClient.NotificationClientConfigs.GetAll(context.Background(), nil) + notificationClient, err := h.storageClient.NotificationClientConfigs.Get(context.Background(), garden.GetNotificationClientID()) if err != nil { return fmt.Errorf("error getting all notification clients: %w", err) } @@ -107,18 +112,14 @@ func (h *WaterNotificationHandler) handle(topic string, payload []byte) error { title := fmt.Sprintf("%s finished watering", zone.Name) message := fmt.Sprintf("watered for %s", waterDuration.String()) - for _, nc := range notificationClients { - ncLogger := logger.With(notificationClientIDLogField, nc.GetID()) - - err = nc.SendMessage(title, message) - if err != nil { - ncLogger.Error("error sending message", "error", err) - continue - } - - ncLogger.Info("successfully send notification") + err = notificationClient.SendMessage(title, message) + if err != nil { + logger.Error("error sending message", "error", err) + return err } + logger.Info("successfully send notification") + return nil } diff --git a/garden-app/server/water_notification_handler_test.go b/garden-app/server/water_notification_handler_test.go index 309b9b4a..df589129 100644 --- a/garden-app/server/water_notification_handler_test.go +++ b/garden-app/server/water_notification_handler_test.go @@ -3,13 +3,17 @@ package server import ( "context" "log/slog" + "net/http" "testing" "time" "github.com/calvinmclean/automated-garden/garden-app/pkg" + "github.com/calvinmclean/automated-garden/garden-app/pkg/notifications" "github.com/calvinmclean/automated-garden/garden-app/pkg/storage" "github.com/calvinmclean/babyapi" "github.com/stretchr/testify/require" + "gopkg.in/dnaeon/go-vcr.v3/cassette" + "gopkg.in/dnaeon/go-vcr.v3/recorder" ) func TestParseWaterMessage(t *testing.T) { @@ -63,18 +67,13 @@ func TestHandleMessage(t *testing.T) { }) garden := &pkg.Garden{ - ID: babyapi.NewID(), - TopicPrefix: "garden", + ID: babyapi.NewID(), + TopicPrefix: "garden", + NotificationClientID: nil, } err = storageClient.Gardens.Set(context.Background(), garden) require.NoError(t, err) - t.Run("ErrorGettingZone", func(t *testing.T) { - err = handler.handle("garden/data/water", []byte("water,zone=0 millis=6000")) - require.Error(t, err) - require.Equal(t, "error getting zone with position 0: no zone found", err.Error()) - }) - zero := uint(0) zone := &pkg.Zone{ ID: babyapi.NewID(), @@ -88,4 +87,82 @@ func TestHandleMessage(t *testing.T) { err = handler.handle("garden/data/water", []byte("water,zone=0 millis=6000")) require.NoError(t, err) }) + + t.Run("CreateNotificationClient", func(t *testing.T) { + nc := ¬ifications.Client{ + ID: babyapi.NewID(), + Type: "pushover", + Options: map[string]any{ + "app_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "recipient_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + }, + } + + err := storageClient.NotificationClientConfigs.Set(context.Background(), nc) + require.NoError(t, err) + + ncID := nc.GetID() + apiErr := garden.Patch(&pkg.Garden{NotificationClientID: &ncID}) + require.Nil(t, apiErr) + err = storageClient.Gardens.Set(context.Background(), garden) + require.NoError(t, err) + }) + + t.Run("ErrorGettingZone", func(t *testing.T) { + err = handler.handle("garden/data/water", []byte("water,zone=1 millis=6000")) + require.Error(t, err) + require.Equal(t, "error getting zone with position 1: no zone found", err.Error()) + }) + + t.Run("ErrorUsingPushover", func(t *testing.T) { + r, err := recorder.New("testdata/fixtures/pushover_fail") + if err != nil { + t.Fatal(err) + } + defer func() { + require.NoError(t, r.Stop()) + }() + + if r.Mode() != recorder.ModeRecordOnce { + t.Fatal("Recorder should be in ModeRecordOnce") + } + + // github.com/gregdel/pushover uses http.DefaultClient + http.DefaultClient = r.GetDefaultClient() + + err = handler.handle("garden/data/water", []byte("water,zone=0 millis=6000")) + require.Error(t, err) + require.Equal(t, "Errors:\napplication token is invalid, see https://pushover.net/api", err.Error()) + }) + + t.Run("Success", func(t *testing.T) { + r, err := recorder.New("testdata/fixtures/pushover_success") + if err != nil { + t.Fatal(err) + } + defer func() { + require.NoError(t, r.Stop()) + }() + + if r.Mode() != recorder.ModeRecordOnce { + t.Fatal("Recorder should be in ModeRecordOnce") + } + + numMessages := 0 + r.AddHook(func(i *cassette.Interaction) error { + if i.Request.URL == "https://api.pushover.net/1/messages.json" { + numMessages++ + } + return nil + }, recorder.BeforeResponseReplayHook) + + // github.com/gregdel/pushover uses http.DefaultClient + http.DefaultClient = r.GetDefaultClient() + + err = handler.handle("garden/data/water", []byte("water,zone=0 millis=6000")) + require.NoError(t, err) + + // ensure a message is sent by API + require.Equal(t, 1, numMessages) + }) } diff --git a/garden-app/worker/notifications.go b/garden-app/worker/notifications.go index 4735ecf7..e890253d 100644 --- a/garden-app/worker/notifications.go +++ b/garden-app/worker/notifications.go @@ -10,12 +10,12 @@ import ( ) func (w *Worker) sendLightActionNotification(g *pkg.Garden, state pkg.LightState, logger *slog.Logger) { - if g.LightSchedule.GetNotificationClientID() == "" { + if g.GetNotificationClientID() == "" { return } title := fmt.Sprintf("%s: Light %s", g.Name, state.String()) - w.sendNotification(g.LightSchedule.GetNotificationClientID(), title, "Successfully executed LightAction", logger) + w.sendNotification(g.GetNotificationClientID(), title, "Successfully executed LightAction", logger) } func (w *Worker) sendDownNotification(g *pkg.Garden, clientID, actionName string) { diff --git a/garden-app/worker/scheduler.go b/garden-app/worker/scheduler.go index ced889d2..e9f5fc2c 100644 --- a/garden-app/worker/scheduler.go +++ b/garden-app/worker/scheduler.go @@ -481,8 +481,8 @@ func (w *Worker) executeLightActionInScheduledJob(g *pkg.Garden, input *action.L actionLogger = actionLogger.With("state", input.State.String()) actionLogger.Info("executing LightAction") - if g.LightSchedule.GetNotificationClientID() != "" { - w.sendDownNotification(g, g.LightSchedule.GetNotificationClientID(), "Light") + if g.GetNotificationClientID() != "" { + w.sendDownNotification(g, g.GetNotificationClientID(), "Light") } err := w.ExecuteLightAction(g, input) @@ -490,8 +490,8 @@ func (w *Worker) executeLightActionInScheduledJob(g *pkg.Garden, input *action.L actionLogger.Error("error executing scheduled LightAction", "error", err) schedulerErrors.WithLabelValues(gardenLabels(g)...).Inc() - if g.LightSchedule.GetNotificationClientID() != "" { - w.sendNotification(g.LightSchedule.GetNotificationClientID(), fmt.Sprintf("%s: Light Action Error", g.Name), err.Error(), actionLogger) + if g.GetNotificationClientID() != "" { + w.sendNotification(g.GetNotificationClientID(), fmt.Sprintf("%s: Light Action Error", g.Name), err.Error(), actionLogger) } return } diff --git a/garden-app/worker/scheduler_test.go b/garden-app/worker/scheduler_test.go index f86f0d25..6ee082ab 100644 --- a/garden-app/worker/scheduler_test.go +++ b/garden-app/worker/scheduler_test.go @@ -677,7 +677,7 @@ func TestScheduleLightActions(t *testing.T) { g.LightSchedule.Duration = &pkg.Duration{Duration: time.Second} if tt.enableNotification { ncID := notificationClient.GetID() - g.LightSchedule.NotificationClientID = &ncID + g.NotificationClientID = &ncID } err = worker.ScheduleLightActions(g) @@ -758,7 +758,7 @@ func TestScheduleLightActions(t *testing.T) { g.LightSchedule.StartTime = pkg.NewStartTime(later) g.LightSchedule.Duration = &pkg.Duration{Duration: time.Second} ncID := notificationClient.GetID() - g.LightSchedule.NotificationClientID = &ncID + g.NotificationClientID = &ncID err = worker.ScheduleLightActions(g) assert.NoError(t, err)