diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 061155a..2f16b8d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,3 +14,12 @@ jobs: override: true components: rustfmt, clippy - uses: pre-commit/action@v3.0.1 + + helm-unittest: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Helm unittest plugin + run: helm plugin install https://github.com/helm-unittest/helm-unittest.git + - name: Run Helm unittests + run: helm unittest helm diff --git a/helm/dashboards/dashboard.yaml b/helm/dashboards/dashboard.yaml deleted file mode 100644 index 9018bfc..0000000 --- a/helm/dashboards/dashboard.yaml +++ /dev/null @@ -1,699 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.grafanaDashboard.enabled -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "robotlb.fullname" . }}-dashboard - labels: - {{- include "robotlb.labels" . | nindent 4 }} - {{- with .Values.metrics.grafanaDashboard.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - grafana_dashboard: "1" -data: - robotlb-dashboard.json: | - { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Prometheus --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "RobotLB Operator Dashboard", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "panels": [], - "title": "Overview", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${datasource}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 1 - }, - "id": 2, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "11.0.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${datasource}" - }, - "expr": "robotlb_services_managed{controller=\"robotlb\"}", - "refId": "A" - } - ], - "title": "Managed Services", - "type": "stat" - }, - { - "datasource":{ - "type": "prometheus", - "uid": "${datasource}" - }, - "fieldConfig": { - "defaults":{ - "color":{ - "mode": "thresholds" - }, - "mappings":[ - { - "options":{ - "0":{ - "color":"yellow", - "index":0, - "text":"Standby" - }, - "1":{ - "color":"green", - "index":1, - "text":"Leader" - } - }, - "type":"value" - } - ], - "thresholds":{ - "mode":"absolute", - "steps":[ - { - "color":"green", - "value":null - } - ] - }, - "unit":"none" - }, - "overrides":[] - }, - "gridPos":{ - "h": 4, - "w": 6, - "x": 6, - "y": 1 - }, - "id": 3, - "options":{ - "colorMode":"value", - "graphMode":"area", - "justifyMode":"auto", - "orientation":"auto", - "reduceOptions":{ - "calcs":[ - "lastNotNull" - ], - "fields":"", - "values":false - }, - "textMode":"auto" - }, - "pluginVersion":"11.0.0", - "targets":[ - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "expr":"robotlb_leader_status{controller=\"robotlb\"}", - "refId":"A" - } - ], - "title":"Leader Status", - "type":"stat" - }, - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "fieldConfig":{ - "defaults":{ - "color":{ - "mode":"palette-classic" - }, - "custom":{ - "axisBorderShow":false, - "axisCenteredZero":false, - "axisColorMode":"text", - "axisLabel":"", - "axisPlacement":"auto", - "barAlignment":0, - "drawStyle":"line", - "fillOpacity":0, - "gradientMode":"none", - "hideFrom":{ - "legend":false, - "tooltip":false, - "viz":false - }, - "insertNulls":false, - "lineInterpolation":"linear", - "lineWidth":1, - "pointSize":5, - "scaleDistribution":{ - "type":"linear" - }, - "showPoints":"auto", - "spanNulls":false, - "stacking":{ - "group":"A", - "mode":"none" - }, - "thresholdsStyle":{ - "mode":"off" - } - }, - "mappings":[], - "thresholds":{ - "mode":"absolute", - "steps":[ - { - "color":"green", - "value":null - }, - { - "color":"red", - "value":80 - } - ] - }, - "unit":"s" - }, - "overrides":[] - }, - "gridPos":{ - "h": 4, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "options":{ - "legend":{ - "calcs":[ - "mean", - "max" - ], - "displayMode":"list", - "placement":"bottom", - "showLegend":true - }, - "tooltip":{ - "mode":"single", - "sort":"none" - } - }, - "targets":[ - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "expr":"robotlb_reconcile_duration_seconds{controller=\"robotlb\"}", - "legendFormat":"Reconcile Duration", - "refId":"A" - } - ], - "title":"Reconcile Duration", - "type":"timeseries" - }, - { - "collapsed":false, - "gridPos":{ - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 5, - "panels":[], - "title":"Operations", - "type":"row" - }, - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "fieldConfig":{ - "defaults":{ - "color":{ - "mode":"palette-classic" - }, - "custom":{ - "axisBorderShow":false, - "axisCenteredZero":false, - "axisColorMode":"text", - "axisLabel":"", - "axisPlacement":"auto", - "barAlignment":0, - "drawStyle":"line", - "fillOpacity":10, - "gradientMode":"none", - "hideFrom":{ - "legend":false, - "tooltip":false, - "viz":false - }, - "insertNulls":false, - "lineInterpolation":"linear", - "lineWidth":1, - "pointSize":5, - "scaleDistribution":{ - "type":"linear" - }, - "showPoints":"never", - "spanNulls":false, - "stacking":{ - "group":"A", - "mode":"none" - }, - "thresholdsStyle":{ - "mode":"off" - } - }, - "mappings":[], - "thresholds":{ - "mode":"absolute", - "steps":[ - { - "color":"green", - "value":null - } - ] - }, - "unit":"ops" - }, - "overrides":[] - }, - "gridPos":{ - "h": 8, - "w": 12, - "x": 0, - "y": 6 - }, - "id": 6, - "options":{ - "legend":{ - "calcs":[ - "rate" - ], - "displayMode":"list", - "placement":"bottom", - "showLegend":true - }, - "tooltip":{ - "mode":"multi", - "sort":"none" - } - }, - "targets":[ - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "expr":"rate(robotlb_reconcile_operations_total{controller=\"robotlb\"}[5m])", - "legendFormat":"Reconciles/sec", - "refId":"A" - } - ], - "title":"Reconcile Rate", - "type":"timeseries" - }, - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "fieldConfig":{ - "defaults":{ - "color":{ - "mode":"palette-classic" - }, - "custom":{ - "axisBorderShow":false, - "axisCenteredZero":false, - "axisColorMode":"text", - "axisLabel":"", - "axisPlacement":"auto", - "barAlignment":0, - "drawStyle":"line", - "fillOpacity":10, - "gradientMode":"none", - "hideFrom":{ - "legend":false, - "tooltip":false, - "viz":false - }, - "insertNulls":false, - "lineInterpolation":"linear", - "lineWidth":1, - "pointSize":5, - "scaleDistribution":{ - "type":"linear" - }, - "showPoints":"never", - "spanNulls":false, - "stacking":{ - "group":"A", - "mode":"none" - }, - "thresholdsStyle":{ - "mode":"off" - } - }, - "mappings":[], - "thresholds":{ - "mode":"absolute", - "steps":[ - { - "color":"green", - "value":null - }, - { - "color":"red", - "value":0.01 - } - ] - }, - "unit":"ops" - }, - "overrides":[] - }, - "gridPos":{ - "h": 8, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 7, - "options":{ - "legend":{ - "calcs":[ - "rate" - ], - "displayMode":"list", - "placement":"bottom", - "showLegend":true - }, - "tooltip":{ - "mode":"multi", - "sort":"none" - } - }, - "targets":[ - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "expr":"rate(robotlb_reconcile_failures_total{controller=\"robotlb\"}[5m])", - "legendFormat":"Failures/sec", - "refId":"A" - } - ], - "title":"Failure Rate", - "type":"timeseries" - }, - { - "collapsed":false, - "gridPos":{ - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 8, - "panels":[], - "title":"Hetzner Cloud API", - "type":"row" - }, - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "fieldConfig":{ - "defaults":{ - "color":{ - "mode":"palette-classic" - }, - "custom":{ - "axisBorderShow":false, - "axisCenteredZero":false, - "axisColorMode":"text", - "axisLabel":"", - "axisPlacement":"auto", - "barAlignment":0, - "drawStyle":"line", - "fillOpacity":10, - "gradientMode":"none", - "hideFrom":{ - "legend":false, - "tooltip":false, - "viz":false - }, - "insertNulls":false, - "lineInterpolation":"linear", - "lineWidth":1, - "pointSize":5, - "scaleDistribution":{ - "type":"linear" - }, - "showPoints":"never", - "spanNulls":false, - "stacking":{ - "group":"A", - "mode":"none" - }, - "thresholdsStyle":{ - "mode":"off" - } - }, - "mappings":[], - "thresholds":{ - "mode":"absolute", - "steps":[ - { - "color":"green", - "value":null - } - ] - }, - "unit":"ops" - }, - "overrides":[] - }, - "gridPos":{ - "h": 8, - "w": 12, - "x": 0, - "y": 15 - }, - "id": 9, - "options":{ - "legend":{ - "calcs":[ - "rate" - ], - "displayMode":"list", - "placement":"bottom", - "showLegend":true - }, - "tooltip":{ - "mode":"multi", - "sort":"none" - } - }, - "targets":[ - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "expr":"rate(robotlb_hcloud_api_requests_total{controller=\"robotlb\"}[5m])", - "legendFormat":"Requests/sec", - "refId":"A" - } - ], - "title":"API Request Rate", - "type":"timeseries" - }, - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "fieldConfig":{ - "defaults":{ - "color":{ - "mode":"palette-classic" - }, - "custom":{ - "axisBorderShow":false, - "axisCenteredZero":false, - "axisColorMode":"text", - "axisLabel":"", - "axisPlacement":"auto", - "barAlignment":0, - "drawStyle":"line", - "fillOpacity":10, - "gradientMode":"none", - "hideFrom":{ - "legend":false, - "tooltip":false, - "viz":false - }, - "insertNulls":false, - "lineInterpolation":"linear", - "lineWidth":1, - "pointSize":5, - "scaleDistribution":{ - "type":"linear" - }, - "showPoints":"never", - "spanNulls":false, - "stacking":{ - "group":"A", - "mode":"none" - }, - "thresholdsStyle":{ - "mode":"off" - } - }, - "mappings":[], - "thresholds":{ - "mode":"absolute", - "steps":[ - { - "color":"green", - "value":null - }, - { - "color":"red", - "value":0.001 - } - ] - }, - "unit":"ops" - }, - "overrides":[] - }, - "gridPos":{ - "h": 8, - "w": 12, - "x": 12, - "y": 15 - }, - "id": 10, - "options":{ - "legend":{ - "calcs":[ - "rate" - ], - "displayMode":"list", - "placement":"bottom", - "showLegend":true - }, - "tooltip":{ - "mode":"multi", - "sort":"none" - } - }, - "targets":[ - { - "datasource":{ - "type":"prometheus", - "uid": "${datasource}" - }, - "expr":"rate(robotlb_hcloud_api_errors_total{controller=\"robotlb\"}[5m])", - "legendFormat":"Errors/sec", - "refId":"A" - } - ], - "title":"API Error Rate", - "type":"timeseries" - } - ], - "refresh":"", - "schemaVersion":38, - "style":"dark", - "tags":[ - "robotlb", - "operator" - ], - "templating":{ - "list":[] - }, - "time":{ - "from":"now-1h", - "to":"now" - }, - "timepicker":{}, - "timezone":"", - "title":"RobotLB", - "uid":"robotlb", - "version":1, - "weekStart":"" - } -{{- end }} diff --git a/helm/templates/dashboard.yaml b/helm/templates/dashboard.yaml new file mode 100644 index 0000000..0418b10 --- /dev/null +++ b/helm/templates/dashboard.yaml @@ -0,0 +1,1447 @@ +{{- if and .Values.metrics.enabled .Values.metrics.grafanaDashboard.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "robotlb.fullname" . }}-dashboard + labels: + {{- include "robotlb.labels" . | nindent 4 }} + {{- with .Values.metrics.grafanaDashboard.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + grafana_dashboard: "1" +data: + robotlb-dashboard.json: | + { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "RobotLB Operator Dashboard - Monitors controller health, reconciliation operations, and Hetzner Cloud API interactions", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "panels": [], + "title": "📊 Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total number of Kubernetes services currently managed by RobotLB operator", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "robotlb_services_managed{controller=\"$controller\"}", + "refId": "A" + } + ], + "title": "Managed Services", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Current leader election status: Leader (1) or Standby (0)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "yellow", + "index": 0, + "text": "Standby" + }, + "1": { + "color": "green", + "index": 1, + "text": "Leader" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "robotlb_leader_status{controller=\"$controller\"}", + "refId": "A" + } + ], + "title": "Leader Status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Success rate of reconcile operations over the selected time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 95 + }, + { + "color": "green", + "value": 99 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "(\n sum(rate(robotlb_reconcile_operations_total{controller=\"$controller\"}[$__rate_interval]))\n -\n sum(rate(robotlb_reconcile_failures_total{controller=\"$controller\"}[$__rate_interval]))\n)\n/\nsum(rate(robotlb_reconcile_operations_total{controller=\"$controller\"}[$__rate_interval]))\n* 100\n", + "refId": "A" + } + ], + "title": "Reconcile Success Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Current rate of reconcile operations per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 1 + }, + "id": 12, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(rate(robotlb_reconcile_operations_total{controller=\"$controller\"}[$__rate_interval]))", + "refId": "A" + } + ], + "title": "Reconcile Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Average duration of reconcile operations", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "rate(robotlb_reconcile_duration_seconds_sum{controller=\"$controller\"}[$__rate_interval])\n/\nrate(robotlb_reconcile_duration_seconds_count{controller=\"$controller\"}[$__rate_interval])\n", + "refId": "A" + } + ], + "title": "Avg Reconcile Duration", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Current rate of Hetzner Cloud API requests per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 13, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(rate(robotlb_hcloud_api_requests_total{controller=\"$controller\"}[$__rate_interval]))", + "refId": "A" + } + ], + "title": "API Request Rate", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 5, + "panels": [], + "title": "⚙️ Reconciliation Performance", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of reconcile operations per second over time", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "rate(robotlb_reconcile_operations_total{controller=\"$controller\"}[$__rate_interval])", + "legendFormat": "Reconciles/sec", + "refId": "A" + } + ], + "title": "Reconcile Operations Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of reconcile operations over time", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "rate(robotlb_reconcile_duration_seconds_sum{controller=\"$controller\"}[$__rate_interval])\n/\nrate(robotlb_reconcile_duration_seconds_count{controller=\"$controller\"}[$__rate_interval])\n", + "legendFormat": "Avg Duration", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "histogram_quantile(0.50, sum(rate(robotlb_reconcile_duration_seconds_bucket{controller=\"$controller\"}[$__rate_interval])) by (le))", + "legendFormat": "p50", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "histogram_quantile(0.95, sum(rate(robotlb_reconcile_duration_seconds_bucket{controller=\"$controller\"}[$__rate_interval])) by (le))", + "legendFormat": "p95", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "histogram_quantile(0.99, sum(rate(robotlb_reconcile_duration_seconds_bucket{controller=\"$controller\"}[$__rate_interval])) by (le))", + "legendFormat": "p99", + "refId": "D" + } + ], + "title": "Reconcile Duration", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 8, + "panels": [], + "title": "❌ Errors & Failures", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of reconcile failures per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.01 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "rate(robotlb_reconcile_failures_total{controller=\"$controller\"}[$__rate_interval])", + "legendFormat": "Failures/sec", + "refId": "A" + } + ], + "title": "Reconcile Failure Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Cumulative count of reconcile operations vs failures", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total Operations" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Failures" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 15 + }, + "id": 15, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "robotlb_reconcile_operations_total{controller=\"$controller\"}", + "legendFormat": "Total Operations", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "robotlb_reconcile_failures_total{controller=\"$controller\"}", + "legendFormat": "Total Failures", + "refId": "B" + } + ], + "title": "Operations vs Failures", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 9, + "panels": [], + "title": "☁️ Hetzner Cloud API", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of Hetzner Cloud API requests per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 16, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "rate(robotlb_hcloud_api_requests_total{controller=\"$controller\"}[$__rate_interval])", + "legendFormat": "Requests/sec", + "refId": "A" + } + ], + "title": "API Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of Hetzner Cloud API errors per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.001 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 17, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "rate(robotlb_hcloud_api_errors_total{controller=\"$controller\"}[$__rate_interval])", + "legendFormat": "Errors/sec", + "refId": "A" + } + ], + "title": "API Error Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "API error rate as a percentage of total requests", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "(\n sum(rate(robotlb_hcloud_api_errors_total{controller=\"$controller\"}[$__rate_interval]))\n /\n sum(rate(robotlb_hcloud_api_requests_total{controller=\"$controller\"}[$__rate_interval]))\n) * 100\n", + "legendFormat": "Error Rate %", + "refId": "A" + } + ], + "title": "API Error Percentage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total cumulative API requests and errors", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total Requests" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Errors" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 19, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "robotlb_hcloud_api_requests_total{controller=\"$controller\"}", + "legendFormat": "Total Requests", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "robotlb_hcloud_api_errors_total{controller=\"$controller\"}", + "legendFormat": "Total Errors", + "refId": "B" + } + ], + "title": "API Requests vs Errors", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 39, + "tags": [ + "robotlb", + "operator", + "kubernetes", + "hetzner" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(robotlb_services_managed, controller)", + "hide": 0, + "includeAll": true, + "label": "Controller", + "multi": true, + "name": "controller", + "options": [], + "query": { + "query": "label_values(robotlb_services_managed, controller)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "RobotLB", + "uid": "robotlb", + "version": 2, + "weekStart": "" + } +{{- end }} diff --git a/helm/tests/dashboard_test.yaml b/helm/tests/dashboard_test.yaml new file mode 100644 index 0000000..d39b92d --- /dev/null +++ b/helm/tests/dashboard_test.yaml @@ -0,0 +1,177 @@ +suite: Dashboard +templates: + - dashboard.yaml +tests: + - it: should not render dashboard by default + set: + metrics.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should not render dashboard when metrics disabled + set: + metrics.enabled: false + metrics.grafanaDashboard.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should render dashboard when both enabled + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: RELEASE-NAME-robotlb-dashboard + - isNotNull: + path: data["robotlb-dashboard.json"] + + - it: should include correct labels + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - equal: + path: metadata.labels["grafana_dashboard"] + value: "1" + - equal: + path: metadata.labels["app.kubernetes.io/name"] + value: robotlb + + - it: should include custom labels when provided + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + metrics.grafanaDashboard.labels: + custom_label: custom_value + another_label: another_value + asserts: + - equal: + path: metadata.labels["custom_label"] + value: custom_value + - equal: + path: metadata.labels["another_label"] + value: another_value + + - it: should contain all expected metrics in dashboard + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_services_managed' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_leader_status' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_reconcile_duration_seconds' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_reconcile_operations_total' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_reconcile_failures_total' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_hcloud_api_requests_total' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'robotlb_hcloud_api_errors_total' + + - it: should use template variable for controller label in queries + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'controller=\\"\$controller\\"' + + - it: should include template variables for flexibility + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"name": "datasource"' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"name": "controller"' + + - it: should use modern Grafana schema version + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"schemaVersion": 39' + + - it: should include all dashboard sections + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'Overview' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'Reconciliation Performance' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'Errors.*Failures' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'Hetzner Cloud API' + + - it: should include percentile metrics in duration panel + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'histogram_quantile.*0\.50' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'histogram_quantile.*0\.95' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'histogram_quantile.*0\.99' + + - it: should calculate success rate correctly + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: 'Reconcile Success Rate' + + - it: should include appropriate dashboard tags + set: + metrics.enabled: true + metrics.grafanaDashboard.enabled: true + asserts: + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"tags"[\s\S]*"robotlb"' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"tags"[\s\S]*"operator"' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"tags"[\s\S]*"kubernetes"' + - matchRegex: + path: data["robotlb-dashboard.json"] + pattern: '"tags"[\s\S]*"hetzner"' diff --git a/helm/tests/prometheusrules_test.yaml b/helm/tests/prometheusrules_test.yaml new file mode 100644 index 0000000..be043cb --- /dev/null +++ b/helm/tests/prometheusrules_test.yaml @@ -0,0 +1,81 @@ +suite: Prometheus Rules +templates: + - prometheusrules.yaml +tests: + - it: should not render prometheus rules by default + set: + metrics.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should not render prometheus rules when metrics disabled + set: + metrics.enabled: false + metrics.prometheusRules.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should render prometheus rules when both enabled + set: + metrics.enabled: true + metrics.prometheusRules.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PrometheusRule + - equal: + path: metadata.name + value: RELEASE-NAME-robotlb + + - it: should include all expected alerts + set: + metrics.enabled: true + metrics.prometheusRules.enabled: true + asserts: + - equal: + path: spec.groups[0].name + value: robotlb.rules + - lengthEqual: + path: spec.groups[0].rules + count: 5 + + - it: should include correct metrics in alerts + set: + metrics.enabled: true + metrics.prometheusRules.enabled: true + documentSelector: + path: kind + value: PrometheusRule + asserts: + - matchRegex: + path: spec.groups[0].rules[?(@.alert == "RobotLBReconcileErrors")].expr + pattern: 'robotlb_reconcile_failures_total' + - matchRegex: + path: spec.groups[0].rules[?(@.alert == "RobotLBHighReconcileErrorRate")].expr + pattern: 'robotlb_reconcile_failures_total' + - matchRegex: + path: spec.groups[0].rules[?(@.alert == "RobotLBHighReconcileErrorRate")].expr + pattern: 'robotlb_reconcile_operations_total' + - matchRegex: + path: spec.groups[0].rules[?(@.alert == "RobotLBNotLeader")].expr + pattern: 'robotlb_leader_status' + - matchRegex: + path: spec.groups[0].rules[?(@.alert == "RobotLBHCloudAPIErrors")].expr + pattern: 'robotlb_hcloud_api_errors_total' + - matchRegex: + path: spec.groups[0].rules[?(@.alert == "RobotLBSlowReconcile")].expr + pattern: 'robotlb_reconcile_duration_seconds' + + - it: should include custom labels when provided + set: + metrics.enabled: true + metrics.prometheusRules.enabled: true + metrics.prometheusRules.labels: + custom_label: custom_value + asserts: + - equal: + path: metadata.labels["custom_label"] + value: custom_value diff --git a/helm/tests/service_test.yaml b/helm/tests/service_test.yaml new file mode 100644 index 0000000..0a4f7f0 --- /dev/null +++ b/helm/tests/service_test.yaml @@ -0,0 +1,44 @@ +suite: Service +templates: + - service.yaml +tests: + - it: should render service by default + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + - equal: + path: metadata.name + value: RELEASE-NAME-robotlb-metrics + + - it: should not render service when metrics.service disabled + set: + metrics.service.enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: should use correct port + asserts: + - equal: + path: spec.ports[0].port + value: 8080 + - equal: + path: spec.ports[0].targetPort + value: 8080 + - equal: + path: spec.ports[0].name + value: metrics + - equal: + path: spec.ports[0].protocol + value: TCP + + - it: should include annotations when provided + set: + metrics.service.annotations: + custom_annotation: custom_value + asserts: + - equal: + path: metadata.annotations.custom_annotation + value: custom_value diff --git a/helm/tests/servicemonitor_test.yaml b/helm/tests/servicemonitor_test.yaml new file mode 100644 index 0000000..4a858b6 --- /dev/null +++ b/helm/tests/servicemonitor_test.yaml @@ -0,0 +1,42 @@ +suite: ServiceMonitor +templates: + - servicemonitor.yaml +tests: + - it: should not render service monitor by default + set: + metrics.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should not render service monitor when metrics disabled + set: + metrics.enabled: false + metrics.serviceMonitor.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should render service monitor when both enabled + set: + metrics.enabled: true + metrics.serviceMonitor.enabled: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ServiceMonitor + + - it: should use correct interval and timeout + set: + metrics.enabled: true + metrics.serviceMonitor.enabled: true + metrics.serviceMonitor.interval: 60s + metrics.serviceMonitor.scrapeTimeout: 30s + asserts: + - equal: + path: spec.endpoints[0].interval + value: 60s + - equal: + path: spec.endpoints[0].scrapeTimeout + value: 30s