From 8b4e8a1cca4842c7c5bb94cf3def40d56e174023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Wed, 31 Jan 2018 21:42:02 -0800 Subject: [PATCH 01/15] dep prune is depracated, drop it dep will now run prune based on the Gopkg.toml settings, add a config for it and drop 'dep prune' from the Makefile --- Gopkg.toml | 3 +++ Makefile | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.toml b/Gopkg.toml index 7e7c079b7..c414c74ca 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -19,6 +19,9 @@ # name = "github.com/x/y" # version = "2.4.0" +[prune] + go-tests = true + unused-packages = true [[constraint]] branch = "master" diff --git a/Makefile b/Makefile index 6dc904129..f0416f6ba 100644 --- a/Makefile +++ b/Makefile @@ -56,18 +56,15 @@ $(NAME): .build/deps-build-go.ok .build/vendor.ok bindata_assetfs.go $(SOURCES) .build/vendor.ok: .build/deps-build-go.ok Gopkg.lock Gopkg.toml dep ensure - dep prune touch $@ .PHONY: vendor vendor: .build/deps-build-go.ok dep ensure - dep prune .PHONY: vendor-update vendor-update: .build/deps-build-go.ok dep ensure -update - dep prune .PHONY: webpack webpack: .build/artifacts-webpack.ok From 835797c81b3698cfeca2dbb84dd1f191f1891a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Wed, 31 Jan 2018 21:18:21 -0800 Subject: [PATCH 02/15] Set proxy value when logging configuration on startup --- internal/config/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/config/config.go b/internal/config/config.go index 55c63fab0..d763f3408 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -172,6 +172,7 @@ func (config *configSchema) LogValues() { URI: hideURLPassword(s.URI), Timeout: s.Timeout, TLS: s.TLS, + Proxy: s.Proxy, } servers = append(servers, server) } From e17018339af1a164612d1ce6d5d4aa00552aeccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 13 Feb 2018 22:42:36 +0000 Subject: [PATCH 03/15] Add mock files for Alertmanager 0.14.0 --- Makefile | 2 +- internal/mock/0.14.0/.ok | 0 internal/mock/0.14.0/api/v1/alerts/groups | 765 ++++++++++++++++++++++ internal/mock/0.14.0/api/v1/silences | 64 ++ internal/mock/0.14.0/api/v1/status | 98 +++ internal/mock/Makefile | 2 +- 6 files changed, 929 insertions(+), 2 deletions(-) create mode 100644 internal/mock/0.14.0/.ok create mode 100644 internal/mock/0.14.0/api/v1/alerts/groups create mode 100644 internal/mock/0.14.0/api/v1/silences create mode 100644 internal/mock/0.14.0/api/v1/status diff --git a/Makefile b/Makefile index f0416f6ba..1214e09eb 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ NAME := unsee VERSION := $(shell git describe --tags --always --dirty='-dev') # Alertmanager instance used when running locally, points to mock data -MOCK_PATH := $(CURDIR)/internal/mock/0.13.0 +MOCK_PATH := $(CURDIR)/internal/mock/0.14.0 ALERTMANAGER_URI := "file://$(MOCK_PATH)" # Listen port when running locally PORT := 8080 diff --git a/internal/mock/0.14.0/.ok b/internal/mock/0.14.0/.ok new file mode 100644 index 000000000..e69de29bb diff --git a/internal/mock/0.14.0/api/v1/alerts/groups b/internal/mock/0.14.0/api/v1/alerts/groups new file mode 100644 index 000000000..c46034a7d --- /dev/null +++ b/internal/mock/0.14.0/api/v1/alerts/groups @@ -0,0 +1,765 @@ +{ + "data": [ + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "alert": "Less than 10% disk space is free", + "dashboard": "http://localhost/dashboard.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "f87343c11c74a3f4", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Free_Disk_Space_Too_Low", + "cluster": "staging", + "instance": "server5", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-name", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Free_Disk_Space_Too_Low\"}", + "labels": { + "alertname": "Free_Disk_Space_Too_Low" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "help": "Example help annotation", + "summary": "Example summary", + "url": "http://localhost/example.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "54c2f185e49cfccb", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "HTTP_Probe_Failed", + "cluster": "dev", + "instance": "web1", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "9a32b09e-0c74-4f69-8ad9-600bdcc7b4cc" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "5cb0dd95e7f3d9c0", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "HTTP_Probe_Failed", + "cluster": "dev", + "instance": "web2", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-name", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"HTTP_Probe_Failed\"}", + "labels": { + "alertname": "HTTP_Probe_Failed" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "3bdb8b68bdce2ae0", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "prod", + "instance": "server2", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "24e4121619386f95", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "staging", + "instance": "server3", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "d9067fcc9686d942", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "staging", + "instance": "server4", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "5f1306dab6671183", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "staging", + "instance": "server5", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "0967807e4073b606", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "dev", + "instance": "server6", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "1167d99e-60dd-4576-b514-64cf03891be2" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "44497481566cd3c7", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "dev", + "instance": "server7", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "1167d99e-60dd-4576-b514-64cf03891be2", + "f70e2eae-1d71-497b-9dd1-3d83b30aaf63" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "af9d8f2f0ccb3970", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "dev", + "instance": "server8", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "1167d99e-60dd-4576-b514-64cf03891be2" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary", + "url": "http://localhost/example.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "d0aee2649e71388b", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "prod", + "instance": "server1", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-name", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Host_Down\"}", + "labels": { + "alertname": "Host_Down" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "alert": "Memory usage exceeding threshold", + "dashboard": "http://localhost/dashboard.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "7d0b114ebf24f857", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Memory_Usage_Too_High", + "cluster": "prod", + "instance": "server2", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-name", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Memory_Usage_Too_High\"}", + "labels": { + "alertname": "Memory_Usage_Too_High" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "alert": "Less than 10% disk space is free", + "dashboard": "http://localhost/dashboard.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "f87343c11c74a3f4", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Free_Disk_Space_Too_Low", + "cluster": "staging", + "instance": "server5", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "service", + "alertname", + "cluster" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-cluster-service", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Free_Disk_Space_Too_Low\", cluster=\"staging\"}", + "labels": { + "alertname": "Free_Disk_Space_Too_Low", + "cluster": "staging" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "help": "Example help annotation", + "summary": "Example summary", + "url": "http://localhost/example.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "54c2f185e49cfccb", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "HTTP_Probe_Failed", + "cluster": "dev", + "instance": "web1", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "9a32b09e-0c74-4f69-8ad9-600bdcc7b4cc" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "5cb0dd95e7f3d9c0", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "HTTP_Probe_Failed", + "cluster": "dev", + "instance": "web2", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname", + "cluster", + "service" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-cluster-service", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"HTTP_Probe_Failed\", cluster=\"dev\"}", + "labels": { + "alertname": "HTTP_Probe_Failed", + "cluster": "dev" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "af9d8f2f0ccb3970", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "dev", + "instance": "server8", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "1167d99e-60dd-4576-b514-64cf03891be2" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "0967807e4073b606", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "dev", + "instance": "server6", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "1167d99e-60dd-4576-b514-64cf03891be2" + ], + "state": "suppressed" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "44497481566cd3c7", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "dev", + "instance": "server7", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": null, + "silencedBy": [ + "1167d99e-60dd-4576-b514-64cf03891be2", + "f70e2eae-1d71-497b-9dd1-3d83b30aaf63" + ], + "state": "suppressed" + } + } + ], + "routeOpts": { + "groupBy": [ + "cluster", + "service", + "alertname" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-cluster-service", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Host_Down\", cluster=\"dev\"}", + "labels": { + "alertname": "Host_Down", + "cluster": "dev" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "summary": "Example summary", + "url": "http://localhost/example.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "d0aee2649e71388b", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "prod", + "instance": "server1", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "3bdb8b68bdce2ae0", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "prod", + "instance": "server2", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname", + "cluster", + "service" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-cluster-service", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Host_Down\", cluster=\"prod\"}", + "labels": { + "alertname": "Host_Down", + "cluster": "prod" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "24e4121619386f95", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "staging", + "instance": "server3", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "d9067fcc9686d942", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "staging", + "instance": "server4", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + }, + { + "annotations": { + "summary": "Example summary" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "5f1306dab6671183", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Host_Down", + "cluster": "staging", + "instance": "server5", + "job": "node_ping" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "service", + "alertname", + "cluster" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-cluster-service", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Host_Down\", cluster=\"staging\"}", + "labels": { + "alertname": "Host_Down", + "cluster": "staging" + } + }, + { + "blocks": [ + { + "alerts": [ + { + "annotations": { + "alert": "Memory usage exceeding threshold", + "dashboard": "http://localhost/dashboard.html" + }, + "endsAt": "0001-01-01T00:00:00Z", + "fingerprint": "7d0b114ebf24f857", + "generatorURL": "localhost/prometheus", + "labels": { + "alertname": "Memory_Usage_Too_High", + "cluster": "prod", + "instance": "server2", + "job": "node_exporter" + }, + "receivers": null, + "startsAt": "2018-02-13T22:41:17.691429964Z", + "status": { + "inhibitedBy": [], + "silencedBy": [], + "state": "active" + } + } + ], + "routeOpts": { + "groupBy": [ + "alertname", + "cluster", + "service" + ], + "groupInterval": 35000000000, + "groupWait": 15000000000, + "receiver": "by-cluster-service", + "repeatInterval": 3596400000000000 + } + } + ], + "groupKey": "{}/{alertname=~\"^(?:.*)$\"}:{alertname=\"Memory_Usage_Too_High\", cluster=\"prod\"}", + "labels": { + "alertname": "Memory_Usage_Too_High", + "cluster": "prod" + } + } + ], + "status": "success" +} diff --git a/internal/mock/0.14.0/api/v1/silences b/internal/mock/0.14.0/api/v1/silences new file mode 100644 index 000000000..34f366f06 --- /dev/null +++ b/internal/mock/0.14.0/api/v1/silences @@ -0,0 +1,64 @@ +{ + "data": [ + { + "comment": "Silenced instance", + "createdBy": "john@example.com", + "endsAt": "2063-01-01T00:00:00Z", + "id": "9a32b09e-0c74-4f69-8ad9-600bdcc7b4cc", + "matchers": [ + { + "isRegex": false, + "name": "instance", + "value": "web1" + } + ], + "startsAt": "2018-02-13T22:41:17.682678891Z", + "status": { + "state": "active" + }, + "updatedAt": "2018-02-13T22:41:17.682685244Z" + }, + { + "comment": "Silenced Host_Down alerts in the dev cluster", + "createdBy": "john@example.com", + "endsAt": "2063-01-01T00:00:00Z", + "id": "1167d99e-60dd-4576-b514-64cf03891be2", + "matchers": [ + { + "isRegex": false, + "name": "alertname", + "value": "Host_Down" + }, + { + "isRegex": false, + "name": "cluster", + "value": "dev" + } + ], + "startsAt": "2018-02-13T22:41:17.685938633Z", + "status": { + "state": "active" + }, + "updatedAt": "2018-02-13T22:41:17.685945586Z" + }, + { + "comment": "Silenced server7", + "createdBy": "john@example.com", + "endsAt": "2063-01-01T00:00:00Z", + "id": "f70e2eae-1d71-497b-9dd1-3d83b30aaf63", + "matchers": [ + { + "isRegex": false, + "name": "instance", + "value": "server7" + } + ], + "startsAt": "2018-02-13T22:41:17.688769461Z", + "status": { + "state": "active" + }, + "updatedAt": "2018-02-13T22:41:17.68877405Z" + } + ], + "status": "success" +} diff --git a/internal/mock/0.14.0/api/v1/status b/internal/mock/0.14.0/api/v1/status new file mode 100644 index 000000000..461935efb --- /dev/null +++ b/internal/mock/0.14.0/api/v1/status @@ -0,0 +1,98 @@ +{ + "data": { + "configJSON": { + "global": { + "hipchat_api_url": "https://api.hipchat.com/", + "opsgenie_api_url": "https://api.opsgenie.com/", + "pagerduty_url": "https://events.pagerduty.com/v2/enqueue", + "resolve_timeout": 300000000000, + "smtp_require_tls": true, + "victorops_api_url": "https://alert.victorops.com/integrations/generic/20131114/alert/", + "wechat_api_url": "https://qyapi.weixin.qq.com/cgi-bin/" + }, + "inhibit_rules": [ + { + "equal": [ + "alertname", + "cluster", + "service" + ], + "source_match": { + "severity": "critical" + }, + "target_match": { + "severity": "warning" + } + } + ], + "receivers": [ + { + "name": "default" + }, + { + "name": "by-cluster-service" + }, + { + "name": "by-name" + } + ], + "route": { + "group_by": [ + "alertname" + ], + "group_interval": 35000000000, + "group_wait": 15000000000, + "receiver": "default", + "repeat_interval": 3596400000000000, + "routes": [ + { + "continue": true, + "group_by": [ + "alertname", + "cluster", + "service" + ], + "match_re": { + "alertname": "^(?:.*)$" + }, + "receiver": "by-cluster-service" + }, + { + "continue": true, + "group_by": [ + "alertname" + ], + "match_re": { + "alertname": "^(?:.*)$" + }, + "receiver": "by-name" + } + ] + }, + "templates": null + }, + "configYAML": "global:\n resolve_timeout: 5m\n smtp_require_tls: true\n pagerduty_url: https://events.pagerduty.com/v2/enqueue\n hipchat_api_url: https://api.hipchat.com/\n opsgenie_api_url: https://api.opsgenie.com/\n wechat_api_url: https://qyapi.weixin.qq.com/cgi-bin/\n victorops_api_url: https://alert.victorops.com/integrations/generic/20131114/alert/\nroute:\n receiver: default\n group_by:\n - alertname\n routes:\n - receiver: by-cluster-service\n group_by:\n - alertname\n - cluster\n - service\n match_re:\n alertname: ^(?:.*)$\n continue: true\n - receiver: by-name\n group_by:\n - alertname\n match_re:\n alertname: ^(?:.*)$\n continue: true\n group_wait: 15s\n group_interval: 35s\n repeat_interval: 999h\ninhibit_rules:\n- source_match:\n severity: critical\n target_match:\n severity: warning\n equal:\n - alertname\n - cluster\n - service\nreceivers:\n- name: default\n- name: by-cluster-service\n- name: by-name\ntemplates: []\n", + "meshStatus": { + "connections": [], + "name": "02:42:ac:11:00:02", + "nickName": "f5aa481fb869", + "peers": [ + { + "name": "02:42:ac:11:00:02", + "nickName": "f5aa481fb869", + "uid": 10095986928128251540 + } + ] + }, + "uptime": "2018-02-13T22:41:02.274924341Z", + "versionInfo": { + "branch": "HEAD", + "buildDate": "20180213-08:16:42", + "buildUser": "root@37b6a49ebba9", + "goVersion": "go1.9.2", + "revision": "30af4d051b37ce817ea7e35b56c57a0e2ec9dbb0", + "version": "0.14.0" + } + }, + "status": "success" +} diff --git a/internal/mock/Makefile b/internal/mock/Makefile index 658f9d344..31671197b 100644 --- a/internal/mock/Makefile +++ b/internal/mock/Makefile @@ -3,7 +3,7 @@ DOCKER_IMAGE := prom/alertmanager DOCKER_ARGS := --name $(DOCKER_NAME) --rm -d -p 9093:9093 -v $(CURDIR)/alertmanager.yml:/etc/alertmanager/config.yml # list of Alertmanager versions to generate mock files for -VERSIONS := 0.4.0 0.4.1 0.4.2 0.5.0 0.5.1 0.6.0 0.6.2 0.7.0 0.7.1 0.8.0 0.9.0 0.9.1 0.10.0 0.11.0 0.12.0 0.13.0 +VERSIONS := 0.4.0 0.4.1 0.4.2 0.5.0 0.5.1 0.6.0 0.6.2 0.7.0 0.7.1 0.8.0 0.9.0 0.9.1 0.10.0 0.11.0 0.12.0 0.13.0 0.14.0 %/.ok: livemock.py $(eval VERSION := $(word 1, $(subst /, ,$@))) From 286f0f59ff2b4942622975a15f6a715acd782ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Fri, 16 Feb 2018 21:42:14 +0000 Subject: [PATCH 04/15] Use Go 1.10 Use Go 1.10 when testing/releasing on Travis and building docker images --- .travis.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2654a85bf..3b53278da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ defaults_go: &DEFAULTS_GO language: go - go: "1.9.2" + go: "1.10" cache: directories: - vendor diff --git a/Dockerfile b/Dockerfile index 679402480..076ea0ffc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ RUN apk add --update make git COPY . /unsee RUN make -C /unsee webpack -FROM golang:1.9.2-alpine3.6 as go-builder +FROM golang:1.10-alpine as go-builder COPY --from=nodejs-builder /unsee /go/src/github.com/cloudflare/unsee ARG VERSION RUN apk add --update make git From 93c0fbe2846dc4bd6561c9f8e90cb8096e963e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Mon, 5 Mar 2018 18:47:30 -0800 Subject: [PATCH 05/15] Upgrade moment to >2.19.3 CVE-2017-18214 affects <2.19.3, fixes #244 --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index f783bf587..d9c425a67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2281,7 +2281,7 @@ "requires": { "bootstrap": "3.3.7", "jquery": "3.2.1", - "moment": "2.19.1", + "moment": "2.21.0", "moment-timezone": "0.4.1" } }, @@ -6322,16 +6322,16 @@ "dev": true }, "moment": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz", - "integrity": "sha1-VtoaLRy/AdOLfhr8McELz6GSkWc=" + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", + "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==" }, "moment-timezone": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.4.1.tgz", "integrity": "sha1-gfWYw61eIs2teWtn7NjYjQ9bqgY=", "requires": { - "moment": "2.19.1" + "moment": "2.21.0" } }, "ms": { diff --git a/package.json b/package.json index 905ef95c6..3b5ecfe8b 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "loaders.css": "^0.1.2", "lru": "^3.1.0", "masonry-layout": "^4.2.0", - "moment": "^2.19.1", + "moment": "^2.21.0", "nprogress": "^0.2.0", "raven-js": "^3.19.1", "underscore": "^1.8.3" From 62555df1b0b61da8a97c65f81ba3bad618fa9c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Sat, 3 Mar 2018 14:05:49 -0800 Subject: [PATCH 06/15] Use the correct variable in tests 'es.JiraURL == es.JiraURL' is always true, it should compare es with gs. Fix it and reformat for readability --- api_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api_test.go b/api_test.go index dd7b0455a..08fe1d619 100644 --- a/api_test.go +++ b/api_test.go @@ -870,7 +870,10 @@ func testAlert(version string, t *testing.T, expectedAlert, gotAlert models.Aler for _, es := range expectedAM.Silences { foundSilence := false for _, gs := range gotAM.Silences { - if es.Comment == gs.Comment && es.CreatedBy == gs.CreatedBy && es.JiraID == gs.JiraID && es.JiraURL == es.JiraURL { + if es.Comment == gs.Comment && + es.CreatedBy == gs.CreatedBy && + es.JiraID == gs.JiraID && + es.JiraURL == gs.JiraURL { foundSilence = true } } From 131e8e2c93910542c24b1121a797753390650343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Sat, 3 Mar 2018 14:06:08 -0800 Subject: [PATCH 07/15] Comment out dead condition --- api_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api_test.go b/api_test.go index 08fe1d619..61e0d3d64 100644 --- a/api_test.go +++ b/api_test.go @@ -894,11 +894,11 @@ func testAlert(version string, t *testing.T, expectedAlert, gotAlert models.Aler } func testAlertGroup(version string, t *testing.T, testCase groupTest, group models.AlertGroup) { - if testCase.hash != group.Hash { - // FIXME this is different per mock version due to startsAt / endsAt - // t.Errorf("[%s] Alert group.Hash mismatch, expected '%s' but got '%s' for group %v", - // version, testCase.hash, group.Hash, group.Labels) - } + //if testCase.hash != group.Hash { + // FIXME this is different per mock version due to startsAt / endsAt + // t.Errorf("[%s] Alert group.Hash mismatch, expected '%s' but got '%s' for group %v", + // version, testCase.hash, group.Hash, group.Labels) + //} if testCase.id != group.ID { t.Errorf("[%s] Alert group.ID mismatch, expected '%s' but got '%s' for group %v", version, testCase.id, group.ID, group.Labels) From f5c91f48daf96d992f638523d9f882986a0d0b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Fri, 9 Mar 2018 18:43:16 -0800 Subject: [PATCH 08/15] Add CODEOWNERS file CODEOWNERS allows github to automatically require code review from the right set of people. Start with defaulting to myself for all files --- docs/CODEOWNERS | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/CODEOWNERS diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS new file mode 100644 index 000000000..010b4c280 --- /dev/null +++ b/docs/CODEOWNERS @@ -0,0 +1,5 @@ +# CODEOWNERS file lists people and teams responsible for code in this +# repository. +# See https://help.github.com/articles/about-codeowners/ for details. + +* @prymitive From dc58c26b9063f53fae206651e1bd7e266ef7a35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Thu, 29 Mar 2018 22:27:03 -0700 Subject: [PATCH 09/15] Fix silence borders There's an extra layer of transparent border and padding makes the green side to be missing a few pixels, correct that --- assets/static/base.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/static/base.css b/assets/static/base.css index cc740ddb5..046908821 100644 --- a/assets/static/base.css +++ b/assets/static/base.css @@ -250,15 +250,19 @@ blockquote.silence-comment { margin-bottom: 2px; padding-left: 0; padding-right: 2px; - padding-top: 2px; + padding-top: 0; padding-bottom: 0; } +.silence-block.well { + border: 0; +} /* button is an icon inside a well, it gets white color make it dark gray by default, so it's visible but doesn't stand out and black on hover */ button.silence-delete { color: inherit; + margin-top: 2px; } button.silence-delete:hover, button.silence-delete:focus { From 4debfd35600b5d5f7ff98aafd2373f8d66ff32bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Thu, 29 Mar 2018 22:34:00 -0700 Subject: [PATCH 10/15] Save space between alert groups --- assets/static/base.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/static/base.css b/assets/static/base.css index 046908821..b4dfd56eb 100644 --- a/assets/static/base.css +++ b/assets/static/base.css @@ -274,7 +274,7 @@ button.silence-delete:focus { } .incident { - padding: 8px; + padding: 5px; } .incident>.panel>.panel-heading { From 24933bc93a57fd0b5d2c2524252f5b0c3e72cc57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20M=C3=BCller?= Date: Tue, 17 Apr 2018 18:14:55 +0200 Subject: [PATCH 11/15] Remove Host header attribute from proxied request (#252) Explicitly set hostame for proxied requests --- proxy.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proxy.go b/proxy.go index a8e26d93f..2aca36a90 100644 --- a/proxy.go +++ b/proxy.go @@ -35,6 +35,10 @@ func NewAlertmanagerProxy(alertmanager *alertmanager.Alertmanager) (*httputil.Re // upstream, there's a gzip middleware that's global so we don't want it // to gzip twice req.Header.Del("Accept-Encoding") + + // set hostname of proxied target + req.Host = upstreamURL.Host + log.Debugf("[%s] Proxy request for %s", alertmanager.Name, req.URL.Path) }, Transport: alertmanager.HTTPTransport, From 3d378c08dfb326628ee39eb16621b9807f390091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Mon, 16 Apr 2018 15:59:40 -0700 Subject: [PATCH 12/15] Ensure that go-bindata-assetfs creates the expected fine There was a recent change in go-bindata-assetfs that causes the default filename to be bindata.go rather than expected bindata_assetfs.go, pass '-o bindata_assetfs' to ensure we always create the expected file --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1214e09eb..2016ae385 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ endif touch $@ bindata_assetfs.go: .build/deps-build-go.ok .build/artifacts-bindata_assetfs.$(GO_BINDATA_MODE) .build/vendor.ok .build/artifacts-webpack.ok - go-bindata-assetfs $(GO_BINDATA_FLAGS) -prefix assets -nometadata assets/templates/... assets/static/dist/... + go-bindata-assetfs $(GO_BINDATA_FLAGS) -o bindata_assetfs.go -prefix assets -nometadata assets/templates/... assets/static/dist/... $(NAME): .build/deps-build-go.ok .build/vendor.ok bindata_assetfs.go $(SOURCES) go build -ldflags "-X main.version=$(VERSION)" From ed594f368ff40a2bc6c37e27bd2640a41b57bf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 17 Apr 2018 21:52:16 -0700 Subject: [PATCH 13/15] Add more tests for Alertmanager proxy support Those will check if we pass correct Host headers and Basic Auth info --- proxy_test.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/proxy_test.go b/proxy_test.go index 330bcc279..0d099413e 100644 --- a/proxy_test.go +++ b/proxy_test.go @@ -123,3 +123,92 @@ func TestProxy(t *testing.T) { } } } + +type proxyHeaderTest struct { + method string + localPath string + upstreamURI string + code int + alertmanagerURI string + alertmanagerHost string + authUser string + authPass string +} + +var proxyHeaderTests = []proxyHeaderTest{ + { + method: "POST", + localPath: "/proxy/alertmanager/dummy/api/v1/silences", + upstreamURI: "http://localhost:9093/api/v1/silences", + code: 200, + alertmanagerURI: "http://localhost:9093", + alertmanagerHost: "localhost:9093", + }, + { + method: "POST", + localPath: "/proxy/alertmanager/dummy/api/v1/silences", + upstreamURI: "http://alertmanager.example.com/api/v1/silences", + code: 200, + alertmanagerURI: "http://alertmanager.example.com", + alertmanagerHost: "alertmanager.example.com", + }, + { + method: "POST", + localPath: "/proxy/alertmanager/dummy/api/v1/silences", + upstreamURI: "http://alertmanager.example.com/api/v1/silences", + code: 200, + alertmanagerURI: "http://foo:bar@alertmanager.example.com", + alertmanagerHost: "alertmanager.example.com", + authUser: "foo", + authPass: "bar", + }, +} + +func TestProxyHeaders(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + for _, testCase := range proxyHeaderTests { + r := ginTestEngine() + am, err := alertmanager.NewAlertmanager( + "dummy", + testCase.alertmanagerURI, + alertmanager.WithRequestTimeout(time.Second*5), + alertmanager.WithProxy(true), + ) + if err != nil { + t.Error(err) + } + setupRouterProxyHandlers(r, am) + + httpmock.Reset() + httpmock.RegisterResponder(testCase.method, testCase.upstreamURI, func(req *http.Request) (*http.Response, error) { + if req.Host != testCase.alertmanagerHost { + t.Errorf("req.Host is '%s' while '%s' was expected", req.Host, testCase.alertmanagerHost) + } + if req.Header.Get("Host") != "" { + t.Errorf("req.Header.Host is '%s' while '%s' was expected", req.Header.Get("Host"), testCase.alertmanagerHost) + } + if testCase.authUser != "" || testCase.authPass != "" { + user, password, _ := req.BasicAuth() + if testCase.authUser != "" && testCase.authUser != user { + t.Errorf("%s %s proxied to %s was expected to have Basic Auth user '%s', got '%s'", + testCase.method, testCase.localPath, testCase.upstreamURI, testCase.authUser, user) + } + if testCase.authPass != "" && testCase.authPass != password { + t.Errorf("%s %s proxied to %s was expected to have Basic Auth password '%s', got '%s'", + testCase.method, testCase.localPath, testCase.upstreamURI, testCase.authPass, password) + } + } + return httpmock.NewStringResponse(testCase.code, "ok"), nil + }) + + req, _ := http.NewRequest(testCase.method, testCase.localPath, nil) + resp := newCloseNotifyingRecorder() + r.ServeHTTP(resp, req) + if resp.Code != testCase.code { + t.Errorf("%s %s proxied to %s returned status %d while %d was expected", + testCase.method, testCase.localPath, testCase.upstreamURI, resp.Code, testCase.code) + } + } +} From 0fd2ec204378026484d9df2b749b6e2c306670b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 17 Apr 2018 21:52:50 -0700 Subject: [PATCH 14/15] Set Basic Auth on proxied requests if user:pass is set in the Alertmanager URI --- proxy.go | 7 +++++++ proxy_test.go | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/proxy.go b/proxy.go index 2aca36a90..4d3b43173 100644 --- a/proxy.go +++ b/proxy.go @@ -31,6 +31,13 @@ func NewAlertmanagerProxy(alertmanager *alertmanager.Alertmanager) (*httputil.Re Director: func(req *http.Request) { req.URL.Scheme = upstreamURL.Scheme req.URL.Host = upstreamURL.Host + + if upstreamURL.User.Username() != "" { + username := upstreamURL.User.Username() + password, _ := upstreamURL.User.Password() + req.SetBasicAuth(username, password) + } + // drop Accept-Encoding header so we always get uncompressed reponses from // upstream, there's a gzip middleware that's global so we don't want it // to gzip twice diff --git a/proxy_test.go b/proxy_test.go index 0d099413e..813140e3e 100644 --- a/proxy_test.go +++ b/proxy_test.go @@ -162,6 +162,16 @@ var proxyHeaderTests = []proxyHeaderTest{ authUser: "foo", authPass: "bar", }, + { + method: "POST", + localPath: "/proxy/alertmanager/dummy/api/v1/silences", + upstreamURI: "http://alertmanager.example.com/api/v1/silences", + code: 200, + alertmanagerURI: "http://foo@alertmanager.example.com", + alertmanagerHost: "alertmanager.example.com", + authUser: "foo", + authPass: "", + }, } func TestProxyHeaders(t *testing.T) { From 56d402663d5d4a36ce772e523db65acfe35dcaed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 17 Apr 2018 22:08:50 -0700 Subject: [PATCH 15/15] Use Go 1.10.1 --- .travis.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3b53278da..03928c1f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ defaults_go: &DEFAULTS_GO language: go - go: "1.10" + go: "1.10.1" cache: directories: - vendor diff --git a/Dockerfile b/Dockerfile index 076ea0ffc..9c603a8bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ RUN apk add --update make git COPY . /unsee RUN make -C /unsee webpack -FROM golang:1.10-alpine as go-builder +FROM golang:1.10.1-alpine as go-builder COPY --from=nodejs-builder /unsee /go/src/github.com/cloudflare/unsee ARG VERSION RUN apk add --update make git