Merge pull request #36 from salt-formulas/feature/clustecheck_for_mysqltype
Allow disable option *-check for mysql/pgsql type
diff --git a/.kitchen.travis.yml b/.kitchen.travis.yml
new file mode 100644
index 0000000..f847543
--- /dev/null
+++ b/.kitchen.travis.yml
@@ -0,0 +1,6 @@
+suites:
+
+ - name: <%= ENV['SUITE'] %>
+ provisioner:
+ pillars-from-files:
+ neutron.sls: tests/pillar/<%= ENV['SUITE'] %>.sls
diff --git a/.travis.yml b/.travis.yml
index 4f34af2..77b9e3c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,16 +17,23 @@
- bundle install
env:
- - PLATFORM=trevorj/salty-whales:trusty
- - PLATFORM=trevorj/salty-whales:xenial
-
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=admin
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=admin
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=single_contrail
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=single_contrail
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=single_general_service
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=single_general_service
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=single_openstack_service
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=single_openstack_service
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=stats
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=stats
before_script:
- set -o pipefail
- make test | tail
script:
- - test ! -e .kitchen.yml || bundle exec kitchen test -t tests/integration
+ - KITCHEN_LOCAL_YAML=.kitchen.travis.yml bundle exec kitchen test -t tests/integration
notifications:
webhooks:
diff --git a/haproxy/files/grafana_dashboards/haproxy_prometheus.json b/haproxy/files/grafana_dashboards/haproxy_prometheus.json
new file mode 100644
index 0000000..78f1adf
--- /dev/null
+++ b/haproxy/files/grafana_dashboards/haproxy_prometheus.json
@@ -0,0 +1,895 @@
+{% raw %}
+{
+ "annotations": {
+ "list": []
+ },
+ "editable": true,
+ "gnetId": null,
+ "graphTooltip": 1,
+ "hideControls": false,
+ "id": null,
+ "links": [],
+ "refresh": "1m",
+ "rows": [
+ {
+ "collapse": false,
+ "height": 282,
+ "panels": [
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 7,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "/queue/",
+ "color": "#BF1B00"
+ }
+ ],
+ "spaceLength": 10,
+ "span": 4,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "max(haproxy_server_connections {host=~\"$host\"}) without(pid) > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{ host }} connections",
+ "refId": "B",
+ "step": 2
+ },
+ {
+ "expr": "max(haproxy_server_ssl_connections {host=~\"$host\"}) without(pid) > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{ host }} SSL connections",
+ "refId": "A",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Server Connections",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 6,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "/queue/",
+ "color": "#BF1B00"
+ }
+ ],
+ "spaceLength": 10,
+ "span": 4,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "max(haproxy_server_tasks{host=~\"$host\"}) without(pid) > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{ host }} tasks",
+ "refId": "A",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Server Tasks",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 8,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "span": 4,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "max(haproxy_server_run_queue {host=~\"$host\"}) without(pid) > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "{{ host }} run_queue",
+ "refId": "C",
+ "step": 1
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Server Run Queue",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "decimals": 0,
+ "description": "",
+ "fill": 0,
+ "id": 9,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": true,
+ "hideEmpty": true,
+ "max": true,
+ "min": true,
+ "rightSide": true,
+ "show": true,
+ "sort": "min",
+ "sortDesc": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "span": 7,
+ "stack": false,
+ "steppedLine": true,
+ "targets": [
+ {
+ "expr": "haproxy_active_servers{host=~\"$host\",proxy=~\"$proxy\", sv=\"BACKEND\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{ host }}\u00a0{{ proxy }}",
+ "refId": "A",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Number of Active Servers",
+ "tooltip": {
+ "shared": true,
+ "sort": 2,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "description": "",
+ "fill": 0,
+ "id": 10,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": true,
+ "max": true,
+ "min": true,
+ "rightSide": true,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "span": 5,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "haproxy_backup_servers{host=~\"$host\",proxy=~\"$proxy\", sv=\"BACKEND\"} > 0",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{ host }}\u00a0{{ proxy }}",
+ "refId": "A",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Number of Backup Servers",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ }
+ ],
+ "repeat": null,
+ "repeatIteration": null,
+ "repeatRowId": null,
+ "showTitle": true,
+ "title": "Servers Statistics",
+ "titleSize": "h6"
+ },
+ {
+ "collapse": false,
+ "height": 307,
+ "panels": [
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 2,
+ "legend": {
+ "alignAsTable": true,
+ "avg": true,
+ "current": true,
+ "max": true,
+ "min": false,
+ "rightSide": false,
+ "show": true,
+ "sort": "avg",
+ "sortDesc": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "span": 6,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "avg(haproxy_req_rate{sv=\"FRONTEND\", proxy=~\"$proxy\", host=~\"$host\"}) by (host, proxy) > 0",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{ host }} {{ proxy }}",
+ "refId": "C",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "HTTP requests",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "ops",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 5,
+ "legend": {
+ "alignAsTable": true,
+ "avg": true,
+ "current": true,
+ "max": true,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "/ 5xx/",
+ "color": "#BF1B00"
+ },
+ {
+ "alias": "/ 2xx/",
+ "color": "#629E51"
+ },
+ {
+ "alias": "/ 3xx/",
+ "color": "#E0752D"
+ }
+ ],
+ "spaceLength": 10,
+ "span": 6,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "irate(haproxy_http_response_2xx{proxy=~\"$proxy\", host=~\"$host\", sv=\"FRONTEND\"}[1m]) > 0",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{host}} {{proxy}} 2xx",
+ "refId": "A",
+ "step": 1
+ },
+ {
+ "expr": "irate(haproxy_http_response_1xx{proxy=~\"$proxy\", host=~\"$host\", sv=\"FRONTEND\"}[1m]) > 0",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{host}} {{proxy}} 1xx",
+ "refId": "B",
+ "step": 2
+ },
+ {
+ "expr": "irate(haproxy_http_response_3xx{proxy=~\"$proxy\", host=~\"$host\", sv=\"FRONTEND\"}[1m]) > 0",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{host}} {{proxy}} 3xx",
+ "refId": "C",
+ "step": 2
+ },
+ {
+ "expr": "irate(haproxy_http_response_4xx{proxy=~\"$proxy\", host=~\"$host\", sv=\"FRONTEND\"}[1m]) > 0",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{host}} {{proxy}} 4xx",
+ "refId": "D",
+ "step": 2
+ },
+ {
+ "expr": "irate(haproxy_http_response_5xx{proxy=~\"$proxy\", host=~\"$host\", sv=\"FRONTEND\"}[1m]) > 0",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{host}} {{proxy}} 5xx",
+ "refId": "E",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "HTTP Responses",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "ops",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 3,
+ "legend": {
+ "alignAsTable": true,
+ "avg": true,
+ "current": true,
+ "max": true,
+ "min": false,
+ "rightSide": false,
+ "show": true,
+ "sort": "max",
+ "sortDesc": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "/^in.*/",
+ "transform": "negative-Y"
+ }
+ ],
+ "spaceLength": 10,
+ "span": 6,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "irate(haproxy_bin{sv=\"FRONTEND\",host=~\"$host\", proxy=~\"$proxy\"}[1m]) >0",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "in {{ host }} {{ proxy }}",
+ "refId": "A",
+ "step": 1
+ },
+ {
+ "expr": "irate(haproxy_bout{sv=\"FRONTEND\",host=~\"$host\", proxy=~\"$proxy\"}[1m]) >0",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "out {{ host }} {{ proxy }}",
+ "refId": "B",
+ "step": 1
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Throughput",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "Bps",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "fill": 1,
+ "id": 4,
+ "legend": {
+ "alignAsTable": true,
+ "avg": true,
+ "current": true,
+ "max": true,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "span": 6,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "haproxy_scur{proxy=~\"$proxy\", host=~\"$host\", sv=\"FRONTEND\"} > 0 ",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{\u00a0host }} {{ proxy }}",
+ "refId": "A",
+ "step": 2
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Current Sessions",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ }
+ ],
+ "repeat": null,
+ "repeatIteration": null,
+ "repeatRowId": null,
+ "showTitle": true,
+ "title": "Activity",
+ "titleSize": "h6"
+ }
+ ],
+ "schemaVersion": 14,
+ "sharedCrosshair": true,
+ "style": "dark",
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "allValue": null,
+ "current": {},
+ "hide": 0,
+ "includeAll": true,
+ "label": null,
+ "multi": true,
+ "name": "host",
+ "options": [],
+ "query": "label_values(haproxy_downtime,host)",
+ "refresh": 1,
+ "refresh_on_load": true,
+ "regex": "",
+ "sort": 1,
+ "tagValuesQuery": "",
+ "tags": [],
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ },
+ {
+ "allValue": null,
+ "current": {},
+ "hide": 0,
+ "includeAll": true,
+ "label": null,
+ "multi": true,
+ "name": "proxy",
+ "options": [],
+ "query": "query_result(sum by (proxy) (haproxy_downtime{host=~\"$host\"} * on (instance, job, proxy, sv) group_left(host) haproxy_active_servers ))",
+ "refresh": 1,
+ "refresh_on_load": true,
+ "regex": "/proxy=\"(.+)\"/",
+ "sort": 1,
+ "tagValuesQuery": "",
+ "tags": [],
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ }
+ ]
+ },
+ "time": {
+ "from": "now-1h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ]
+ },
+ "timezone": "browser",
+ "title": "Haproxy",
+ "version": 22
+}
+{% endraw %}
diff --git a/haproxy/files/haproxy-status.sh b/haproxy/files/haproxy-status.sh
new file mode 100644
index 0000000..48fba3a
--- /dev/null
+++ b/haproxy/files/haproxy-status.sh
@@ -0,0 +1,49 @@
+{%- from "haproxy/map.jinja" import proxy with context -%}
+#!/bin/sh
+
+show_stats() {
+ echo 'show stat' | socat 'UNIX-CONNECT:{{ proxy.stats_socket }}' STDIO | awk \
+ '
+ function fillstr(string, num)
+ {
+ len=length(string);
+ if (len>=num)
+ {
+ printf("%s",substr(string,1,num));
+ }
+ else
+ {
+ printf("%s",string);
+ for(i=1; i<=num-len; i++)
+ {
+ printf(" ");
+ }
+ }
+ }
+
+ BEGIN {
+ FS = ",";
+ };
+
+ {
+ if ($1 ~ /^#/) { next };
+ if ($1 == "") { next };
+
+ status=sprintf("Status: %s",$18);
+ if ($37 != "") {
+ status=status sprintf("/%s",$37);
+ }
+ sessions=sprintf("Sessions: %s",$5);
+ rate=sprintf("Rate: %s",$34);
+
+ fillstr($1,25);
+ fillstr($2,15);
+ fillstr(status,20);
+ fillstr(sessions,15);
+ fillstr(rate,10);
+ printf("\n");
+ }
+ '
+}
+
+show_stats
diff --git a/haproxy/files/haproxy.cfg b/haproxy/files/haproxy.cfg
index e3f515f..a395973 100644
--- a/haproxy/files/haproxy.cfg
+++ b/haproxy/files/haproxy.cfg
@@ -63,7 +63,7 @@
listen {{ listen_name }}
{%- for bind in listen.binds %}
- bind {{ bind.address }}:{{ bind.port }} {% if bind.get('ssl', {}).enabled|default(False) %}{% if bind.ssl.pem_file is defined %}ssl crt {{ bind.ssl.pem_file }}{% else %}crt /etc/haproxy/ssl/{{ listen_name }}{% endif %}{% endif %}
+ bind {{ bind.address }}:{{ bind.port }} {% if bind.get('ssl', {}).enabled|default(False) %}{% if bind.ssl.pem_file is defined %}ssl crt {{ bind.ssl.pem_file }}{% else %}ssl crt /etc/haproxy/ssl/{{ listen_name }}{% endif %}{% endif %}
{%- endfor %}
{%- if listen.get('type', None) == 'http' %}
mode http
@@ -76,7 +76,7 @@
timeout client 300s
timeout server 300s
{%- elif listen.get('type', None) == 'mysql' %}
- balance leastconn
+ balance {{ listen.get('balance', 'leastconn') }}
mode tcp
option httpchk
option tcplog
@@ -89,7 +89,7 @@
option mysql-check user haproxy
{%- endif %}
{%- elif listen.get('type', None) == 'pgsql' %}
- balance leastconn
+ balance {{ listen.get('balance', 'leastconn') }}
mode tcp
option httpchk
option tcplog
@@ -101,7 +101,7 @@
option pgsql-check user postgres
{%- endif %}
{%- elif listen.get('type', None) == 'horizon' %}
- balance source
+ balance {{ listen.get('balance', 'source') }}
capture cookie vgnvisitor= len 32
cookie SERVERID insert indirect nocache
mode http
@@ -174,9 +174,12 @@
{%- endfor %}
{%- for type, checks in listen.get('health-check', {}).iteritems() %}
{%- if checks.get('enabled', True) %}
- {%- if type == 'http' and 'httpchk' not in listen.get('options', []) %}
+ {%- if type == 'http' and 'httpchk' not in listen.get('options', [])|join('|') %}
option httpchk
{%- endif %}
+ {%- if type == 'tcp' and 'tcp-check' not in listen.get('options', [])|join('|') %}
+ option tcp-check
+ {%- endif %}
{%- for option in checks.get('options', []) %}
{{ type }}-check {{ option }}
{%- endfor %}
@@ -202,12 +205,21 @@
{%- for listen_name, listen in proxy.get('listen', {}).iteritems() %}
{%- if listen.get('format', 'listen') == 'end' %}
-frontend {{ listen_name }} {{ listen.binds[0].address }}:{{ listen.binds[0].port }}
+frontend {{ listen_name }}
+ bind {{ listen.binds[0].address }}:{{ listen.binds[0].port }}
+ {% if listen.binds[0].get('ssl', {}).enabled|default(False) %}
+ bind {{ listen.binds[0].address }}:{{ listen.binds[0].ssl_port|default('443') }} {% if listen.binds[0].ssl.pem_file is defined %}ssl crt {{ listen.binds[0].ssl.pem_file }}{% else %}ssl crt /etc/haproxy/ssl/{{ listen_name }}{% endif %}
+ redirect scheme https code 301 if !{ ssl_fc }
+ {% endif %}
{%- for acl in listen.get('acls', []) %}
{%- for condition in acl.get('conditions', []) %}
acl {{ acl.name }} {{ condition.type }} {{ condition.condition }}
{%- endfor %}
- use_backend {{ acl.name }}-backend if {{ acl.name }}
+ {%- if listen_name == 'service_proxy' %}
+ use_backend {{ acl.name }} if {{ acl.name }}
+ {% else %}
+ use_backend {{ acl.name }}-backend if {{ acl.name }}
+ {% endif %}
{%- endfor %}
default_backend {{ listen_name }}-backend
@@ -218,6 +230,7 @@
{%- for server in listen.get('servers', []) %}
server {{ server.get('name', server.host) }} {{ server.host }}:{{ server.port }} {{ server.get('params', '') }}
{%- endfor %}
+{%- if listen_name != 'service_proxy' %}
{%- for acl in listen.get('acls', []) %}
backend {{ acl.name }}-backend
@@ -227,4 +240,5 @@
{%- endfor %}
{%- endfor %}
{%- endif %}
+{%- endif %}
{%- endfor %}
diff --git a/haproxy/meta/grafana.yml b/haproxy/meta/grafana.yml
index 5f9daca..63ab766 100644
--- a/haproxy/meta/grafana.yml
+++ b/haproxy/meta/grafana.yml
@@ -1,8 +1,14 @@
dashboard:
- haproxy:
+ haproxy_prometheus:
+ datasource: prometheus
+ format: json
+ template: haproxy/files/grafana_dashboards/haproxy_prometheus.json
+ haproxy_influxdb:
+ datasource: influxdb
format: json
template: haproxy/files/grafana_dashboards/haproxy_influxdb.json
main:
+ datasource: influxdb
row:
ost-middleware:
title: Middleware
diff --git a/haproxy/meta/prometheus.yml b/haproxy/meta/prometheus.yml
new file mode 100644
index 0000000..ce9f008
--- /dev/null
+++ b/haproxy/meta/prometheus.yml
@@ -0,0 +1,67 @@
+{%- if pillar.haproxy is defined and pillar.haproxy.proxy is defined %}
+{%- from "haproxy/map.jinja" import proxy with context %}
+{%- if proxy.enabled and proxy.listen is defined and proxy.listen|length > 0 %}
+server:
+ alert:
+{%- for listen_name, listen in proxy.listen.iteritems() if listen.get('check', True) %}
+{%- set camel_case_name = listen_name.replace('-','_').split('_')|map('capitalize')|join('') %}
+ HAproxy{{ camel_case_name }}HTTPResponse5xx:
+{% raw %}
+ if: >-
+ rate(haproxy_http_response_5xx{sv="FRONTEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"}[1m]) > 1
+ for: 2m
+ labels:
+ severity: warning
+ service: "haproxy/{{ $labels.proxy }}"
+ annotations:
+ summary: HTTP 5xx responses on '{{ $labels.proxy }}' proxy (host {{ $labels.host }})
+ description: >-
+ Too many 5xx HTTP errors have been detected on the '{{ $labels.proxy }}' proxy for the last 2 minutes
+ ({{ $value }} error(s) per second)
+{% endraw %}
+ HAproxy{{ camel_case_name }}BackendWarning:
+{% raw %}
+ if: >-
+ max(max_over_time(haproxy_active_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"}[12h]))
+ - min (haproxy_active_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"}) >= 1
+ for: 5m
+ labels:
+ severity: warning
+ service: "haproxy/{{ $labels.proxy }}"
+ annotations:
+ summary: "At least one backend is down for '{{ $labels.proxy }}' proxy for the last 5 minutes"
+ description: >-
+ {{ $value }} of backends are down for the '{{ $labels.proxy }}' proxy
+{% endraw %}
+ HAproxy{{ camel_case_name }}BackendCritical:
+{% raw %}
+ if: >-
+ (max(max_over_time(haproxy_active_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"}[12h]))
+ - min (haproxy_active_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"})
+ )/ max(max_over_time(haproxy_active_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"}[12h])) * 100 >= 50
+ for: 5m
+ labels:
+ severity: critical
+ service: "haproxy/{{ $labels.proxy }}"
+ annotations:
+ summary: "Less than 50% of backends are up for the '{{ $labels.proxy }}' proxy for the last 5 minutes"
+ description: >-
+ {{ $value }}% of backends are down for the '{{ $labels.proxy }}' proxy
+{% endraw %}
+ HAproxy{{ camel_case_name }}BackendDown:
+{% raw %}
+ if: >-
+ max(haproxy_active_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"})
+ + max(haproxy_backup_servers{sv="BACKEND",proxy="{% endraw %}{{ listen_name }}{% raw %}"}) == 0
+ for: 2m
+ labels:
+ severity: down
+ service: "haproxy/{{ $labels.proxy }}"
+ annotations:
+ summary: "All backends are down for the '{{ $labels.proxy }}' proxy"
+ description: >-
+ The proxy '{{ $labels.proxy }}' has no active backend
+{% endraw %}
+{%- endfor %}
+{%- endif %}
+{%- endif %}
diff --git a/haproxy/meta/sphinx.yml b/haproxy/meta/sphinx.yml
index 61d61d1..c8902cd 100644
--- a/haproxy/meta/sphinx.yml
+++ b/haproxy/meta/sphinx.yml
@@ -7,7 +7,7 @@
name: proxy
param:
version:
- value: "{{ salt['cmd.run']('haproxy -v')|replace("HA-Proxy version ", '') }}"
+ value: "{{ salt['cmd.shell']('haproxy -v 2>/dev/null || echo unknown')|replace('HA-Proxy version ', '') }}"
endpoint:
{%- for listen_name, listen in proxy.get('listen', {}).iteritems() %}
{%- if listen.binds.0.address not in ["127.0.0.1", "localhost", "::1"] %}
diff --git a/haproxy/meta/telegraf.yml b/haproxy/meta/telegraf.yml
new file mode 100644
index 0000000..6e28f3b
--- /dev/null
+++ b/haproxy/meta/telegraf.yml
@@ -0,0 +1,8 @@
+{%- from "haproxy/map.jinja" import proxy with context %}
+{%- if proxy.enabled %}
+{%- set servers = [proxy.stats_socket] %}
+agent:
+ input:
+ haproxy:
+ servers: {{ servers|yaml }}
+{%- endif %}
diff --git a/haproxy/proxy.sls b/haproxy/proxy.sls
index d5e65cd..55792c6 100644
--- a/haproxy/proxy.sls
+++ b/haproxy/proxy.sls
@@ -27,6 +27,22 @@
- require:
- pkg: haproxy_packages
+haproxy_status_packages:
+ pkg.installed:
+ - pkgs:
+ - socat
+
+haproxy_status_sh:
+ file.managed:
+ - name: /usr/bin/haproxy-status.sh
+ - user: root
+ - group: root
+ - mode: 700
+ - source: salt://haproxy/files/haproxy-status.sh
+ - template: jinja
+ - require:
+ - pkg: haproxy_status_packages
+
{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
net.ipv4.ip_nonlocal_bind:
@@ -35,18 +51,17 @@
{% endif %}
-{% if not grains.get('noservices', False) %}
-
haproxy_service:
service.running:
- name: {{ proxy.service }}
- enable: true
+ {%- if grains.get('noservices') %}
+ - onlyif: /bin/false
+ {%- endif %}
- watch:
- file: /etc/haproxy/haproxy.cfg
- file: /etc/default/haproxy
-{% endif %}
-
{%- for listen_name, listen in proxy.get('listen', {}).iteritems() %}
{%- if listen.get('enabled', True) %}
{%- for bind in listen.binds %}
@@ -67,10 +82,8 @@
chain: {{ bind.ssl.get('chain', '')|yaml }}
- require:
- file: haproxy_ssl
- {% if not grains.get('noservices', False) %}
- watch_in:
- service: haproxy_service
- {% endif %}
{%- endif %}
{%- endfor %}
diff --git a/metadata.yml b/metadata.yml
index 48c699e..4d35e66 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,3 +1,8 @@
name: "haproxy"
version: "0.2"
source: "https://github.com/salt-formulas/salt-formula-haproxy"
+
+# For haproxy/meta/sensu.yml
+dependencies:
+- name: linux
+ source: "https://github.com/salt-formulas/salt-formula-linux"
diff --git a/metadata/service/support.yml b/metadata/service/support.yml
index 95a2e7e..50c8d01 100644
--- a/metadata/service/support.yml
+++ b/metadata/service/support.yml
@@ -7,7 +7,11 @@
enabled: true
sensu:
enabled: false
+ telegraf:
+ enabled: true
sphinx:
enabled: true
grafana:
enabled: true
+ prometheus:
+ enabled: true
diff --git a/tests/pillar/single_contrail.sls b/tests/pillar/single_contrail.sls
index 5c3ca7b..0cfe8f1 100644
--- a/tests/pillar/single_contrail.sls
+++ b/tests/pillar/single_contrail.sls
@@ -49,4 +49,9 @@
- name: ams1posntw03
host: 127.0.0.1
port: 9100
- params: check inter 2000 rise 2 fall 3
\ No newline at end of file
+ params: check inter 2000 rise 2 fall 3
+
+# For haproxy/meta/sensu.yml
+linux:
+ network:
+ fqdn: linux.ci.local
diff --git a/tests/pillar/single_general_service.sls b/tests/pillar/single_general_service.sls
index 57f9a80..9887419 100644
--- a/tests/pillar/single_general_service.sls
+++ b/tests/pillar/single_general_service.sls
@@ -22,4 +22,9 @@
- name: ctl03
host: 127.0.0.1
port: 9292
- params: check inter 10s fastinter 2s downinter 3s rise 3 fall 3
\ No newline at end of file
+ params: check inter 10s fastinter 2s downinter 3s rise 3 fall 3
+
+# For haproxy/meta/sensu.yml
+linux:
+ network:
+ fqdn: linux.ci.local
diff --git a/tests/pillar/single_openstack_service.sls b/tests/pillar/single_openstack_service.sls
index 362c2ce..9e2ec2f 100644
--- a/tests/pillar/single_openstack_service.sls
+++ b/tests/pillar/single_openstack_service.sls
@@ -22,4 +22,9 @@
- name: ctl03
host: 127.0.0.1
port: 8776
- params: check inter 10s fastinter 2s downinter 3s rise 3 fall 3
\ No newline at end of file
+ params: check inter 10s fastinter 2s downinter 3s rise 3 fall 3
+
+# For haproxy/meta/sensu.yml
+linux:
+ network:
+ fqdn: linux.ci.local
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 3f42101..29fb975 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -6,11 +6,13 @@
CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
METADATA=${CURDIR}/../metadata.yml
FORMULA_NAME=$(cat $METADATA | python -c "import sys,yaml; print yaml.load(sys.stdin)['name']")
+FORMULA_META_DIR=${CURDIR}/../${FORMULA_NAME}/meta
## Overrideable parameters
PILLARDIR=${PILLARDIR:-${CURDIR}/pillar}
BUILDDIR=${BUILDDIR:-${CURDIR}/build}
VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv}
+MOCK_BIN_DIR=${MOCK_BIN_DIR:-${CURDIR}/mock_bin}
DEPSDIR=${BUILDDIR}/deps
SALT_FILE_DIR=${SALT_FILE_DIR:-${BUILDDIR}/file_root}
@@ -18,7 +20,7 @@
SALT_CONFIG_DIR=${SALT_CONFIG_DIR:-${BUILDDIR}/salt}
SALT_CACHE_DIR=${SALT_CACHE_DIR:-${SALT_CONFIG_DIR}/cache}
-SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR}"
+SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null"
if [ "x${SALT_VERSION}" != "x" ]; then
PIP_SALT_VERSION="==${SALT_VERSION}"
@@ -40,10 +42,20 @@
pip install salt${PIP_SALT_VERSION}
}
+setup_mock_bin() {
+ # If some state requires a binary, a lightweight replacement for
+ # such binary can be put into MOCK_BIN_DIR for test purposes
+ if [ -d "${MOCK_BIN_DIR}" ]; then
+ PATH="${MOCK_BIN_DIR}:$PATH"
+ export PATH
+ fi
+}
+
setup_pillar() {
[ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR}
echo "base:" > ${SALT_PILLAR_DIR}/top.sls
for pillar in ${PILLARDIR}/*; do
+ grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
state_name=$(basename ${pillar%.sls})
echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
done
@@ -56,6 +68,7 @@
echo "base:" > ${SALT_FILE_DIR}/top.sls
for pillar in ${PILLARDIR}/*.sls; do
+ grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
state_name=$(basename ${pillar%.sls})
echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
done
@@ -64,6 +77,7 @@
file_client: local
cachedir: ${SALT_CACHE_DIR}
verify_env: False
+minion_id_caching: False
file_roots:
base:
@@ -118,6 +132,7 @@
[ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
which salt-call || setup_virtualenv
+ setup_mock_bin
setup_pillar
setup_salt
install_dependencies
@@ -125,8 +140,28 @@
run() {
for pillar in ${PILLARDIR}/*.sls; do
+ grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
state_name=$(basename ${pillar%.sls})
+ salt_run grains.set 'noservices' False force=True
+
+ echo "Checking state ${FORMULA_NAME}.${state_name} ..."
salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
+
+ # Check that all files in 'meta' folder can be rendered using any valid pillar
+ for meta in `find ${FORMULA_META_DIR} -type f`; do
+ meta_name=$(basename ${meta})
+ echo "Checking meta ${meta_name} ..."
+ salt_run --out=quiet --id=${state_name} cp.get_template ${meta} ${SALT_CACHE_DIR}/${meta_name} \
+ || (log_err "Failed to render meta ${meta} using pillar ${FORMULA_NAME}.${state_name}"; exit 1)
+ cat ${SALT_CACHE_DIR}/${meta_name}
+ done
+ done
+}
+
+real_run() {
+ for pillar in ${PILLARDIR}/*.sls; do
+ state_name=$(basename ${pillar%.sls})
+ salt_run --id=${state_name} state.sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
done
}
@@ -155,6 +190,9 @@
run)
run
;;
+ real-run)
+ real_run
+ ;;
*)
prepare
run