From 567476d952c27724e167b5d9008cb09f9c2c6ae6 Mon Sep 17 00:00:00 2001 From: Dave Shepherd Date: Wed, 19 Dec 2018 11:09:19 +0000 Subject: [PATCH 1/4] Ignore response from ingress creation in tests as it contains metadata that can cause the update to fail due to internal modification. I was frequently getting tests failing with the following error because the "ResourceVersion" was different and I didn't see the need to amend the response when the tests were just modifying the annotations for the original ingress created immediately above, so resubmitting the original version with the minor modification seems acceptable to me. panic: Operation cannot be fulfilled on ingresses.extensions "ingress-imc-rpsmo": the object has been modified; please apply your changes to the latest version and try again --- pkg/controller/controller_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go index 36a809c7..6824661b 100644 --- a/pkg/controller/controller_test.go +++ b/pkg/controller/controller_test.go @@ -220,7 +220,7 @@ func TestUpdateIngressWithAnnotationDisabledShouldNotCreateMonitor(t *testing.T) ingress := util.CreateIngressObject(ingressName, namespace, url) - ingress, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) + _, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) if err != nil { panic(err) @@ -348,7 +348,7 @@ func TestUpdateIngressWithAnnotationEnabledShouldCreateMonitorAndDelete(t *testi ingress := util.CreateIngressObject(ingressName, namespace, url) - ingress, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) + _, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) if err != nil { panic(err) @@ -397,7 +397,7 @@ func TestUpdateIngressWithAnnotationFromEnabledToDisabledShouldDeleteMonitor(t * ingress = addMonitorAnnotationToIngress(ingress, true) - ingress, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) + _, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) if err != nil { panic(err) @@ -447,7 +447,7 @@ func TestUpdateIngressWithNewURLShouldUpdateMonitor(t *testing.T) { ingress = addMonitorAnnotationToIngress(ingress, true) - ingress, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) + _, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) if err != nil { panic(err) @@ -517,7 +517,7 @@ func TestUpdateIngressWithEnabledAnnotationShouldCreateMonitorAndDelete(t *testi ingress = addMonitorAnnotationToIngress(ingress, false) - ingress, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) + _, err := controller.kubeClient.ExtensionsV1beta1().Ingresses(namespace).Create(ingress) if err != nil { panic(err) From 6d66a1cc459f7cfbae3c35f62a6e6aa9cabe52dc Mon Sep 17 00:00:00 2001 From: Dave Shepherd Date: Wed, 19 Dec 2018 16:21:54 +0000 Subject: [PATCH 2/4] Introduce interval annotation for uptime robot --- docs/uptimerobot-configuration.md | 10 ++- pkg/monitors/uptimerobot/uptime-mappers.go | 5 ++ .../uptimerobot/uptime-mappers_test.go | 17 +++-- pkg/monitors/uptimerobot/uptime-monitor.go | 8 +++ .../uptimerobot/uptime-monitor_test.go | 64 +++++++++++++++++++ 5 files changed, 98 insertions(+), 6 deletions(-) diff --git a/docs/uptimerobot-configuration.md b/docs/uptimerobot-configuration.md index 0504a245..6c1d70aa 100644 --- a/docs/uptimerobot-configuration.md +++ b/docs/uptimerobot-configuration.md @@ -29,4 +29,12 @@ You will get a response similar to what is shown below ] ``` -Copy values of `id` field of your alert contacts which you want to use for Ingress Monitor Controller and append `_0_0` to them and seperate them by `-`. You will now have a string similar to `12345_0_0-23564_0_0`. This is basically the value you will need to specify in Ingress Monitor Controller's ConfigMap as `alertContacts`. \ No newline at end of file +Copy values of `id` field of your alert contacts which you want to use for Ingress Monitor Controller and append `_0_0` to them and seperate them by `-`. You will now have a string similar to `12345_0_0-23564_0_0`. This is basically the value you will need to specify in Ingress Monitor Controller's ConfigMap as `alertContacts`. + +## Annotations + +Additional uptime robot configurations can be added through a set of annotations to each ingress object, the current supported annotations are: + +| Annotation | Description | +|:-----------------------------------------:|:-----------------------------------------:| +| uptimerobot.monitor.stakater.com/interval | The uptimerobot check interval in minutes | diff --git a/pkg/monitors/uptimerobot/uptime-mappers.go b/pkg/monitors/uptimerobot/uptime-mappers.go index 63d85ef5..9618d636 100644 --- a/pkg/monitors/uptimerobot/uptime-mappers.go +++ b/pkg/monitors/uptimerobot/uptime-mappers.go @@ -13,6 +13,11 @@ func UptimeMonitorMonitorToBaseMonitorMapper(uptimeMonitor UptimeMonitorMonitor) m.URL = uptimeMonitor.URL m.ID = strconv.Itoa(uptimeMonitor.ID) + var annotations = map[string]string { + "uptimerobot.monitor.stakater.com/interval": strconv.Itoa(uptimeMonitor.Interval), + } + m.Annotations = annotations + return &m } diff --git a/pkg/monitors/uptimerobot/uptime-mappers_test.go b/pkg/monitors/uptimerobot/uptime-mappers_test.go index c79d4e82..8d2f0498 100644 --- a/pkg/monitors/uptimerobot/uptime-mappers_test.go +++ b/pkg/monitors/uptimerobot/uptime-mappers_test.go @@ -9,20 +9,27 @@ import ( ) func TestUptimeMonitorMonitorToBaseMonitorMapper(t *testing.T) { - uptimeMonitorObject := UptimeMonitorMonitor{FriendlyName: "Test Monitor", ID: 124, URL: "https://stakater.com"} + uptimeMonitorObject := UptimeMonitorMonitor{FriendlyName: "Test Monitor", ID: 124, URL: "https://stakater.com", Interval: 900} monitorObject := UptimeMonitorMonitorToBaseMonitorMapper(uptimeMonitorObject) - if monitorObject.ID != strconv.Itoa(uptimeMonitorObject.ID) || monitorObject.Name != uptimeMonitorObject.FriendlyName || monitorObject.URL != uptimeMonitorObject.URL { + if monitorObject.ID != strconv.Itoa(uptimeMonitorObject.ID) || monitorObject.Name != uptimeMonitorObject.FriendlyName || monitorObject.URL != uptimeMonitorObject.URL || "900" != monitorObject.Annotations["uptimerobot.monitor.stakater.com/interval"] { t.Error("Mapper did not map the values correctly") } } func TestUptimeMonitorMonitorsToBaseMonitorsMapper(t *testing.T) { - uptimeMonitorObject1 := UptimeMonitorMonitor{FriendlyName: "Test Monitor 1", ID: 124, URL: "https://stakater.com"} - uptimeMonitorObject2 := UptimeMonitorMonitor{FriendlyName: "Test Monitor 2", ID: 125, URL: "https://stackator.com"} + uptimeMonitorObject1 := UptimeMonitorMonitor{FriendlyName: "Test Monitor 1", ID: 124, URL: "https://stakater.com", Interval: 900} + uptimeMonitorObject2 := UptimeMonitorMonitor{FriendlyName: "Test Monitor 2", ID: 125, URL: "https://stackator.com", Interval: 600} - correctMonitors := []models.Monitor{models.Monitor{Name: "Test Monitor 1", ID: "124", URL: "https://stakater.com"}, models.Monitor{Name: "Test Monitor 2", ID: "125", URL: "https://stackator.com"}} + var annotations1 = map[string]string { + "uptimerobot.monitor.stakater.com/interval": "900", + } + var annotations2 = map[string]string { + "uptimerobot.monitor.stakater.com/interval": "600", + } + + correctMonitors := []models.Monitor{models.Monitor{Name: "Test Monitor 1", ID: "124", URL: "https://stakater.com", Annotations: annotations1}, models.Monitor{Name: "Test Monitor 2", ID: "125", URL: "https://stackator.com", Annotations: annotations2}} var uptimeMonitors []UptimeMonitorMonitor uptimeMonitors = append(uptimeMonitors, uptimeMonitorObject1) diff --git a/pkg/monitors/uptimerobot/uptime-monitor.go b/pkg/monitors/uptimerobot/uptime-monitor.go index e002ac9c..aed6a937 100644 --- a/pkg/monitors/uptimerobot/uptime-monitor.go +++ b/pkg/monitors/uptimerobot/uptime-monitor.go @@ -85,6 +85,10 @@ func (monitor *UpTimeMonitorService) Add(m models.Monitor) { body := "api_key=" + monitor.apiKey + "&format=json&type=1&url=" + url.QueryEscape(m.URL) + "&friendly_name=" + url.QueryEscape(m.Name) + "&alert_contacts=" + monitor.alertContacts + if val, ok := m.Annotations["uptimerobot.monitor.stakater.com/interval"]; ok { + body += "&interval=" + val + } + response := client.PostUrlEncodedFormBody(body) if response.StatusCode == 200 { @@ -108,6 +112,10 @@ func (monitor *UpTimeMonitorService) Update(m models.Monitor) { body := "api_key=" + monitor.apiKey + "&format=json&id=" + m.ID + "&friendly_name=" + m.Name + "&url=" + m.URL + if val, ok := m.Annotations["uptimerobot.monitor.stakater.com/interval"]; ok { + body += "&interval=" + val + } + response := client.PostUrlEncodedFormBody(body) if response.StatusCode == 200 { diff --git a/pkg/monitors/uptimerobot/uptime-monitor_test.go b/pkg/monitors/uptimerobot/uptime-monitor_test.go index 6f0dd0e7..6eeb478d 100644 --- a/pkg/monitors/uptimerobot/uptime-monitor_test.go +++ b/pkg/monitors/uptimerobot/uptime-monitor_test.go @@ -61,6 +61,70 @@ func TestUpdateMonitorWithCorrectValues(t *testing.T) { service.Remove(*mRes) } +func TestAddMonitorWithAnnotations(t *testing.T) { + config := config.GetControllerConfig() + + service := UpTimeMonitorService{} + service.Setup(config.Providers[0]) + + var annotations = map[string]string { + "uptimerobot.monitor.stakater.com/interval": "600", + } + + m := models.Monitor{Name: "google-test", URL: "https://google.com", Annotations: annotations} + service.Add(m) + + mRes, err := service.GetByName("google-test") + + if err != nil { + t.Error("Error: " + err.Error()) + } + if mRes.Name != m.Name || mRes.URL != m.URL || "600" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { + t.Error("URL, name and interval should be the same") + } + service.Remove(*mRes) +} + +func TestUpdateMonitorAnnotations(t *testing.T) { + config := config.GetControllerConfig() + + service := UpTimeMonitorService{} + service.Setup(config.Providers[0]) + + var annotations = map[string]string { + "uptimerobot.monitor.stakater.com/interval": "600", + } + + m := models.Monitor{Name: "google-test", URL: "https://google.com", Annotations: annotations} + service.Add(m) + + mRes, err := service.GetByName("google-test") + + if err != nil { + t.Error("Error: " + err.Error()) + } + if mRes.Name != m.Name || mRes.URL != m.URL || "600" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { + t.Error("URL, name and interval should be the same") + } + + mRes.URL = "https://facebook.com" + annotations["uptimerobot.monitor.stakater.com/interval"] = "900" + mRes.Annotations = annotations + + service.Update(*mRes) + + mRes, err = service.GetByName("google-test") + + if err != nil { + t.Error("Error: " + err.Error()) + } + if mRes.URL != "https://facebook.com" || "900" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { + t.Error("URL and interval should be the same.") + } + + service.Remove(*mRes) +} + func TestAddMonitorWithIncorrectValues(t *testing.T) { config := config.GetControllerConfig() From dd57a2489367a925bad4a8822953afe83c65863a Mon Sep 17 00:00:00 2001 From: Dave Shepherd Date: Fri, 21 Dec 2018 13:25:06 +0000 Subject: [PATCH 3/4] Improve uptime monitor test output to help diagnose failures --- .../uptimerobot/uptime-monitor_test.go | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/pkg/monitors/uptimerobot/uptime-monitor_test.go b/pkg/monitors/uptimerobot/uptime-monitor_test.go index 6eeb478d..3bb86273 100644 --- a/pkg/monitors/uptimerobot/uptime-monitor_test.go +++ b/pkg/monitors/uptimerobot/uptime-monitor_test.go @@ -21,8 +21,11 @@ func TestAddMonitorWithCorrectValues(t *testing.T) { if err != nil { t.Error("Error: " + err.Error()) } - if mRes.Name != m.Name || mRes.URL != m.URL { - t.Error("URL and name should be the same") + if mRes.Name != m.Name { + t.Error("The name is incorrect, expected: " + m.Name + ", but was: " + mRes.Name) + } + if mRes.URL != m.URL { + t.Error("The URL is incorrect, expected: " + m.URL + ", but was: " + mRes.URL) } service.Remove(*mRes) } @@ -41,8 +44,11 @@ func TestUpdateMonitorWithCorrectValues(t *testing.T) { if err != nil { t.Error("Error: " + err.Error()) } - if mRes.Name != m.Name || mRes.URL != m.URL { - t.Error("URL and name should be the same") + if mRes.Name != m.Name { + t.Error("The initial name is incorrect, expected: " + m.Name + ", but was: " + mRes.Name) + } + if mRes.URL != m.URL { + t.Error("The initial URL is incorrect, expected: " + m.URL + ", but was: " + mRes.URL) } mRes.URL = "https://facebook.com" @@ -55,7 +61,7 @@ func TestUpdateMonitorWithCorrectValues(t *testing.T) { t.Error("Error: " + err.Error()) } if mRes.URL != "https://facebook.com" { - t.Error("URL and name should be the same") + t.Error("The URL should have been updated, expected: https://facebook.com, but was: " + mRes.URL) } service.Remove(*mRes) @@ -79,8 +85,14 @@ func TestAddMonitorWithAnnotations(t *testing.T) { if err != nil { t.Error("Error: " + err.Error()) } - if mRes.Name != m.Name || mRes.URL != m.URL || "600" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { - t.Error("URL, name and interval should be the same") + if mRes.Name != m.Name { + t.Error("The name is incorrect, expected: " + m.Name + ", but was: " + mRes.Name) + } + if mRes.URL != m.URL { + t.Error("The URL is incorrect, expected: " + m.URL + ", but was: " + mRes.URL) + } + if "600" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { + t.Error("The interval is incorrect, expected: 600, but was: " + mRes.Annotations["uptimerobot.monitor.stakater.com/interval"]) } service.Remove(*mRes) } @@ -103,8 +115,14 @@ func TestUpdateMonitorAnnotations(t *testing.T) { if err != nil { t.Error("Error: " + err.Error()) } - if mRes.Name != m.Name || mRes.URL != m.URL || "600" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { - t.Error("URL, name and interval should be the same") + if mRes.Name != m.Name { + t.Error("The initial name is incorrect, expected: " + m.Name + ", but was: " + mRes.Name) + } + if mRes.URL != m.URL { + t.Error("The initial URL is incorrect, expected: " + m.URL + ", but was: " + mRes.URL) + } + if "600" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { + t.Error("The initial interval is incorrect: 600, but was: " + mRes.Annotations["uptimerobot.monitor.stakater.com/interval"]) } mRes.URL = "https://facebook.com" @@ -118,8 +136,11 @@ func TestUpdateMonitorAnnotations(t *testing.T) { if err != nil { t.Error("Error: " + err.Error()) } - if mRes.URL != "https://facebook.com" || "900" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { - t.Error("URL and interval should be the same.") + if mRes.URL != "https://facebook.com" { + t.Error("The updated URL is incorrect, expected: https://facebook.com, but was: " + mRes.URL) + } + if "900" != mRes.Annotations["uptimerobot.monitor.stakater.com/interval"] { + t.Error("The updated interval is incorrect, expected: 900, but was: " + mRes.Annotations["uptimerobot.monitor.stakater.com/interval"]) } service.Remove(*mRes) From fa65bedcf4623d0bede2008b55923a1c12aac86c Mon Sep 17 00:00:00 2001 From: kahootali Date: Thu, 3 Jan 2019 11:09:11 +0500 Subject: [PATCH 4/4] change keyword type to int --- pkg/monitors/uptimerobot/uptime-responses.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/monitors/uptimerobot/uptime-responses.go b/pkg/monitors/uptimerobot/uptime-responses.go index f15e3234..7ad92de9 100644 --- a/pkg/monitors/uptimerobot/uptime-responses.go +++ b/pkg/monitors/uptimerobot/uptime-responses.go @@ -18,7 +18,7 @@ type UptimeMonitorMonitor struct { URL string `json:"url"` Type int `json:"type"` SubType string `json:"sub_type"` - KeywordType string `json:"keyword_type"` + KeywordType int `json:"keyword_type"` KeywordValue string `json:"keyword_value"` HTTPUsername string `json:"http_username"` HTTPPassword string `json:"http_password"`