chore(backend): add tests for Alertmanager 0.15.2

This commit is contained in:
Łukasz Mierzwa
2018-08-14 18:38:27 +01:00
parent e94f0cd4ef
commit ebb115348f
5 changed files with 940 additions and 1 deletions

0
internal/mock/0.15.2/.ok Normal file
View File

View File

@@ -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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"53b23b18-eb32-492c-816d-0db910bdafb1"
],
"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-08-14T17:36:40.017867056Z",
"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": "24e4121619386f95",
"generatorURL": "localhost/prometheus",
"labels": {
"alertname": "Host_Down",
"cluster": "staging",
"instance": "server3",
"job": "node_ping"
},
"receivers": null,
"startsAt": "2018-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"4cf5fd82-1edd-4169-99d1-ff8415e72179"
],
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"4cf5fd82-1edd-4169-99d1-ff8415e72179",
"5d988cf7-c076-43c9-8c98-7724bc07894d"
],
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"4cf5fd82-1edd-4169-99d1-ff8415e72179"
],
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": [],
"silencedBy": [],
"state": "active"
}
}
],
"routeOpts": {
"groupBy": [
"alertname",
"cluster",
"service"
],
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"53b23b18-eb32-492c-816d-0db910bdafb1"
],
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": [],
"silencedBy": [],
"state": "active"
}
}
],
"routeOpts": {
"groupBy": [
"cluster",
"service",
"alertname"
],
"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": "0967807e4073b606",
"generatorURL": "localhost/prometheus",
"labels": {
"alertname": "Host_Down",
"cluster": "dev",
"instance": "server6",
"job": "node_ping"
},
"receivers": null,
"startsAt": "2018-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"4cf5fd82-1edd-4169-99d1-ff8415e72179"
],
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"4cf5fd82-1edd-4169-99d1-ff8415e72179",
"5d988cf7-c076-43c9-8c98-7724bc07894d"
],
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": null,
"silencedBy": [
"4cf5fd82-1edd-4169-99d1-ff8415e72179"
],
"state": "suppressed"
}
}
],
"routeOpts": {
"groupBy": [
"alertname",
"cluster",
"service"
],
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"status": {
"inhibitedBy": [],
"silencedBy": [],
"state": "active"
}
}
],
"routeOpts": {
"groupBy": [
"cluster",
"service",
"alertname"
],
"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": "d9067fcc9686d942",
"generatorURL": "localhost/prometheus",
"labels": {
"alertname": "Host_Down",
"cluster": "staging",
"instance": "server4",
"job": "node_ping"
},
"receivers": null,
"startsAt": "2018-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"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-08-14T17:36:40.017867056Z",
"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=\"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-08-14T17:36:40.017867056Z",
"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"
}

View File

@@ -0,0 +1,64 @@
{
"data": [
{
"comment": "Silenced instance",
"createdBy": "john@example.com",
"endsAt": "2063-01-01T00:00:00Z",
"id": "53b23b18-eb32-492c-816d-0db910bdafb1",
"matchers": [
{
"isRegex": false,
"name": "instance",
"value": "web1"
}
],
"startsAt": "2018-08-14T17:36:40.003722418Z",
"status": {
"state": "active"
},
"updatedAt": "2018-08-14T17:36:40.0037313Z"
},
{
"comment": "Silenced Host_Down alerts in the dev cluster",
"createdBy": "john@example.com",
"endsAt": "2063-01-01T00:00:00Z",
"id": "4cf5fd82-1edd-4169-99d1-ff8415e72179",
"matchers": [
{
"isRegex": false,
"name": "alertname",
"value": "Host_Down"
},
{
"isRegex": false,
"name": "cluster",
"value": "dev"
}
],
"startsAt": "2018-08-14T17:36:40.007903563Z",
"status": {
"state": "active"
},
"updatedAt": "2018-08-14T17:36:40.007909561Z"
},
{
"comment": "Silenced server7",
"createdBy": "john@example.com",
"endsAt": "2063-01-01T00:00:00Z",
"id": "5d988cf7-c076-43c9-8c98-7724bc07894d",
"matchers": [
{
"isRegex": false,
"name": "instance",
"value": "server7"
}
],
"startsAt": "2018-08-14T17:36:40.013397062Z",
"status": {
"state": "active"
},
"updatedAt": "2018-08-14T17:36:40.013404352Z"
}
],
"status": "success"
}

View File

@@ -0,0 +1,110 @@
{
"data": {
"clusterStatus": {
"name": "01CMWR563B2AQ4SBJT0G15MY2Q",
"peers": [
{
"address": "172.17.0.2:9094",
"name": "01CMWR563B2AQ4SBJT0G15MY2Q"
}
],
"status": "ready"
},
"configJSON": {
"global": {
"hipchat_api_url": "https://api.hipchat.com/",
"http_config": {
"BasicAuth": null,
"BearerToken": "",
"BearerTokenFile": "",
"ProxyURL": {},
"TLSConfig": {
"CAFile": "",
"CertFile": "",
"InsecureSkipVerify": false,
"KeyFile": "",
"ServerName": ""
}
},
"opsgenie_api_url": "https://api.opsgenie.com/",
"pagerduty_url": "https://events.pagerduty.com/v2/enqueue",
"resolve_timeout": 300000000000,
"smtp_hello": "localhost",
"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 http_config: {}\n smtp_hello: localhost\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",
"uptime": "2018-08-14T17:36:24.688050101Z",
"versionInfo": {
"branch": "HEAD",
"buildDate": "20180814-10:53:39",
"buildUser": "root@3101e5b68a55",
"goVersion": "go1.10.3",
"revision": "d19fae3bae451940b8470abb680cfdd59bfa7cfa",
"version": "0.15.2"
}
},
"status": "success"
}

View File

@@ -5,7 +5,7 @@ DOCKER_ARGS := --name $(DOCKER_NAME) --rm -d -p 9093:9093 \
-v $(CURDIR)/alertmanager.yml:/etc/alertmanager/alertmanager.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 0.14.0 0.15.0 0.15.1
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 0.15.0 0.15.1 0.15.2
%/.ok: livemock.py
$(eval VERSION := $(word 1, $(subst /, ,$@)))