From 04ef3774b0e241ee878d2334a58326caa43c0495 Mon Sep 17 00:00:00 2001 From: Christos Diamantis <154525755+christos-diamantis@users.noreply.github.com> Date: Wed, 9 Jul 2025 16:44:17 +0300 Subject: [PATCH] Zabbix 7.4 compatibility tests (#2053) * Resolves issue (#2051) --- .github/workflows/compatibility-74.yml | 39 ++ devenv/zabbix74/bootstrap/Dockerfile | 17 + devenv/zabbix74/bootstrap/bootstrap_config.py | 75 +++ .../zabbix74/bootstrap/zbx_export_hosts.json | 427 +++++++++++++++++ .../zabbix74/bootstrap/zbx_export_hosts.xml | 432 ++++++++++++++++++ devenv/zabbix74/docker-compose.yml | 117 +++++ .../zabbix_api_74_integration_test.go | 161 +++++++ 7 files changed, 1268 insertions(+) create mode 100644 .github/workflows/compatibility-74.yml create mode 100644 devenv/zabbix74/bootstrap/Dockerfile create mode 100644 devenv/zabbix74/bootstrap/bootstrap_config.py create mode 100644 devenv/zabbix74/bootstrap/zbx_export_hosts.json create mode 100644 devenv/zabbix74/bootstrap/zbx_export_hosts.xml create mode 100644 devenv/zabbix74/docker-compose.yml create mode 100644 pkg/zabbixapi/zabbix_api_74_integration_test.go diff --git a/.github/workflows/compatibility-74.yml b/.github/workflows/compatibility-74.yml new file mode 100644 index 0000000..8ad3e24 --- /dev/null +++ b/.github/workflows/compatibility-74.yml @@ -0,0 +1,39 @@ +name: zabbix_74 +run-name: Compatibility with Zabbix 7.4 test +permissions: + contents: read + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + compatibility-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - uses: actions/setup-go@v5.3.0 + + - name: Start Zabbix environment + run: | + docker compose -f devenv/zabbix74/docker-compose.yml up -d + # Wait for Zabbix to be ready + sleep 30 + + - name: Run integration tests + env: + INTEGRATION_TEST74: 'true' + ZABBIX_URL: 'http://localhost:8188/api_jsonrpc.php' + ZABBIX_USER: 'Admin' + ZABBIX_PASSWORD: 'zabbix' + run: go test -v ./pkg/zabbixapi/... + + - name: Cleanup + if: always() + run: docker compose -f devenv/zabbix74/docker-compose.yml down -v \ No newline at end of file diff --git a/devenv/zabbix74/bootstrap/Dockerfile b/devenv/zabbix74/bootstrap/Dockerfile new file mode 100644 index 0000000..bb92a63 --- /dev/null +++ b/devenv/zabbix74/bootstrap/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.13-slim-bookworm + +ENV ZBX_API_URL=http://zabbix-web:8080 +ENV ZBX_API_USER="Admin" +ENV ZBX_API_PASSWORD="zabbix" +ENV ZBX_CONFIG="zbx_export_hosts.json" +ENV ZBX_BOOTSTRAP_SCRIPT="bootstrap_config.py" + +RUN pip install zabbix_utils + +ADD ./bootstrap_config.py /bootstrap_config.py +ADD ${ZBX_CONFIG} /${ZBX_CONFIG} + +WORKDIR / + +# Run bootstrap_config.py when the container launches +CMD ["python", "/bootstrap_config.py"] \ No newline at end of file diff --git a/devenv/zabbix74/bootstrap/bootstrap_config.py b/devenv/zabbix74/bootstrap/bootstrap_config.py new file mode 100644 index 0000000..ff6a975 --- /dev/null +++ b/devenv/zabbix74/bootstrap/bootstrap_config.py @@ -0,0 +1,75 @@ +import os +from zabbix_utils import ZabbixAPI + +zabbix_url = os.environ['ZBX_API_URL'] +zabbix_user = os.environ['ZBX_API_USER'] +zabbix_password = os.environ['ZBX_API_PASSWORD'] +print(zabbix_url, zabbix_user, zabbix_password) + +zapi = ZabbixAPI(zabbix_url) + +for i in range(10): + try: + zapi.login(user=zabbix_user, password=zabbix_password) + print("Connected to Zabbix API Version %s" % zapi.api_version()) + break + except Exception as e: + print(e) + +config_path = os.environ['ZBX_CONFIG'] +import_rules = { + 'discoveryRules': { + 'createMissing': True, + 'updateExisting': True + }, + 'graphs': { + 'createMissing': True, + 'updateExisting': True + }, + 'host_groups': { + 'createMissing': True + }, + 'hosts': { + 'createMissing': True, + 'updateExisting': True + }, + 'images': { + 'createMissing': True, + 'updateExisting': True + }, + 'items': { + 'createMissing': True, + 'updateExisting': True + }, + 'maps': { + 'createMissing': True, + 'updateExisting': True + }, + 'templateLinkage': { + 'createMissing': True, + }, + 'templates': { + 'createMissing': True, + 'updateExisting': True + }, + 'triggers': { + 'createMissing': True, + 'updateExisting': True + }, +} + +print("Importing Zabbix config from %s" % config_path) +with open(config_path, 'r') as f: + config = f.read() + + try: + import_result = zapi.configuration.import_(source=config, format="json", rules=import_rules) + if import_result == True: + print("Zabbix config imported successfully") + else: + print("Failed to import Zabbix config") + except Exception as e: + print(e) + +for h in zapi.host.get(output="extend"): + print(h['name']) \ No newline at end of file diff --git a/devenv/zabbix74/bootstrap/zbx_export_hosts.json b/devenv/zabbix74/bootstrap/zbx_export_hosts.json new file mode 100644 index 0000000..09dcf4f --- /dev/null +++ b/devenv/zabbix74/bootstrap/zbx_export_hosts.json @@ -0,0 +1,427 @@ +{ + "zabbix_export": { + "version": "7.0", + "host_groups": [ + { + "uuid": "2e427c268ac1468b9add94b65e2d6c14", + "name": "Backend" + }, + { + "uuid": "d97ba66b283544339628b71975a6e68d", + "name": "Frontend" + }, + { + "uuid": "dc579cd7a1a34222933f24f52a68bcd8", + "name": "Linux servers" + }, + { + "uuid": "6f6799aa69e844b4b3918f779f2abf08", + "name": "Zabbix servers" + } + ], + "hosts": [ + { + "host": "backend01", + "name": "backend01", + "templates": [ + { + "name": "Template ZAS Agent" + } + ], + "groups": [ + { + "name": "Backend" + }, + { + "name": "Linux servers" + } + ], + "interfaces": [ + { + "useip": "NO", + "dns": "zas_backend_01", + "interface_ref": "if1" + } + ], + "tags": [ + { + "tag": "backend" + }, + { + "tag": "service", + "value": "backend" + } + ], + "inventory_mode": "DISABLED" + }, + { + "host": "backend02", + "name": "backend02", + "templates": [ + { + "name": "Template ZAS Agent" + } + ], + "groups": [ + { + "name": "Backend" + }, + { + "name": "Linux servers" + } + ], + "interfaces": [ + { + "useip": "NO", + "dns": "zas_backend_02", + "interface_ref": "if1" + } + ], + "tags": [ + { + "tag": "backend" + }, + { + "tag": "service", + "value": "backend" + } + ], + "inventory_mode": "DISABLED" + }, + { + "host": "frontend01", + "name": "frontend01", + "templates": [ + { + "name": "Template ZAS Agent" + } + ], + "groups": [ + { + "name": "Frontend" + }, + { + "name": "Linux servers" + } + ], + "interfaces": [ + { + "useip": "NO", + "dns": "zas_frontend_01", + "interface_ref": "if1" + } + ], + "tags": [ + { + "tag": "frontend" + }, + { + "tag": "service", + "value": "frontend" + } + ], + "inventory_mode": "DISABLED" + }, + { + "host": "frontend02", + "name": "frontend02", + "templates": [ + { + "name": "Template ZAS Agent" + } + ], + "groups": [ + { + "name": "Frontend" + }, + { + "name": "Linux servers" + } + ], + "interfaces": [ + { + "useip": "NO", + "dns": "zas_frontend_02", + "interface_ref": "if1" + } + ], + "tags": [ + { + "tag": "frontend" + }, + { + "tag": "service", + "value": "frontend" + } + ], + "inventory_mode": "DISABLED" + }, + { + "host": "Zabbix server", + "name": "Zabbix server", + "templates": [ + { + "name": "Linux by Zabbix agent" + }, + { + "name": "Zabbix server health" + } + ], + "groups": [ + { + "name": "Zabbix servers" + } + ], + "interfaces": [ + { + "useip": "NO", + "dns": "zabbix-agent", + "interface_ref": "if1" + } + ], + "inventory_mode": "DISABLED" + } + ], + "template_groups": [ + { + "uuid": "7df96b18c230490a9a0a9e2307226338", + "name": "Templates" + } + ], + "templates": [ + { + "uuid": "2d7a65bb369c48199361913b223b1695", + "template": "Template ZAS Agent", + "name": "Template ZAS Agent", + "templates": [ + { + "name": "Zabbix agent" + } + ], + "groups": [ + { + "name": "Templates" + } + ], + "items": [ + { + "uuid": "e79d4215ec014b74923b905bb8f82410", + "name": "Incoming network traffic on eth0", + "key": "net.if.in[eth0]", + "history": "1d", + "units": "bps", + "tags": [ + { + "tag": "Application", + "value": "Network interfaces" + } + ] + }, + { + "uuid": "18b377dae9fe48d093c16ee7a7c93320", + "name": "Outgoing network traffic on eth0", + "key": "net.if.out[eth0]", + "history": "1d", + "units": "bps", + "tags": [ + { + "tag": "Application", + "value": "Network interfaces" + } + ] + }, + { + "uuid": "2479e055e91c476f9be93b5f363cfa2f", + "name": "Processor load (1 min average per core)", + "key": "system.cpu.load[percpu,avg1]", + "history": "1d", + "value_type": "FLOAT", + "description": "The processor load is calculated as system CPU load divided by number of CPU cores.", + "tags": [ + { + "tag": "Application", + "value": "CPU" + }, + { + "tag": "Application", + "value": "Performance" + } + ], + "triggers": [ + { + "uuid": "60e5484b60ca4061b21bd23f8364bd6e", + "expression": "last(/Template ZAS Agent/system.cpu.load[percpu,avg1])>2", + "name": "Processor load is too high on {HOST.NAME}", + "priority": "WARNING", + "tags": [ + { + "tag": "app", + "value": "performance" + }, + { + "tag": "type", + "value": "cpu" + } + ] + } + ] + }, + { + "uuid": "f0dd4221793c49889cf2789806afa597", + "name": "Processor load (15 min average per core)", + "key": "system.cpu.load[percpu,avg15]", + "history": "1d", + "value_type": "FLOAT", + "description": "The processor load is calculated as system CPU load divided by number of CPU cores.", + "tags": [ + { + "tag": "Application", + "value": "CPU" + }, + { + "tag": "Application", + "value": "Performance" + } + ] + }, + { + "uuid": "9a8b4a1f173b4f209723d820dc2e054a", + "name": "CPU $2 time", + "key": "system.cpu.util[,iowait]", + "history": "1d", + "value_type": "FLOAT", + "units": "%", + "description": "Amount of time the CPU has been waiting for I/O to complete.", + "tags": [ + { + "tag": "Application", + "value": "CPU" + }, + { + "tag": "Application", + "value": "Performance" + } + ], + "triggers": [ + { + "uuid": "ceb468b9eb434fa6bd4c8a5d7507fd87", + "expression": "avg(/Template ZAS Agent/system.cpu.util[,iowait],5m)>20", + "name": "Disk I/O is overloaded on {HOST.NAME}", + "priority": "WARNING", + "description": "OS spends significant time waiting for I/O (input/output) operations. It could be indicator of performance issues with storage system.", + "tags": [ + { + "tag": "disk" + }, + { + "tag": "type", + "value": "disk" + } + ] + } + ] + }, + { + "uuid": "e6d19d47cf60452ead1e791da2d5c0dc", + "name": "CPU $2 time", + "key": "system.cpu.util[,system]", + "history": "1d", + "value_type": "FLOAT", + "units": "%", + "description": "The time the CPU has spent running the kernel and its processes.", + "tags": [ + { + "tag": "Application", + "value": "CPU" + }, + { + "tag": "Application", + "value": "Performance" + } + ] + }, + { + "uuid": "2d81fbc139774306959712a627c99b9a", + "name": "CPU $2 time", + "key": "system.cpu.util[,user]", + "history": "1d", + "value_type": "FLOAT", + "units": "%", + "description": "The time the CPU has spent running users' processes that are not niced.", + "tags": [ + { + "tag": "Application", + "value": "CPU" + }, + { + "tag": "Application", + "value": "Performance" + } + ] + } + ] + } + ], + "graphs": [ + { + "uuid": "7aac0ec0c0e04b7a8bb6472d1faa7a09", + "name": "CPU load", + "ymin_type_1": "FIXED", + "graph_items": [ + { + "color": "009900", + "item": { + "host": "Template ZAS Agent", + "key": "system.cpu.load[percpu,avg1]" + } + }, + { + "sortorder": "2", + "color": "990000", + "item": { + "host": "Template ZAS Agent", + "key": "system.cpu.load[percpu,avg15]" + } + } + ] + }, + { + "uuid": "f25064d88b964a678fac7ea6095b238a", + "name": "CPU utilization", + "show_triggers": "NO", + "type": "STACKED", + "ymin_type_1": "FIXED", + "ymax_type_1": "FIXED", + "graph_items": [ + { + "sortorder": "4", + "drawtype": "FILLED_REGION", + "color": "999900", + "item": { + "host": "Template ZAS Agent", + "key": "system.cpu.util[,iowait]" + } + }, + { + "sortorder": "5", + "drawtype": "FILLED_REGION", + "color": "990000", + "item": { + "host": "Template ZAS Agent", + "key": "system.cpu.util[,system]" + } + }, + { + "sortorder": "6", + "drawtype": "FILLED_REGION", + "color": "000099", + "item": { + "host": "Template ZAS Agent", + "key": "system.cpu.util[,user]" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/devenv/zabbix74/bootstrap/zbx_export_hosts.xml b/devenv/zabbix74/bootstrap/zbx_export_hosts.xml new file mode 100644 index 0000000..37c5991 --- /dev/null +++ b/devenv/zabbix74/bootstrap/zbx_export_hosts.xml @@ -0,0 +1,432 @@ + + + 6.2 + 2022-04-28T13:04:18Z + + + 2e427c268ac1468b9add94b65e2d6c14 + Backend + + + d97ba66b283544339628b71975a6e68d + Frontend + + + dc579cd7a1a34222933f24f52a68bcd8 + Linux servers + + + 6f6799aa69e844b4b3918f779f2abf08 + Zabbix servers + + + 7df96b18c230490a9a0a9e2307226338 + Templates + + + + + backend01 + backend01 + + + + + + Backend + + + Linux servers + + + + + NO + zas_backend_01 + if1 + + + + + backend + + + service + backend + + + DISABLED + + + backend02 + backend02 + + + + + + Backend + + + Linux servers + + + + + NO + zas_backend_02 + if1 + + + + + backend + + + service + backend + + + DISABLED + + + frontend01 + frontend01 + + + + + + Frontend + + + Linux servers + + + + + NO + zas_frontend_01 + if1 + + + + + frontend + + + service + frontend + + + DISABLED + + + frontend02 + frontend02 + + + + + + Frontend + + + Linux servers + + + + + NO + zas_frontend_02 + if1 + + + + + frontend + + + service + frontend + + + DISABLED + + + Zabbix server + Zabbix server + + + + + + + Zabbix servers + + + + + NO + zabbix-agent + if1 + + + DISABLED + + + + + + + + 7aac0ec0c0e04b7a8bb6472d1faa7a09 + CPU load + FIXED + + + 009900 + + Template ZAS Agent + system.cpu.load[percpu,avg1] + + + + 2 + 990000 + + Template ZAS Agent + system.cpu.load[percpu,avg15] + + + + + + f25064d88b964a678fac7ea6095b238a + CPU utilization + NO + STACKED + FIXED + FIXED + + + 4 + FILLED_REGION + 999900 + + Template ZAS Agent + system.cpu.util[,iowait] + + + + 5 + FILLED_REGION + 990000 + + Template ZAS Agent + system.cpu.util[,system] + + + + 6 + FILLED_REGION + 000099 + + Template ZAS Agent + system.cpu.util[,user] + + + + + + \ No newline at end of file diff --git a/devenv/zabbix74/docker-compose.yml b/devenv/zabbix74/docker-compose.yml new file mode 100644 index 0000000..28350f9 --- /dev/null +++ b/devenv/zabbix74/docker-compose.yml @@ -0,0 +1,117 @@ +services: + # Grafana + grafana: + image: grafana/grafana:main + ports: + - '3001:3000' + volumes: + - ../..:/grafana-zabbix + - ../dashboards:/devenv/dashboards + - ../grafana.ini:/etc/grafana/grafana.ini:ro + - '../datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml' + - '../dashboards.yaml:/etc/grafana/provisioning/dashboards/dashboards.yaml' + + # Zabbix + zabbix-server: + image: zabbix/zabbix-server-pgsql:alpine-7.4-latest + ports: + - '10051:10051' + depends_on: + - database + environment: + DB_SERVER_HOST: database + DB_SERVER_PORT: 5432 + POSTGRES_USER: zabbix + POSTGRES_PASSWORD: zabbix + POSTGRES_DB: zabbix + ZBX_TIMEOUT: 10 + ZBX_STARTPOLLERS: 10 + ZBX_STARTPOLLERSUNREACHABLE: 5 + ZBX_DEBUGLEVEL: 3 + + zabbix-web: + image: zabbix/zabbix-web-apache-pgsql:alpine-7.4-latest + ports: + - '8188:8080' + depends_on: + - database + - zabbix-server + environment: + ZBX_SERVER_HOST: zabbix-server + ZBX_SERVER_PORT: 10051 + DB_SERVER_HOST: database + DB_SERVER_PORT: 5432 + POSTGRES_USER: zabbix + POSTGRES_PASSWORD: zabbix + POSTGRES_DB: zabbix + + database: + image: postgres:16 + ports: + - '15432:5432' + command: postgres -c 'max_connections=1000' + environment: + POSTGRES_USER: zabbix + POSTGRES_PASSWORD: zabbix + + zabbix-agent: + image: zabbix/zabbix-agent:alpine-7.4-latest + environment: + ZBX_SERVER_HOST: zabbix-server + ZBX_SERVER_PORT: 10051 + + ######################################################### + # Bootstrap config + ######################################################### + + bootstrap: + build: ./bootstrap + environment: + ZBX_API_URL: http://zabbix-web:8080 + ZBX_API_USER: Admin + ZBX_API_PASSWORD: zabbix + depends_on: + - database + - zabbix-server + - zabbix-web + + ######################################################### + # Fake agents + ######################################################### + + # backend + redis_backend: + image: redis:alpine + + zas_backend_01: + build: ../zas-agent + volumes: + - ../zas-agent/conf/zas_scenario_backend.cfg:/etc/zas_scenario.cfg + environment: + REDIS_HOST: redis_backend + # restart: always + + zas_backend_02: + build: ../zas-agent + volumes: + - ../zas-agent/conf/zas_scenario_backend.cfg:/etc/zas_scenario.cfg + environment: + REDIS_HOST: redis_backend + + # frontend + redis_frontend: + image: redis:alpine + + zas_frontend_01: + build: ../zas-agent + volumes: + - ../zas-agent/conf/zas_scenario_frontend.cfg:/etc/zas_scenario.cfg + environment: + REDIS_HOST: redis_frontend + + zas_frontend_02: + build: ../zas-agent + volumes: + - ../zas-agent/conf/zas_scenario_frontend.cfg:/etc/zas_scenario.cfg + environment: + REDIS_HOST: redis_frontend \ No newline at end of file diff --git a/pkg/zabbixapi/zabbix_api_74_integration_test.go b/pkg/zabbixapi/zabbix_api_74_integration_test.go new file mode 100644 index 0000000..32516ca --- /dev/null +++ b/pkg/zabbixapi/zabbix_api_74_integration_test.go @@ -0,0 +1,161 @@ +package zabbixapi + +import ( + "bytes" + "context" + "encoding/json" + "io" + "net/http" + "os" + "testing" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// These tests require a running Zabbix server and proper environment variables +// ZABBIX_URL - URL of the Zabbix server (e.g., http://localhost/zabbix/api_jsonrpc.php) +// ZABBIX_USER - Username for authentication +// ZABBIX_PASSWORD - Password for authentication +// To run locally, start devenv/zabbix74 and run INTEGRATION_TEST74=true ZABBIX_URL="http://localhost:8188/api_jsonrpc.php" ZABBIX_USER="Admin" ZABBIX_PASSWORD="zabbix" go test -v ./pkg/zabbixapi/... + +func TestIntegrationZabbixAPI74(t *testing.T) { + // Skip if not running integration tests + if os.Getenv("INTEGRATION_TEST74") != "true" { + t.Skip("Skipping integration test") + } + + // Get test configuration from environment + zabbixURL := os.Getenv("ZABBIX_URL") + zabbixUser := os.Getenv("ZABBIX_USER") + zabbixPassword := os.Getenv("ZABBIX_PASSWORD") + zabbixVersion := 74 + + // Validate required environment variables + require.NotEmpty(t, zabbixURL, "ZABBIX_URL environment variable is required") + require.NotEmpty(t, zabbixUser, "ZABBIX_USER environment variable is required") + require.NotEmpty(t, zabbixPassword, "ZABBIX_PASSWORD environment variable is required") + + // Create new Zabbix API instance + dsSettings := backend.DataSourceInstanceSettings{ + URL: zabbixURL, + } + api, err := New(dsSettings, nil) + require.NoError(t, err) + require.NotNil(t, api) + + // Test authentication + t.Run("Authentication", func(t *testing.T) { + err := api.Authenticate(context.Background(), zabbixUser, zabbixPassword, zabbixVersion) + require.NoError(t, err) + assert.NotEmpty(t, api.GetAuth(), "Authentication token should not be empty") + }) + + // Test API version check + t.Run("API Version Check", func(t *testing.T) { + // Try to get API version + resp, err := api.RequestUnauthenticated(context.Background(), "apiinfo.version", map[string]interface{}{}, zabbixVersion) + require.NoError(t, err) + require.NotNil(t, resp) + + version := resp.MustString() + assert.NotEmpty(t, version, "API version should not be empty") + }) + + // Test host group retrieval + t.Run("Get Host Groups", func(t *testing.T) { + // First authenticate + err := api.Authenticate(context.Background(), zabbixUser, zabbixPassword, zabbixVersion) + require.NoError(t, err) + + // Get host groups + params := map[string]interface{}{ + "output": "extend", + } + resp, err := api.Request(context.Background(), "hostgroup.get", params, zabbixVersion) + require.NoError(t, err) + require.NotNil(t, resp) + + // Verify response is an array + groups, err := resp.Array() + require.NoError(t, err) + assert.NotNil(t, groups, "Host groups should not be nil") + }) + + // Test error handling + t.Run("Error Handling", func(t *testing.T) { + // Try to make a request without authentication + api.SetAuth("") + _, err := api.Request(context.Background(), "hostgroup.get", map[string]interface{}{}, zabbixVersion) + assert.Error(t, err) + assert.True(t, backend.IsDownstreamError(err)) + }) + + // Test auth parameter is not in request body for v7.2+ + t.Run("Auth Parameter Not In Request Body", func(t *testing.T) { + // First authenticate + err := api.Authenticate(context.Background(), zabbixUser, zabbixPassword, zabbixVersion) + require.NoError(t, err) + + // Create a test client that captures the request body + var requestBody map[string]interface{} + testClient := NewTestClient(func(req *http.Request) *http.Response { + // Read and parse the request body + body, err := io.ReadAll(req.Body) + require.NoError(t, err) + err = json.Unmarshal(body, &requestBody) + require.NoError(t, err) + + // Verify auth header is present + assert.Equal(t, "Bearer "+api.GetAuth(), req.Header.Get("Authorization"), "Authorization header should be present with Bearer token") + + // Return a mock response + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(`{"result": "test"}`)), + } + }) + + // Create a new API instance with the test client + apiWithTestClient, err := New(dsSettings, testClient) + require.NoError(t, err) + apiWithTestClient.SetAuth(api.GetAuth()) + + // Make a request + _, err = apiWithTestClient.Request(context.Background(), "test.get", map[string]interface{}{}, zabbixVersion) + require.NoError(t, err) + + // Verify auth parameter is not in the request body + _, hasAuth := requestBody["auth"] + assert.False(t, hasAuth, "Auth parameter should not be present in request body for v7.2+") + }) + + // Test basic auth is not supported in v7.2+ + t.Run("Basic Auth Not Supported", func(t *testing.T) { + // Create settings with basic auth enabled + dsSettingsWithBasicAuth := backend.DataSourceInstanceSettings{ + URL: zabbixURL, + BasicAuthEnabled: true, + BasicAuthUser: zabbixUser, + } + + // Create a new API instance with basic auth enabled + apiWithBasicAuth, err := New(dsSettingsWithBasicAuth, nil) + require.NoError(t, err) + require.NotNil(t, apiWithBasicAuth) + + // Get host groups + params := map[string]interface{}{ + "output": "extend", + } + + apiWithBasicAuth.SetAuth("something") + + // Try to authenticate + _, err = apiWithBasicAuth.Request(context.Background(), "hostgroup.get", params, zabbixVersion) + require.Error(t, err) + assert.Contains(t, err.Error(), "Basic Auth is not supported for Zabbix v7.2 and later") + assert.True(t, backend.IsDownstreamError(err)) + }) +}