Add compatibility workflows and integration tests (#1991)
Fixes #1986 Fixes #1994 - Updated .gitignore to include SSL certificate files. - Introduced new GitHub Actions workflows for testing compatibility with Zabbix versions 5.0, 6.0, 7.0, and 7.2. - Added integration tests for Zabbix API for each version, ensuring proper authentication and API version handling. - Updated Docker Compose files to support SSL configuration for Zabbix web services. - Removed deprecated default Docker Compose and bootstrap files. - Removed devenv for version 6.2.
This commit is contained in:
@@ -58,7 +58,7 @@ func newZabbixDatasourceInstance(ctx context.Context, dsSettings backend.DataSou
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zabbixAPI, err := zabbixapi.New(dsSettings.URL, client)
|
||||
zabbixAPI, err := zabbixapi.New(dsSettings, client)
|
||||
if err != nil {
|
||||
logger.Error("Error initializing Zabbix API", "error", err)
|
||||
return nil, err
|
||||
|
||||
@@ -26,6 +26,7 @@ var (
|
||||
// ZabbixAPI is a simple client responsible for making request to Zabbix API
|
||||
type ZabbixAPI struct {
|
||||
url *url.URL
|
||||
dsSettings backend.DataSourceInstanceSettings
|
||||
httpClient *http.Client
|
||||
logger log.Logger
|
||||
auth string
|
||||
@@ -34,15 +35,16 @@ type ZabbixAPI struct {
|
||||
type ZabbixAPIParams = map[string]interface{}
|
||||
|
||||
// New returns new ZabbixAPI instance initialized with given URL or error.
|
||||
func New(apiURL string, client *http.Client) (*ZabbixAPI, error) {
|
||||
func New(dsSettings backend.DataSourceInstanceSettings, client *http.Client) (*ZabbixAPI, error) {
|
||||
apiLogger := log.New()
|
||||
zabbixURL, err := url.Parse(apiURL)
|
||||
zabbixURL, err := url.Parse(dsSettings.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ZabbixAPI{
|
||||
url: zabbixURL,
|
||||
dsSettings: dsSettings,
|
||||
logger: apiLogger,
|
||||
httpClient: client,
|
||||
}, nil
|
||||
@@ -98,7 +100,7 @@ func (api *ZabbixAPI) request(ctx context.Context, method string, params ZabbixA
|
||||
|
||||
// Zabbix v7.2 and later deprecated `auth` parameter and replaced it with using Auth header
|
||||
// `auth` parameter throws an error in new versions so we need to add it only for older versions
|
||||
if auth != "" && version < 70 {
|
||||
if auth != "" && version < 72 {
|
||||
apiRequest["auth"] = auth
|
||||
}
|
||||
|
||||
@@ -114,7 +116,10 @@ func (api *ZabbixAPI) request(ctx context.Context, method string, params ZabbixA
|
||||
|
||||
metrics.ZabbixAPIQueryTotal.WithLabelValues(method).Inc()
|
||||
|
||||
if auth != "" {
|
||||
if auth != "" && version >= 72 {
|
||||
if api.dsSettings.BasicAuthEnabled {
|
||||
return nil, backend.DownstreamError(errors.New("Basic Auth is not supported for Zabbix v7.2 and later"))
|
||||
}
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", auth))
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
148
pkg/zabbixapi/zabbix_api_50_integration_test.go
Normal file
148
pkg/zabbixapi/zabbix_api_50_integration_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package zabbixapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/httpclient"
|
||||
"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/zabbix50 and run INTEGRATION_TEST50=true ZABBIX_URL="https://localhost/api_jsonrpc.php" ZABBIX_USER="Admin" ZABBIX_PASSWORD="zabbix" go test -v ./pkg/zabbixapi/...
|
||||
func TestIntegrationZabbixAPI50(t *testing.T) {
|
||||
// Skip if not running integration tests
|
||||
if os.Getenv("INTEGRATION_TEST50") != "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 := 50
|
||||
|
||||
// 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,
|
||||
BasicAuthEnabled: true,
|
||||
BasicAuthUser: "admin",
|
||||
DecryptedSecureJSONData: map[string]string{
|
||||
"basicAuthPassword": "secret",
|
||||
},
|
||||
JSONData: json.RawMessage(`{"tlsSkipVerify": true}`),
|
||||
}
|
||||
|
||||
// Create HTTP client with TLS skip verify and basic auth
|
||||
httpClient, err := httpclient.New(context.Background(), &dsSettings, 10*time.Second)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, httpClient)
|
||||
|
||||
// Create new Zabbix API instance with basic auth client
|
||||
api, err := New(dsSettings, httpClient)
|
||||
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 in request body for v5.0
|
||||
t.Run("Auth Parameter 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 not present
|
||||
assert.Empty(t, req.Header.Get("Authorization"), "Authorization header should not be present for v5.0")
|
||||
|
||||
// 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 in the request body
|
||||
auth, hasAuth := requestBody["auth"]
|
||||
assert.True(t, hasAuth, "Auth parameter should be present in request body for v5.0")
|
||||
assert.Equal(t, api.GetAuth(), auth, "Auth parameter should match the set auth token")
|
||||
})
|
||||
}
|
||||
147
pkg/zabbixapi/zabbix_api_60_integration_test.go
Normal file
147
pkg/zabbixapi/zabbix_api_60_integration_test.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package zabbixapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/httpclient"
|
||||
"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/zabbix60 and run INTEGRATION_TEST60=true ZABBIX_URL="https://localhost/api_jsonrpc.php" ZABBIX_USER="Admin" ZABBIX_PASSWORD="zabbix" go test -v ./pkg/zabbixapi/...
|
||||
func TestIntegrationZabbixAPI60(t *testing.T) {
|
||||
// Skip if not running integration tests
|
||||
if os.Getenv("INTEGRATION_TEST60") != "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 := 60
|
||||
|
||||
// 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")
|
||||
|
||||
dsSettings := backend.DataSourceInstanceSettings{
|
||||
URL: zabbixURL,
|
||||
BasicAuthEnabled: true,
|
||||
BasicAuthUser: "admin",
|
||||
DecryptedSecureJSONData: map[string]string{
|
||||
"basicAuthPassword": "secret",
|
||||
},
|
||||
JSONData: json.RawMessage(`{"tlsSkipVerify": true}`),
|
||||
}
|
||||
|
||||
// Create HTTP client with TLS skip verify and basic auth
|
||||
httpClient, err := httpclient.New(context.Background(), &dsSettings, 10*time.Second)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, httpClient)
|
||||
|
||||
// Create new Zabbix API instance with basic auth client
|
||||
api, err := New(dsSettings, httpClient)
|
||||
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 in request body for v6.0
|
||||
t.Run("Auth Parameter 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 not present
|
||||
assert.Empty(t, req.Header.Get("Authorization"), "Authorization header should not be present for v6.0")
|
||||
|
||||
// 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 in the request body
|
||||
auth, hasAuth := requestBody["auth"]
|
||||
assert.True(t, hasAuth, "Auth parameter should be present in request body for v6.0")
|
||||
assert.Equal(t, api.GetAuth(), auth, "Auth parameter should match the set auth token")
|
||||
})
|
||||
}
|
||||
149
pkg/zabbixapi/zabbix_api_70_integration_test.go
Normal file
149
pkg/zabbixapi/zabbix_api_70_integration_test.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package zabbixapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/httpclient"
|
||||
"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
|
||||
// ZABBIX_VERSION - Zabbix API version (e.g., 65 for 6.5)
|
||||
// To run locally, start devenv/zabbix70 and run INTEGRATION_TEST70=true ZABBIX_URL="https://localhost/api_jsonrpc.php" ZABBIX_USER="Admin" ZABBIX_PASSWORD="zabbix" go test -v ./pkg/zabbixapi/...
|
||||
|
||||
func TestIntegrationZabbixAPI70(t *testing.T) {
|
||||
// Skip if not running integration tests
|
||||
if os.Getenv("INTEGRATION_TEST70") != "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 := 70
|
||||
|
||||
// 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")
|
||||
|
||||
dsSettings := backend.DataSourceInstanceSettings{
|
||||
URL: zabbixURL,
|
||||
BasicAuthEnabled: true,
|
||||
BasicAuthUser: "admin",
|
||||
DecryptedSecureJSONData: map[string]string{
|
||||
"basicAuthPassword": "secret",
|
||||
},
|
||||
JSONData: json.RawMessage(`{"tlsSkipVerify": true}`),
|
||||
}
|
||||
|
||||
// Create HTTP client with TLS skip verify and basic auth
|
||||
httpClient, err := httpclient.New(context.Background(), &dsSettings, 10*time.Second)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, httpClient)
|
||||
|
||||
// Create new Zabbix API instance with basic auth client
|
||||
api, err := New(dsSettings, httpClient)
|
||||
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 in request body for v7.0
|
||||
t.Run("Auth Parameter 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 not present
|
||||
assert.Empty(t, req.Header.Get("Authorization"), "Authorization header should not be present for v7.0")
|
||||
|
||||
// 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 in the request body
|
||||
auth, hasAuth := requestBody["auth"]
|
||||
assert.True(t, hasAuth, "Auth parameter should be present in request body for v7.0")
|
||||
assert.Equal(t, api.GetAuth(), auth, "Auth parameter should match the set auth token")
|
||||
})
|
||||
}
|
||||
161
pkg/zabbixapi/zabbix_api_72_integration_test.go
Normal file
161
pkg/zabbixapi/zabbix_api_72_integration_test.go
Normal file
@@ -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/zabbix72 and run INTEGRATION_TEST72=true ZABBIX_URL="http://localhost:8188/api_jsonrpc.php" ZABBIX_USER="Admin" ZABBIX_PASSWORD="zabbix" go test -v ./pkg/zabbixapi/...
|
||||
|
||||
func TestIntegrationZabbixAPI72(t *testing.T) {
|
||||
// Skip if not running integration tests
|
||||
if os.Getenv("INTEGRATION_TEST72") != "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 := 72
|
||||
|
||||
// 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))
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user