diff --git a/.github/scripts/compatibility_api_test_5.py b/.github/scripts/compatibility_api_test_5.py deleted file mode 100644 index 009e2a1..0000000 --- a/.github/scripts/compatibility_api_test_5.py +++ /dev/null @@ -1,385 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2001-2023 Zabbix SIA -# -# Zabbix SIA licenses this file under the MIT License. -# See the LICENSE file in the project root for more information. - -import sys -import time -import unittest - -sys.path.append('.') -from zabbix_utils.api import ZabbixAPI -from zabbix_utils.sender import Sender -from zabbix_utils.getter import Getter -from zabbix_utils.aioapi import AsyncZabbixAPI -from zabbix_utils.aiosender import AsyncSender -from zabbix_utils.aiogetter import AsyncGetter -from zabbix_utils.exceptions import APIRequestError, APINotSupported -from zabbix_utils.types import AgentResponse, ItemValue, TrapperResponse, APIVersion - -ZABBIX_URL = '127.0.0.1' -ZABBIX_USER = 'Admin' -ZABBIX_PASSWORD = 'zabbix' - - -class CompatibilityAPITest(unittest.TestCase): - """Compatibility synchronous test with Zabbix API version 5.0""" - - def setUp(self): - self.url = ZABBIX_URL - self.user = ZABBIX_USER - self.password = ZABBIX_PASSWORD - self.token = 'token' - self.zapi = ZabbixAPI( - url=self.url - ) - - def test_classic_auth(self): - """Tests classic auth using username and password""" - - self.assertEqual( - type(self.zapi), ZabbixAPI, "Creating ZabbixAPI object was going wrong") - - self.assertEqual( - type(self.zapi.api_version()), APIVersion, "Version getting was going wrong") - - self.zapi.login( - user=self.user, - password=self.password - ) - - self.assertIsNotNone(self.zapi._ZabbixAPI__session_id, "Login by user and password was going wrong") - - resp = self.zapi.user.checkAuthentication(sessionid=self.zapi._ZabbixAPI__session_id) - - self.assertEqual( - type(resp), dict, "Request user.checkAuthentication was going wrong") - - users = self.zapi.user.get( - output=['userid', 'name'] - ) - self.assertEqual(type(users), list, "Request user.get was going wrong") - - self.zapi.logout() - - self.assertIsNone(self.zapi._ZabbixAPI__session_id, "Logout was going wrong") - - with self.assertRaises(APIRequestError, - msg="Request user.checkAuthentication after logout was going wrong"): - resp = self.zapi.user.checkAuthentication(sessionid=(self.zapi._ZabbixAPI__session_id or '')) - - def test_token_auth(self): - """Tests auth using token""" - - with self.assertRaises(APINotSupported, - msg="Login by token should be not supported"): - self.zapi.login(token=self.token) - - -class CompatibilitySenderTest(unittest.TestCase): - """Compatibility synchronous test with Zabbix sender version 5.0""" - - def setUp(self): - self.ip = ZABBIX_URL - self.port = 10051 - self.chunk_size = 10 - self.sender = Sender( - server=self.ip, - port=self.port, - chunk_size=self.chunk_size - ) - self.hostname = f"{self.__class__.__name__}_host" - self.itemname = f"{self.__class__.__name__}_item" - self.itemkey = f"{self.__class__.__name__}" - self.prepare_items() - - def prepare_items(self): - """Creates host and items for sending values later""" - - zapi = ZabbixAPI( - url=ZABBIX_URL, - user=ZABBIX_USER, - password=ZABBIX_PASSWORD, - skip_version_check=True - ) - - hosts = zapi.host.get( - filter={'host': self.hostname}, - output=['hostid'] - ) - - hostid = None - if len(hosts) > 0: - hostid = hosts[0].get('hostid') - - if not hostid: - hostid = zapi.host.create( - host=self.hostname, - interfaces=[{ - "type": 1, - "main": 1, - "useip": 1, - "ip": "127.0.0.1", - "dns": "", - "port": "10050" - }], - groups=[{"groupid": "2"}] - )['hostids'][0] - - self.assertIsNotNone(hostid, "Creating test host was going wrong") - - items = zapi.item.get( - filter={'key_': self.itemkey}, - output=['itemid'] - ) - - itemid = None - if len(items) > 0: - itemid = items[0].get('itemid') - - if not itemid: - itemid = zapi.item.create( - name=self.itemname, - key_=self.itemkey, - hostid=hostid, - type=2, - value_type=3 - )['itemids'][0] - - self.assertIsNotNone(hostid, "Creating test item was going wrong") - - zapi.logout() - - def test_send_values(self): - """Tests sending item values""" - - time.sleep(10) - - items = [ - ItemValue(self.hostname, self.itemkey, 10), - ItemValue(self.hostname, self.itemkey, 'test message'), - ItemValue(self.hostname, 'item_key1', -1, 1695713666), - ItemValue(self.hostname, 'item_key2', '{"msg":"test message"}'), - ItemValue(self.hostname, self.itemkey, 0, 1695713666, 100), - ItemValue(self.hostname, self.itemkey, 5.5, 1695713666) - ] - resp = self.sender.send(items) - self.assertEqual(type(resp), TrapperResponse, "Sending item values was going wrong") - self.assertEqual(resp.total, len(items), "Total number of the sent values is unexpected") - self.assertEqual(resp.processed, 4, "Number of the processed values is unexpected") - self.assertEqual(resp.failed, (resp.total - resp.processed), "Number of the failed values is unexpected") - - first_chunk = list(resp.details.values())[0][0] - self.assertEqual(type(first_chunk), TrapperResponse, "Sending item values was going wrong") - self.assertEqual(first_chunk.total, len(items), "Total number of the sent values is unexpected") - self.assertEqual(first_chunk.processed, 4, "Number of the processed values is unexpected") - self.assertEqual(first_chunk.failed, (first_chunk.total - first_chunk.processed), "Number of the failed values is unexpected") - - -class CompatibilityGetTest(unittest.TestCase): - """Compatibility synchronous test with Zabbix get version 5.0""" - - def setUp(self): - self.host = ZABBIX_URL - self.port = 10050 - self.agent = Getter( - host=self.host, - port=self.port - ) - - def test_get_values(self): - """Tests getting item values""" - - resp = self.agent.get('system.uname') - - self.assertIsNotNone(resp, "Getting item values was going wrong") - self.assertEqual(type(resp), AgentResponse, "Got value is unexpected") - self.assertEqual(type(resp.value), str, "Got value is unexpected") - - -class CompatibilityAsyncAPITest(unittest.IsolatedAsyncioTestCase): - """Compatibility asynchronous test with Zabbix API version 5.0""" - - async def asyncSetUp(self): - self.url = ZABBIX_URL - self.user = ZABBIX_USER - self.password = ZABBIX_PASSWORD - self.token = 'token' - self.zapi = AsyncZabbixAPI( - url=self.url - ) - - async def asyncTearDown(self): - if self.zapi: - await self.zapi.logout() - - async def test_classic_auth(self): - """Tests auth using username and password""" - - self.assertEqual( - type(self.zapi), AsyncZabbixAPI, "Creating AsyncZabbixAPI object was going wrong") - - self.assertEqual( - type(self.zapi.api_version()), APIVersion, "Version getting was going wrong") - - await self.zapi.login( - user=self.user, - password=self.password - ) - - self.assertIsNotNone(self.zapi._AsyncZabbixAPI__session_id, "Login by user and password was going wrong") - - resp = await self.zapi.user.checkAuthentication(sessionid=self.zapi._AsyncZabbixAPI__session_id) - - self.assertEqual( - type(resp), dict, "Request user.checkAuthentication was going wrong") - - users = await self.zapi.user.get( - output=['userid', 'name'] - ) - self.assertEqual(type(users), list, "Request user.get was going wrong") - - await self.zapi.logout() - - self.assertIsNone(self.zapi._AsyncZabbixAPI__session_id, "Logout was going wrong") - - with self.assertRaises(RuntimeError, - msg="Request user.checkAuthentication after logout was going wrong"): - resp = await self.zapi.user.checkAuthentication(sessionid=(self.zapi._AsyncZabbixAPI__session_id or '')) - - async def test_token_auth(self): - """Tests auth using token""" - - with self.assertRaises(APINotSupported, - msg="Login by token should be not supported"): - await self.zapi.login(token=self.token) - - -class CompatibilityAsyncSenderTest(unittest.IsolatedAsyncioTestCase): - """Compatibility asynchronous test with Zabbix sender version 5.0""" - - async def asyncSetUp(self): - self.ip = ZABBIX_URL - self.port = 10051 - self.chunk_size = 10 - self.sender = AsyncSender( - server=self.ip, - port=self.port, - chunk_size=self.chunk_size - ) - self.hostname = f"{self.__class__.__name__}_host" - self.itemname = f"{self.__class__.__name__}_item" - self.itemkey = f"{self.__class__.__name__}" - await self.prepare_items() - - async def prepare_items(self): - """Creates host and items for sending values later""" - - zapi = AsyncZabbixAPI( - url=ZABBIX_URL, - skip_version_check=True - ) - await zapi.login( - user=ZABBIX_USER, - password=ZABBIX_PASSWORD - ) - - hosts = await zapi.host.get( - filter={'host': self.hostname}, - output=['hostid'] - ) - - hostid = None - if len(hosts) > 0: - hostid = hosts[0].get('hostid') - - if not hostid: - created_host = await zapi.host.create( - host=self.hostname, - interfaces=[{ - "type": 1, - "main": 1, - "useip": 1, - "ip": "127.0.0.1", - "dns": "", - "port": "10050" - }], - groups=[{"groupid": "2"}] - ) - hostid = created_host['hostids'][0] - - self.assertIsNotNone(hostid, "Creating test host was going wrong") - - items = await zapi.item.get( - filter={'key_': self.itemkey}, - output=['itemid'] - ) - - itemid = None - if len(items) > 0: - itemid = items[0].get('itemid') - - if not itemid: - created_item = await zapi.item.create( - name=self.itemname, - key_=self.itemkey, - hostid=hostid, - type=2, - value_type=3 - ) - itemid = created_item['itemids'][0] - - self.assertIsNotNone(hostid, "Creating test item was going wrong") - - await zapi.logout() - - async def test_send_values(self): - """Tests sending item values""" - - time.sleep(10) - - items = [ - ItemValue(self.hostname, self.itemkey, 10), - ItemValue(self.hostname, self.itemkey, 'test message'), - ItemValue(self.hostname, 'item_key1', -1, 1695713666), - ItemValue(self.hostname, 'item_key2', '{"msg":"test message"}'), - ItemValue(self.hostname, self.itemkey, 0, 1695713666, 100), - ItemValue(self.hostname, self.itemkey, 5.5, 1695713666) - ] - resp = await self.sender.send(items) - self.assertEqual(type(resp), TrapperResponse, "Sending item values was going wrong") - self.assertEqual(resp.total, len(items), "Total number of the sent values is unexpected") - self.assertEqual(resp.processed, 4, "Number of the processed values is unexpected") - self.assertEqual(resp.failed, (resp.total - resp.processed), "Number of the failed values is unexpected") - - first_chunk = list(resp.details.values())[0][0] - self.assertEqual(type(first_chunk), TrapperResponse, "Sending item values was going wrong") - self.assertEqual(first_chunk.total, len(items), "Total number of the sent values is unexpected") - self.assertEqual(first_chunk.processed, 4, "Number of the processed values is unexpected") - self.assertEqual(first_chunk.failed, (first_chunk.total - first_chunk.processed), "Number of the failed values is unexpected") - - -class CompatibilityAsyncGetTest(unittest.IsolatedAsyncioTestCase): - """Compatibility asynchronous test with Zabbix get version 5.0""" - - async def asyncSetUp(self): - self.host = ZABBIX_URL - self.port = 10050 - self.agent = AsyncGetter( - host=self.host, - port=self.port - ) - - async def test_get_values(self): - """Tests getting item values""" - - resp = await self.agent.get('system.uname') - - self.assertIsNotNone(resp, "Getting item values was going wrong") - self.assertEqual(type(resp), AgentResponse, "Got value is unexpected") - self.assertEqual(type(resp.value), str, "Got value is unexpected") - - -if __name__ == '__main__': - unittest.main() diff --git a/.github/scripts/compatibility_api_test_7.py b/.github/scripts/compatibility_api_test_7.py index cb944ee..6818620 100644 --- a/.github/scripts/compatibility_api_test_7.py +++ b/.github/scripts/compatibility_api_test_7.py @@ -25,7 +25,7 @@ class CompatibilityAPITest(unittest.TestCase): - """Compatibility synchronous test with Zabbix API version 7.0, 7.2""" + """Compatibility synchronous test with Zabbix API version 7.0, 7.2 and 7.4""" def setUp(self): self.url = ZABBIX_URL @@ -111,7 +111,7 @@ def test_token_auth(self): class CompatibilitySenderTest(unittest.TestCase): - """Compatibility synchronous test with Zabbix sender version 7.0, 7.2""" + """Compatibility synchronous test with Zabbix sender version 7.0, 7.2 and 7.4""" def setUp(self): self.ip = ZABBIX_URL @@ -286,7 +286,7 @@ def test_send_values(self): class CompatibilityGetTest(unittest.TestCase): - """Compatibility synchronous test with Zabbix get version 7.0, 7.2""" + """Compatibility synchronous test with Zabbix get version 7.0, 7.2 and 7.4""" def setUp(self): self.host = ZABBIX_URL @@ -307,7 +307,7 @@ def test_get_values(self): class CompatibilityAsyncAPITest(unittest.IsolatedAsyncioTestCase): - """Compatibility asynchronous test with Zabbix API version 7.0, 7.2""" + """Compatibility asynchronous test with Zabbix API version 7.0, 7.2 and 7.4""" async def asyncSetUp(self): self.url = ZABBIX_URL @@ -399,7 +399,7 @@ async def test_token_auth(self): class CompatibilityAsyncSenderTest(unittest.IsolatedAsyncioTestCase): - """Compatibility asynchronous test with Zabbix sender version 7.0, 7.2""" + """Compatibility asynchronous test with Zabbix sender version 7.0, 7.2 and 7.4""" async def asyncSetUp(self): self.ip = ZABBIX_URL @@ -580,7 +580,7 @@ async def test_send_values(self): class CompatibilityAsyncGetTest(unittest.IsolatedAsyncioTestCase): - """Compatibility asynchronous test with Zabbix get version 7.0, 7.2""" + """Compatibility asynchronous test with Zabbix get version 7.0, 7.2 and 7.4""" async def asyncSetUp(self): self.host = ZABBIX_URL diff --git a/.github/workflows/additional_tests.yaml b/.github/workflows/additional_tests.yaml index 1478992..5edf088 100644 --- a/.github/workflows/additional_tests.yaml +++ b/.github/workflows/additional_tests.yaml @@ -16,10 +16,10 @@ env: jobs: importing-tests: name: Importing tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Install Python run: | sudo apt update && sudo apt-get install -y python3 python3-pip python-is-python3 @@ -58,10 +58,10 @@ jobs: test $(cat /tmp/importing.log | wc -l) -eq 0 || exit 1 additional-tests: name: Additional tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Install packages run: | sudo apt update && sudo apt install -y git sudo nginx gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev diff --git a/.github/workflows/compatibility_60.yaml b/.github/workflows/compatibility_60.yaml index 2ce68ba..c163288 100644 --- a/.github/workflows/compatibility_60.yaml +++ b/.github/workflows/compatibility_60.yaml @@ -17,10 +17,10 @@ env: jobs: compatibility: name: Compatibility test - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Install packages run: | sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev diff --git a/.github/workflows/compatibility_70.yaml b/.github/workflows/compatibility_70.yaml index ad14899..4b77652 100644 --- a/.github/workflows/compatibility_70.yaml +++ b/.github/workflows/compatibility_70.yaml @@ -17,17 +17,19 @@ env: jobs: compatibility: name: Compatibility test - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Install packages run: | - sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev zabbix-sender + sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-16 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.3-pgsql php8.3-bcmath php8.3-xml php8.3-gd php8.3-ldap php8.3-mbstring libzip-dev - name: Build from sources run: | WORKDIR=$(pwd) cd /tmp/ + sudo addgroup --system --quiet zabbix + sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix git -c advice.detachedHead=false clone https://git.zabbix.com/scm/zbx/zabbix.git --branch ${{ env.ZABBIX_BRANCH }} --depth 1 --single-branch /tmp/zabbix-branch cd /tmp/zabbix-branch ./bootstrap.sh @@ -59,21 +61,19 @@ jobs: sudo rm /var/www/html/index.html sudo cp -a . /var/www/html/ sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/zabbix.conf.php /var/www/html/conf/ - sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/14/main/pg_hba.conf + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf sudo chown -R www-data:www-data /var/www/html/ - sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.1/apache2/php.ini + sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.3/apache2/php.ini sudo locale-gen en_US.UTF-8 sudo update-locale - name: Prepare environment run: | - sudo addgroup --system --quiet zabbix - sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix - sudo mkdir -p /var/run/postgresql/14-main.pg_stat_tmp - sudo touch /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - sudo chmod 0777 /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - (sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf)& + sudo mkdir -p /var/run/postgresql/16-main.pg_stat_tmp + sudo touch /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + sudo chmod 0777 /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + (sudo -u postgres /usr/lib/postgresql/16/bin/postgres -D /var/lib/postgresql/16/main -c config_file=/etc/postgresql/16/main/postgresql.conf)& sleep 5 cd /tmp/zabbix-branch/database/postgresql sudo -u postgres createuser zabbix diff --git a/.github/workflows/compatibility_72.yaml b/.github/workflows/compatibility_72.yaml index 73ef9d3..5a35247 100644 --- a/.github/workflows/compatibility_72.yaml +++ b/.github/workflows/compatibility_72.yaml @@ -17,17 +17,19 @@ env: jobs: compatibility: name: Compatibility test - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Install packages run: | - sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev zabbix-sender + sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-16 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.3-pgsql php8.3-bcmath php8.3-xml php8.3-gd php8.3-ldap php8.3-mbstring libzip-dev - name: Build from sources run: | WORKDIR=$(pwd) cd /tmp/ + sudo addgroup --system --quiet zabbix + sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix git -c advice.detachedHead=false clone https://git.zabbix.com/scm/zbx/zabbix.git --branch ${{ env.ZABBIX_BRANCH }} --depth 1 --single-branch /tmp/zabbix-branch cd /tmp/zabbix-branch ./bootstrap.sh @@ -59,21 +61,19 @@ jobs: sudo rm /var/www/html/index.html sudo cp -a . /var/www/html/ sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/zabbix.conf.php /var/www/html/conf/ - sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/14/main/pg_hba.conf + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf sudo chown -R www-data:www-data /var/www/html/ - sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.1/apache2/php.ini + sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.3/apache2/php.ini sudo locale-gen en_US.UTF-8 sudo update-locale - name: Prepare environment run: | - sudo addgroup --system --quiet zabbix - sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix - sudo mkdir -p /var/run/postgresql/14-main.pg_stat_tmp - sudo touch /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - sudo chmod 0777 /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - (sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf)& + sudo mkdir -p /var/run/postgresql/16-main.pg_stat_tmp + sudo touch /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + sudo chmod 0777 /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + (sudo -u postgres /usr/lib/postgresql/16/bin/postgres -D /var/lib/postgresql/16/main -c config_file=/etc/postgresql/16/main/postgresql.conf)& sleep 5 cd /tmp/zabbix-branch/database/postgresql sudo -u postgres createuser zabbix diff --git a/.github/workflows/compatibility_50.yaml b/.github/workflows/compatibility_74.yaml similarity index 56% rename from .github/workflows/compatibility_50.yaml rename to .github/workflows/compatibility_74.yaml index d52c882..5f7247b 100644 --- a/.github/workflows/compatibility_50.yaml +++ b/.github/workflows/compatibility_74.yaml @@ -1,5 +1,5 @@ -name: zabbix_50 -run-name: Compatibility with Zabbix 5.0 test +name: zabbix_74 +run-name: Compatibility with Zabbix 7.4 test on: push: @@ -9,27 +9,27 @@ on: workflow_dispatch: env: - ZABBIX_VERSION: '5.0' + ZABBIX_VERSION: '7.4' ZABBIX_BRANCH: release/$ZABBIX_VERSION CONFIG_PATH: .github/configs/ - TEST_FILE: compatibility_api_test_5.py + TEST_FILE: compatibility_api_test_7.py jobs: compatibility: name: Compatibility test - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Install packages run: | - curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg - echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list - sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-13 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev + sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-16 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.3-pgsql php8.3-bcmath php8.3-xml php8.3-gd php8.3-ldap php8.3-mbstring libzip-dev - name: Build from sources run: | WORKDIR=$(pwd) cd /tmp/ + sudo addgroup --system --quiet zabbix + sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix git -c advice.detachedHead=false clone https://git.zabbix.com/scm/zbx/zabbix.git --branch ${{ env.ZABBIX_BRANCH }} --depth 1 --single-branch /tmp/zabbix-branch cd /tmp/zabbix-branch ./bootstrap.sh @@ -37,27 +37,43 @@ jobs: sudo make dbschema_postgresql sudo make echo -e "CacheUpdateFrequency=1\n" >> ./conf/zabbix_server.conf + ./configure --enable-proxy --with-sqlite3 + sudo make + mkdir /tmp/zabbix_proxy1/ + mkdir /tmp/zabbix_proxy2/ + cp ./conf/zabbix_proxy.conf ./conf/zabbix_proxy1.conf + mv ./conf/zabbix_proxy.conf ./conf/zabbix_proxy2.conf + sed -i "s/Hostname=Zabbix proxy/Hostname=CompatibilitySenderTest_proxy1/g" ./conf/zabbix_proxy1.conf + sed -i "s/Hostname=Zabbix proxy/Hostname=CompatibilitySenderTest_proxy2/g" ./conf/zabbix_proxy2.conf + sed -i "s#LogFile=/tmp/zabbix_proxy.log#LogFile=/tmp/zabbix_proxy1.log#g" ./conf/zabbix_proxy1.conf + sed -i "s#LogFile=/tmp/zabbix_proxy.log#LogFile=/tmp/zabbix_proxy2.log#g" ./conf/zabbix_proxy2.conf + sed -i 's#DBName=zabbix_proxy#DBName=/tmp/proxy1.db#' ./conf/zabbix_proxy1.conf + sed -i 's#DBName=zabbix_proxy#DBName=/tmp/proxy2.db#' ./conf/zabbix_proxy2.conf + echo -e "PidFile=/tmp/zabbix_proxy1/zabbix_proxy1.pid\n" >> ./conf/zabbix_proxy1.conf + echo -e "PidFile=/tmp/zabbix_proxy2/zabbix_proxy2.pid\n" >> ./conf/zabbix_proxy2.conf + echo -e "SocketDir=/tmp/zabbix_proxy1\n" >> ./conf/zabbix_proxy1.conf + echo -e "SocketDir=/tmp/zabbix_proxy2\n" >> ./conf/zabbix_proxy2.conf + echo -e "ListenPort=10061\n" >> ./conf/zabbix_proxy1.conf + echo -e "ListenPort=10062\n" >> ./conf/zabbix_proxy2.conf + sudo chown -R zabbix:zabbix /tmp/zabbix_proxy1/ + sudo chown -R zabbix:zabbix /tmp/zabbix_proxy2/ cd ui sudo rm /var/www/html/index.html sudo cp -a . /var/www/html/ sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/zabbix.conf.php /var/www/html/conf/ - sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/13/main/pg_hba.conf + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf sudo chown -R www-data:www-data /var/www/html/ - sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.1/apache2/php.ini + sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.3/apache2/php.ini sudo locale-gen en_US.UTF-8 sudo update-locale - name: Prepare environment run: | - sudo addgroup --system --quiet zabbix - sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix - sudo mkdir -p /var/run/postgresql/13-main.pg_stat_tmp - sudo chown -R postgres. /var/run/postgresql/ - sudo touch /var/run/postgresql/13-main.pg_stat_tmp/global.tmp - sudo chmod 0777 /var/run/postgresql/13-main.pg_stat_tmp/global.tmp - sudo sed -i 's/port = 5433/port = 5432/' /etc/postgresql/13/main/postgresql.conf - (sudo -u postgres /usr/lib/postgresql/13/bin/postgres -D /var/lib/postgresql/13/main -c config_file=/etc/postgresql/13/main/postgresql.conf)& + sudo mkdir -p /var/run/postgresql/16-main.pg_stat_tmp + sudo touch /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + sudo chmod 0777 /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + (sudo -u postgres /usr/lib/postgresql/16/bin/postgres -D /var/lib/postgresql/16/main -c config_file=/etc/postgresql/16/main/postgresql.conf)& sleep 5 cd /tmp/zabbix-branch/database/postgresql sudo -u postgres createuser zabbix @@ -70,6 +86,12 @@ jobs: run: | cd /tmp/zabbix-branch sudo ./src/zabbix_server/zabbix_server -c ./conf/zabbix_server.conf + - name: Start Zabbix proxies + continue-on-error: true + run: | + cd /tmp/zabbix-branch + sudo ./src/zabbix_proxy/zabbix_proxy -c ./conf/zabbix_proxy1.conf + sudo ./src/zabbix_proxy/zabbix_proxy -c ./conf/zabbix_proxy2.conf - name: Start Zabbix agent run: | cd /tmp/zabbix-branch diff --git a/.github/workflows/compatibility_latest.yaml b/.github/workflows/compatibility_latest.yaml index 7eea525..785b2a2 100644 --- a/.github/workflows/compatibility_latest.yaml +++ b/.github/workflows/compatibility_latest.yaml @@ -20,11 +20,13 @@ jobs: - uses: actions/checkout@v4 - name: Install packages run: | - sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev zabbix-sender + sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-16 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.3-pgsql php8.3-bcmath php8.3-xml php8.3-gd php8.3-ldap php8.3-mbstring libzip-dev - name: Build from sources run: | WORKDIR=$(pwd) cd /tmp/ + sudo addgroup --system --quiet zabbix + sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix git -c advice.detachedHead=false clone https://git.zabbix.com/scm/zbx/zabbix.git --branch ${{ env.ZABBIX_BRANCH }} --depth 1 --single-branch /tmp/zabbix-branch cd /tmp/zabbix-branch ./bootstrap.sh @@ -56,21 +58,19 @@ jobs: sudo rm /var/www/html/index.html sudo cp -a . /var/www/html/ sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/zabbix.conf.php /var/www/html/conf/ - sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/14/main/pg_hba.conf + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf sudo chown -R www-data:www-data /var/www/html/ - sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.1/apache2/php.ini + sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.3/apache2/php.ini sudo locale-gen en_US.UTF-8 sudo update-locale - name: Prepare environment run: | - sudo addgroup --system --quiet zabbix - sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix - sudo mkdir -p /var/run/postgresql/14-main.pg_stat_tmp - sudo touch /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - sudo chmod 0777 /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - (sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf)& + sudo mkdir -p /var/run/postgresql/16-main.pg_stat_tmp + sudo touch /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + sudo chmod 0777 /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + (sudo -u postgres /usr/lib/postgresql/16/bin/postgres -D /var/lib/postgresql/16/main -c config_file=/etc/postgresql/16/main/postgresql.conf)& sleep 5 cd /tmp/zabbix-branch/database/postgresql sudo -u postgres createuser zabbix diff --git a/.github/workflows/depricated_tests.yaml b/.github/workflows/depricated_tests.yaml index f76ef83..80dfe3c 100644 --- a/.github/workflows/depricated_tests.yaml +++ b/.github/workflows/depricated_tests.yaml @@ -17,10 +17,10 @@ env: jobs: depricated-tests: name: Depricated tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Install packages run: | sudo apt update && sudo apt install -y git sudo nginx gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev diff --git a/.github/workflows/integration_api.yaml b/.github/workflows/integration_api.yaml index 6660097..2d0ae01 100644 --- a/.github/workflows/integration_api.yaml +++ b/.github/workflows/integration_api.yaml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v4 - name: Install packages run: | - sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-14 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.1-pgsql php8.1-bcmath php8.1-xml php8.1-gd php8.1-ldap php8.1-mbstring libzip-dev + sudo apt update && sudo apt install -y git sudo gcc make automake pkg-config postgresql-16 libpostgresql-ocaml-dev libxml2-dev libpcre3-dev libevent-dev apache2 libapache2-mod-php php8.3-pgsql php8.3-bcmath php8.3-xml php8.3-gd php8.3-ldap php8.3-mbstring libzip-dev - name: Build from sources run: | WORKDIR=$(pwd) @@ -42,21 +42,21 @@ jobs: sudo rm /var/www/html/index.html sudo cp -a . /var/www/html/ sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/zabbix.conf.php /var/www/html/conf/ - sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/14/main/pg_hba.conf + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf sudo chown -R www-data:www-data /var/www/html/ - sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.1/apache2/php.ini - sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.1/apache2/php.ini + sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/8.3/apache2/php.ini + sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/8.3/apache2/php.ini sudo locale-gen en_US.UTF-8 sudo update-locale - name: Prepare environment run: | sudo addgroup --system --quiet zabbix sudo adduser --quiet --system --disabled-login --ingroup zabbix --home /var/lib/zabbix --no-create-home zabbix - sudo mkdir -p /var/run/postgresql/14-main.pg_stat_tmp - sudo touch /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - sudo chmod 0777 /var/run/postgresql/14-main.pg_stat_tmp/global.tmp - (sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf)& + sudo mkdir -p /var/run/postgresql/16-main.pg_stat_tmp + sudo touch /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + sudo chmod 0777 /var/run/postgresql/16-main.pg_stat_tmp/global.tmp + (sudo -u postgres /usr/lib/postgresql/16/bin/postgres -D /var/lib/postgresql/16/main -c config_file=/etc/postgresql/16/main/postgresql.conf)& sleep 1 cd /tmp/zabbix-branch/database/postgresql sudo -u postgres createuser zabbix diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 72e1b88..5fa33d8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12' - name: Get pip cache id: pip-cache run: | @@ -26,10 +26,10 @@ jobs: with: path: ${{ steps.pip-cache.outputs.dir }} key: ${{ runner.os }}-pip - - name: Install build requirements + - name: Install python requirements run: | python -m pip install --upgrade pip - pip install setuptools wheel + pip install setuptools wheel markdown - name: Set version env run: | echo "LIBRARY_VERSION=$(python -c "import sys; sys.path.append('.'); from zabbix_utils.version import __version__; print(__version__)")" >> $GITHUB_ENV diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 41c3e6c..bc8c944 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -18,6 +18,7 @@ jobs: - "3.10" - "3.11" - "3.12" + - "3.13" platform: - ubuntu-latest - macos-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fa06b8..e7c7138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## [2.0.3](https://github.com/zabbix/python-zabbix-utils/compare/v2.0.2...v2.0.3) (2025-07-03) + +### Features: + +- added support for Zabbix 7.4 + +### Changes: + +- discontinued support for Zabbix 5.0 +- added examples of TLS-PSK use for Python 3.13+ + +### Bug fixes: + +- fixed issue [#32](https://github.com/zabbix/python-zabbix-utils/issues/32) with a circular reference of exceptions +- fixed issue [#30](https://github.com/zabbix/python-zabbix-utils/issues/30) by adding Hostname support to Sender and AsyncSender +- fixed issue [#18](https://github.com/zabbix/python-zabbix-utils/issues/18) by adding with-statement support to AsyncZabbixAPI +- fixed issue [#7](https://github.com/zabbix/python-zabbix-utils/issues/7) with the TLS-PSK example code for Python 3.13+ by using built-in SSL features +- fixed small bugs and flaws + ## [2.0.2](https://github.com/zabbix/python-zabbix-utils/compare/v2.0.1...v2.0.2) (2024-12-12) ### Features: diff --git a/README.md b/README.md index 58a61c1..8371718 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ [![Zabbix sender](https://github.com/zabbix/python-zabbix-utils/actions/workflows/integration_sender.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/integration_sender.yaml) [![Zabbix get](https://github.com/zabbix/python-zabbix-utils/actions/workflows/integration_getter.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/integration_getter.yaml) -[![Zabbix 5.0](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_50.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_50.yaml) [![Zabbix 6.0](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_60.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_60.yaml) [![Zabbix 7.0](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_70.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_70.yaml) [![Zabbix 7.2](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_72.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_72.yaml) +[![Zabbix 7.4](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_74.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_74.yaml) **zabbix_utils** is a Python library for working with [Zabbix API](https://www.zabbix.com/documentation/current/manual/api/reference) as well as with [Zabbix sender](https://www.zabbix.com/documentation/current/manpages/zabbix_sender) and [Zabbix get](https://www.zabbix.com/documentation/current/manpages/zabbix_get) protocols. @@ -24,13 +24,13 @@ Supported versions: -* Zabbix 5.0+ +* Zabbix 6.0+ * Python 3.8+ Tested on: -* Zabbix 5.0, 6.0, 7.0 and 7.2 -* Python 3.8, 3.9, 3.10, 3.11 and 3.12 +* Zabbix 6.0, 7.0, 7.2 and 7.4 +* Python 3.8, 3.9, 3.10, 3.11, 3.12 and 3.13 Dependencies: diff --git a/examples/get/asynchronous/tls_psk_context.py b/examples/get/asynchronous/tls_psk_context.py new file mode 100644 index 0000000..7b74248 --- /dev/null +++ b/examples/get/asynchronous/tls_psk_context.py @@ -0,0 +1,71 @@ +# Copyright (C) 2001-2023 Zabbix SIA +# +# Zabbix SIA licenses this file to you under the MIT License. +# See the LICENSE file in the project root for more information. + +import ssl +import asyncio +from zabbix_utils import AsyncGetter + +# !!! IMPORTANT +# The code example below is supported only from Python version 3.13 onwards. + +# Pre-Shared Key (PSK) and PSK Identity +PSK_KEY = bytes.fromhex('608b0a0049d41fdb35a824ef0a227f24e5099c60aa935e803370a961c937d6f7') +PSK_IDENTITY = b'PSKID' + +# Zabbix agent parameters +ZABBIX_AGENT = "127.0.0.1" +ZABBIX_PORT = 10050 + + +# Create and configure an SSL context for secure communication with the Zabbix server. +def custom_context(*args, **kwargs) -> ssl.SSLContext: + # Create an SSL context for TLS client + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # Disable hostname verification + context.check_hostname = False + + # Set the verification mode to require a valid certificate + context.verify_mode = ssl.CERT_NONE + + # Set the maximum allowed version of the TLS protocol to TLS 1.2 + context.maximum_version = ssl.TLSVersion.TLSv1_2 + + # Set the ciphers to use for the connection + context.set_ciphers('PSK') + + # Set up the callback function to provide the PSK and identity when requested + context.set_psk_client_callback(lambda hint: (PSK_IDENTITY, PSK_KEY)) + + # Return the customized SSL context + return context + + +async def main(): + """ + The main function to perform asynchronous tasks. + """ + + # Create a AsyncGetter instance with a custom SSL context + agent = AsyncGetter( + host=ZABBIX_AGENT, + port=ZABBIX_PORT, + ssl_context=custom_context + ) + + # Send a Zabbix agent query for system information (e.g., uname) + resp = await agent.get('system.uname') + + # Check if there was an error in the response + if resp.error: + # Print the error message + print("An error occurred while trying to get the value:", resp.error) + else: + # Print the value obtained for the specified item key item + print("Received value:", resp.value) + + +# Run the main coroutine +asyncio.run(main()) diff --git a/examples/get/synchronous/psk_wrapper.py b/examples/get/synchronous/psk_wrapper.py index 8551088..4c0e5bc 100644 --- a/examples/get/synchronous/psk_wrapper.py +++ b/examples/get/synchronous/psk_wrapper.py @@ -6,6 +6,10 @@ import ssl from zabbix_utils import Getter +# !!! IMPORTANT +# The following code example is supposed to be used with Python up to the 3.12 version. +# Starting with Python 3.13, TLS-PSK is supported by the built-in ssl module. + # Try importing sslpsk3, fall back to sslpsk2 if not available try: import sslpsk3 as sslpsk @@ -13,6 +17,10 @@ # Import sslpsk2 if sslpsk3 is not available import sslpsk2 as sslpsk +# Zabbix agent parameters +ZABBIX_AGENT = "127.0.0.1" +ZABBIX_PORT = 10050 + # PSK wrapper function for SSL connection def psk_wrapper(sock): @@ -29,10 +37,6 @@ def psk_wrapper(sock): ) -# Zabbix agent parameters -ZABBIX_AGENT = "127.0.0.1" -ZABBIX_PORT = 10050 - # Create a Getter instance with PSK support agent = Getter( host=ZABBIX_AGENT, diff --git a/examples/get/synchronous/tls_psk_wrapper.py b/examples/get/synchronous/tls_psk_wrapper.py new file mode 100644 index 0000000..b24af6a --- /dev/null +++ b/examples/get/synchronous/tls_psk_wrapper.py @@ -0,0 +1,61 @@ +# Copyright (C) 2001-2023 Zabbix SIA +# +# Zabbix SIA licenses this file to you under the MIT License. +# See the LICENSE file in the project root for more information. + +import ssl +from zabbix_utils import Getter + +# !!! IMPORTANT +# The code example below is supported only from Python version 3.13 onwards. + +# Zabbix agent parameters +ZABBIX_AGENT = "127.0.0.1" +ZABBIX_PORT = 10050 + + +# PSK wrapper function for SSL connection +def psk_wrapper(sock): + # Pre-Shared Key (PSK) and PSK Identity + psk = bytes.fromhex('608b0a0049d41fdb35a824ef0a227f24e5099c60aa935e803370a961c937d6f7') + psk_identity = b'PSKID' + + # Create an SSL context for TLS client + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # Disable hostname verification + context.check_hostname = False + + # Set the verification mode to require a valid certificate + context.verify_mode = ssl.CERT_NONE + + # Set the maximum allowed version of the TLS protocol to TLS 1.2 + context.maximum_version = ssl.TLSVersion.TLSv1_2 + + # Set the ciphers to use for the connection + context.set_ciphers('PSK') + + # Set up the callback function to provide the PSK and identity when requested + context.set_psk_client_callback(lambda hint: (psk_identity, psk)) + + # Wrap the socket to establish an SSL connection with PSK + return context.wrap_socket(sock) + + +# Create a Getter instance with PSK support +agent = Getter( + host=ZABBIX_AGENT, + port=ZABBIX_PORT, + socket_wrapper=psk_wrapper +) + +# Send a Zabbix agent query for system information (e.g., uname) +resp = agent.get('system.uname') + +# Check if there was an error in the response +if resp.error: + # Print the error message + print("An error occurred while trying to get the value:", resp.error) +else: + # Print the value obtained for the specified item key item + print("Received value:", resp.value) diff --git a/examples/sender/asynchronous/agent_config_using.py b/examples/sender/asynchronous/agent_config_using.py index ce259c9..b315597 100644 --- a/examples/sender/asynchronous/agent_config_using.py +++ b/examples/sender/asynchronous/agent_config_using.py @@ -22,7 +22,7 @@ async def main(): # Send a value to a Zabbix server/proxy with specified parameters # Parameters: (host, key, value, clock) - response = await sender.send_value('host', 'item.key', 'value', 1695713666) + response = await sender.send_value(sender.host, 'item.key', 'value', 1695713666) # Check if the value sending was successful if response.failed == 0: diff --git a/examples/sender/asynchronous/tls_cert_context_from_config.py b/examples/sender/asynchronous/tls_cert_context_from_config.py index 072e6d0..9260c77 100644 --- a/examples/sender/asynchronous/tls_cert_context_from_config.py +++ b/examples/sender/asynchronous/tls_cert_context_from_config.py @@ -48,6 +48,7 @@ async def main(): sender = AsyncSender( server=ZABBIX_SERVER, port=ZABBIX_PORT, + use_config=True, ssl_context=custom_context ) diff --git a/examples/sender/asynchronous/tls_psk_context.py b/examples/sender/asynchronous/tls_psk_context.py new file mode 100644 index 0000000..e5977d7 --- /dev/null +++ b/examples/sender/asynchronous/tls_psk_context.py @@ -0,0 +1,71 @@ +# Copyright (C) 2001-2023 Zabbix SIA +# +# Zabbix SIA licenses this file to you under the MIT License. +# See the LICENSE file in the project root for more information. + +import ssl +import asyncio +from zabbix_utils import AsyncSender + +# !!! IMPORTANT +# The code example below is supported only from Python version 3.13 onwards. + +# Zabbix server details +ZABBIX_SERVER = "zabbix-server.example.com" +ZABBIX_PORT = 10051 + +# Pre-Shared Key (PSK) and PSK Identity +PSK_KEY = bytes.fromhex('608b0a0049d41fdb35a824ef0a227f24e5099c60aa935e803370a961c937d6f7') +PSK_IDENTITY = b'PSKID' + + +# Create and configure an SSL context for secure communication with the Zabbix server. +def custom_context(*args, **kwargs) -> ssl.SSLContext: + # Create an SSL context for TLS client + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # Disable hostname verification + context.check_hostname = False + + # Set the verification mode to require a valid certificate + context.verify_mode = ssl.CERT_NONE + + # Set the maximum allowed version of the TLS protocol to TLS 1.2 + context.maximum_version = ssl.TLSVersion.TLSv1_2 + + # Set the ciphers to use for the connection + context.set_ciphers('PSK') + + # Set up the callback function to provide the PSK and identity when requested + context.set_psk_client_callback(lambda hint: (PSK_IDENTITY, PSK_KEY)) + + # Return the customized SSL context + return context + + +async def main(): + """ + The main function to perform asynchronous tasks. + """ + + # Create an instance of AsyncSender with a custom SSL context + sender = AsyncSender( + server=ZABBIX_SERVER, + port=ZABBIX_PORT, + ssl_context=custom_context + ) + + # Send a value to a Zabbix server/proxy with specified parameters + # Parameters: (host, key, value, clock, ns) + response = await sender.send_value('host', 'item.key', 'value', 1695713666, 30) + + # Check if the value sending was successful + if response.failed == 0: + # Print a success message along with the response time + print(f"Value sent successfully in {response.time}") + else: + # Print a failure message + print("Failed to send value") + +# Run the main coroutine +asyncio.run(main()) diff --git a/examples/sender/asynchronous/tls_psk_context_from_config.py b/examples/sender/asynchronous/tls_psk_context_from_config.py new file mode 100644 index 0000000..a5a4a89 --- /dev/null +++ b/examples/sender/asynchronous/tls_psk_context_from_config.py @@ -0,0 +1,79 @@ +# Copyright (C) 2001-2023 Zabbix SIA +# +# Zabbix SIA licenses this file to you under the MIT License. +# See the LICENSE file in the project root for more information. + +import ssl +import asyncio +from zabbix_utils import AsyncSender + +# !!! IMPORTANT +# The code example below is supported only from Python version 3.13 onwards. + +# Zabbix server details +ZABBIX_SERVER = "zabbix-server.example.com" +ZABBIX_PORT = 10051 + + +# Create and configure an SSL context for secure communication with the Zabbix server. +def custom_context(config) -> ssl.SSLContext: + psk = None + + # Try to get PSK key and identity + psk_identity = config.get('tlspskidentity').encode('utf-8') + psk_file = config.get('tlspskfile') + + # Read PSK from file if specified + if psk_file: + with open(psk_file, encoding='utf-8') as f: + psk = bytes.fromhex(f.read()) + + # Create an SSL context for TLS client + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # Disable hostname verification + context.check_hostname = False + + # Set the verification mode to require a valid certificate + context.verify_mode = ssl.CERT_NONE + + # Set the maximum allowed version of the TLS protocol to TLS 1.2 + context.maximum_version = ssl.TLSVersion.TLSv1_2 + + # Set the ciphers to use for the connection + context.set_ciphers('PSK') + + # Set up the callback function to provide the PSK and identity when requested + context.set_psk_client_callback(lambda hint: (psk_identity, psk)) + + # Return the customized SSL context + return context + + +async def main(): + """ + The main function to perform asynchronous tasks. + """ + + # Create an instance of AsyncSender with a custom SSL context + sender = AsyncSender( + server=ZABBIX_SERVER, + port=ZABBIX_PORT, + use_config=True, + ssl_context=custom_context + ) + + # Send a value to a Zabbix server/proxy with specified parameters + # Parameters: (host, key, value, clock, ns) + response = await sender.send_value('host', 'item.key', 'value', 1695713666, 30) + + # Check if the value sending was successful + if response.failed == 0: + # Print a success message along with the response time + print(f"Value sent successfully in {response.time}") + else: + # Print a failure message + print("Failed to send value") + +# Run the main coroutine +asyncio.run(main()) diff --git a/examples/sender/synchronous/agent_config_using.py b/examples/sender/synchronous/agent_config_using.py index 1bdea04..cfba28a 100644 --- a/examples/sender/synchronous/agent_config_using.py +++ b/examples/sender/synchronous/agent_config_using.py @@ -15,7 +15,7 @@ # Send a value to a Zabbix server/proxy with specified parameters # Parameters: (host, key, value, clock) -response = sender.send_value('host', 'item.key', 'value', 1695713666) +response = sender.send_value(sender.host, 'item.key', 'value', 1695713666) # Check if the value sending was successful if response.failed == 0: diff --git a/examples/sender/synchronous/psk_wrapper.py b/examples/sender/synchronous/psk_wrapper.py index 9dea96e..1e8057e 100644 --- a/examples/sender/synchronous/psk_wrapper.py +++ b/examples/sender/synchronous/psk_wrapper.py @@ -6,6 +6,10 @@ import ssl from zabbix_utils import Sender +# !!! IMPORTANT +# The following code example is supposed to be used with Python up to the 3.12 version. +# Starting with Python 3.13, TLS-PSK is supported by the built-in ssl module. + # Try importing sslpsk3, fall back to sslpsk2 if not available try: import sslpsk3 as sslpsk @@ -15,7 +19,7 @@ # PSK wrapper function for SSL connection -def psk_wrapper(sock, tls): +def psk_wrapper(sock, *args, **kwargs): # Pre-Shared Key (PSK) and PSK Identity psk = bytes.fromhex('608b0a0049d41fdb35a824ef0a227f24e5099c60aa935e803370a961c937d6f7') psk_identity = b'PSKID' diff --git a/examples/sender/synchronous/tls_psk_wrapper.py b/examples/sender/synchronous/tls_psk_wrapper.py new file mode 100644 index 0000000..d6d22aa --- /dev/null +++ b/examples/sender/synchronous/tls_psk_wrapper.py @@ -0,0 +1,62 @@ +# Copyright (C) 2001-2023 Zabbix SIA +# +# Zabbix SIA licenses this file to you under the MIT License. +# See the LICENSE file in the project root for more information. + +import ssl +from zabbix_utils import Sender + +# !!! IMPORTANT +# The code example below is supported only from Python version 3.13 onwards. + +# Zabbix server details +ZABBIX_SERVER = "zabbix-server.example.com" +ZABBIX_PORT = 10051 + + +# PSK wrapper function for SSL connection +def psk_wrapper(sock, *args, **kwargs): + # Pre-Shared Key (PSK) and PSK Identity + psk = bytes.fromhex('608b0a0049d41fdb35a824ef0a227f24e5099c60aa935e803370a961c937d6f7') + psk_identity = b'PSKID' + + # Create an SSL context for TLS client + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # Disable hostname verification + context.check_hostname = False + + # Set the verification mode to require a valid certificate + context.verify_mode = ssl.CERT_NONE + + # Set the maximum allowed version of the TLS protocol to TLS 1.2 + context.maximum_version = ssl.TLSVersion.TLSv1_2 + + # Set the ciphers to use for the connection + context.set_ciphers('PSK') + + # Set up the callback function to provide the PSK and identity when requested + context.set_psk_client_callback(lambda hint: (psk_identity, psk)) + + # Wrap the socket to establish an SSL connection with PSK + return context.wrap_socket(sock) + + +# Create a Sender instance with PSK support +sender = Sender( + server=ZABBIX_SERVER, + port=ZABBIX_PORT, + socket_wrapper=psk_wrapper +) + +# Send a value to a Zabbix server/proxy with specified parameters +# Parameters: (host, key, value, clock, ns) +response = sender.send_value('host', 'item.key', 'value', 1695713666, 30) + +# Check if the value sending was successful +if response.failed == 0: + # Print a success message along with the response time + print(f"Value sent successfully in {response.time}") +else: + # Print a failure message + print("Failed to send value") diff --git a/examples/sender/synchronous/tls_psk_wrapper_from_config.py b/examples/sender/synchronous/tls_psk_wrapper_from_config.py new file mode 100644 index 0000000..9a70d67 --- /dev/null +++ b/examples/sender/synchronous/tls_psk_wrapper_from_config.py @@ -0,0 +1,73 @@ +# Copyright (C) 2001-2023 Zabbix SIA +# +# Zabbix SIA licenses this file to you under the MIT License. +# See the LICENSE file in the project root for more information. + +import ssl +from zabbix_utils import Sender + +# !!! IMPORTANT +# The code example below is supported only from Python version 3.13 onwards. + +# Zabbix server details +ZABBIX_SERVER = "zabbix-server.example.com" +ZABBIX_PORT = 10051 + + +# PSK wrapper function for SSL connection +def psk_wrapper(sock, config): + psk = None + psk_identity = config.get('tlspskidentity').encode('utf-8') + psk_file = config.get('tlspskfile') + + # Read PSK from file if specified + if psk_file: + with open(psk_file, encoding='utf-8') as f: + psk = bytes.fromhex(f.read()) + + # Check if both PSK and PSK identity are available + if psk and psk_identity: + # Create an SSL context for TLS client + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # Disable hostname verification + context.check_hostname = False + + # Set the verification mode to require a valid certificate + context.verify_mode = ssl.CERT_NONE + + # Set the maximum allowed version of the TLS protocol to TLS 1.2 + context.maximum_version = ssl.TLSVersion.TLSv1_2 + + # Set the ciphers to use for the connection + context.set_ciphers('PSK') + + # Set up the callback function to provide the PSK and identity when requested + context.set_psk_client_callback(lambda hint: (psk_identity, psk)) + + # Wrap the socket to establish an SSL connection with PSK + return context.wrap_socket(sock) + + # Return original socket if PSK or PSK identity is missing + return sock + + +# Create a Sender instance with PSK support +sender = Sender( + server=ZABBIX_SERVER, + port=ZABBIX_PORT, + use_config=True, + socket_wrapper=psk_wrapper +) + +# Send a value to a Zabbix server/proxy with specified parameters +# Parameters: (host, key, value, clock, ns) +response = sender.send_value('host', 'item.key', 'value', 1695713666, 30) + +# Check if the value sending was successful +if response.failed == 0: + # Print a success message along with the response time + print(f"Value sent successfully in {response.time}") +else: + # Print a failure message + print("Failed to send value") diff --git a/setup.py b/setup.py index 5cb887b..31a240f 100644 --- a/setup.py +++ b/setup.py @@ -65,6 +65,7 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Topic :: System :: Monitoring", diff --git a/tests/test_zabbix_aioapi.py b/tests/test_zabbix_aioapi.py index 96f1417..4d9b278 100644 --- a/tests/test_zabbix_aioapi.py +++ b/tests/test_zabbix_aioapi.py @@ -164,21 +164,32 @@ async def test_login(self): self.assertEqual(self.zapi._AsyncZabbixAPI__session_id, case['output'], f"unexpected output with input data: {case['input']}") await self.zapi.logout() - - async with AsyncZabbixAPI(client_session=common.MockSession()) as zapi: - try: - await zapi.login(**case['input']) - except case['exception']: - if not case['raised']: - self.fail(f"raised unexpected Exception with input data: {case['input']}") - else: - if case['raised']: - self.fail(f"not raised expected Exception with input data: {case['input']}") + try: + zapi = await AsyncZabbixAPI(client_session=common.MockSession(), **case['input']) + self.assertEqual(zapi._AsyncZabbixAPI__use_token, bool(case['input'].get('token')), + f"unexpected output with input data: {case['input']}") + self.assertEqual(zapi._AsyncZabbixAPI__session_id, case['output'], + f"unexpected output with input data: {case['input']}") + except case['exception']: + if not case['raised']: + self.fail(f"raised unexpected Exception with input data: {case['input']}") + else: + if case['raised']: + self.fail(f"not raised expected Exception with input data: {case['input']}") + + try: + async with AsyncZabbixAPI(client_session=common.MockSession(), **case['input']) as zapi: self.assertEqual(zapi._AsyncZabbixAPI__use_token, bool(case['input'].get('token')), f"unexpected output with input data: {case['input']}") self.assertEqual(zapi._AsyncZabbixAPI__session_id, case['output'], f"unexpected output with input data: {case['input']}") + except case['exception']: + if not case['raised']: + self.fail(f"raised unexpected Exception with input data: {case['input']}") + else: + if case['raised']: + self.fail(f"not raised expected Exception with input data: {case['input']}") async def test_logout(self): """Tests logout in different auth cases""" @@ -375,37 +386,43 @@ async def test_version_conditions(self): test_cases = [ { 'input': {'token': DEFAULT_VALUES['token']}, - 'version': '5.2.0', - 'raised': {'APINotSupported': True, 'ProcessingError': True}, + 'version': '5.0.0', + 'raised': {'APINotSupported': True, 'ProcessingError': False}, 'output': DEFAULT_VALUES['session'] }, + { + 'input': {'token': DEFAULT_VALUES['token']}, + 'version': '6.0.1', + 'raised': {'APINotSupported': False, 'ProcessingError': False}, + 'output': DEFAULT_VALUES['token'] + }, { 'input': {'token': DEFAULT_VALUES['token'], 'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.2.0', + 'version': '6.0.2', 'raised': {'APINotSupported': True, 'ProcessingError': True}, 'output': DEFAULT_VALUES['session'] }, { 'input': {'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.2.0', + 'version': '6.0.3', 'raised': {'APINotSupported': False, 'ProcessingError': False}, 'output': DEFAULT_VALUES['session'] }, { 'input': {'token': DEFAULT_VALUES['token']}, - 'version': '5.4.0', + 'version': '7.4.1', 'raised': {'APINotSupported': False, 'ProcessingError': False}, 'output': DEFAULT_VALUES['token'] }, { 'input': {'token': DEFAULT_VALUES['token'], 'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.4.0', + 'version': '7.4.2', 'raised': {'APINotSupported': False, 'ProcessingError': True}, 'output': DEFAULT_VALUES['token'] }, { 'input': {'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.4.0', + 'version': '7.4.3', 'raised': {'APINotSupported': False, 'ProcessingError': False}, 'output': DEFAULT_VALUES['session'] } diff --git a/tests/test_zabbix_api.py b/tests/test_zabbix_api.py index 63ec234..4be1c7f 100644 --- a/tests/test_zabbix_api.py +++ b/tests/test_zabbix_api.py @@ -286,37 +286,43 @@ def test_version_conditions(self): test_cases = [ { 'input': {'token': DEFAULT_VALUES['token']}, - 'version': '5.2.0', - 'raised': {'APINotSupported': True, 'ProcessingError': True}, + 'version': '5.0.0', + 'raised': {'APINotSupported': True, 'ProcessingError': False}, 'output': DEFAULT_VALUES['session'] }, + { + 'input': {'token': DEFAULT_VALUES['token']}, + 'version': '6.0.1', + 'raised': {'APINotSupported': False, 'ProcessingError': False}, + 'output': DEFAULT_VALUES['token'] + }, { 'input': {'token': DEFAULT_VALUES['token'], 'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.2.0', + 'version': '6.0.2', 'raised': {'APINotSupported': True, 'ProcessingError': True}, 'output': DEFAULT_VALUES['session'] }, { 'input': {'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.2.0', + 'version': '6.0.3', 'raised': {'APINotSupported': False, 'ProcessingError': False}, 'output': DEFAULT_VALUES['session'] }, { 'input': {'token': DEFAULT_VALUES['token']}, - 'version': '5.4.0', + 'version': '7.4.1', 'raised': {'APINotSupported': False, 'ProcessingError': False}, 'output': DEFAULT_VALUES['token'] }, { 'input': {'token': DEFAULT_VALUES['token'], 'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.4.0', + 'version': '7.4.2', 'raised': {'APINotSupported': False, 'ProcessingError': True}, 'output': DEFAULT_VALUES['token'] }, { 'input': {'user': DEFAULT_VALUES['user'], 'password': DEFAULT_VALUES['password']}, - 'version': '5.4.0', + 'version': '7.4.3', 'raised': {'APINotSupported': False, 'ProcessingError': False}, 'output': DEFAULT_VALUES['session'] } diff --git a/zabbix_utils/aioapi.py b/zabbix_utils/aioapi.py index ccf411d..a52f00e 100644 --- a/zabbix_utils/aioapi.py +++ b/zabbix_utils/aioapi.py @@ -34,7 +34,7 @@ from os import environ as env from urllib.error import URLError -from typing import Callable, Union, Optional, Any +from typing import Callable, Union, Optional, Coroutine, Any from aiohttp.client_exceptions import ContentTypeError from .types import APIVersion @@ -120,7 +120,8 @@ class AsyncZabbixAPI(): __session_id = None __internal_client = None - def __init__(self, url: Optional[str] = None, + def __init__(self, url: Optional[str] = None, token: Optional[str] = None, + user: Optional[str] = None, password: Optional[str] = None, http_user: Optional[str] = None, http_password: Optional[str] = None, skip_version_check: bool = False, validate_certs: bool = True, client_session: Optional[aiohttp.ClientSession] = None, timeout: int = 30): @@ -131,6 +132,10 @@ def __init__(self, url: Optional[str] = None, self.validate_certs = validate_certs self.timeout = timeout + self.__token = token + self.__user = user + self.__password = password + client_params: dict = {} if client_session is None: @@ -171,18 +176,21 @@ def __getattr__(self, name: str) -> Callable: return APIObject(name, self) async def __aenter__(self) -> Callable: - return self + return await self.login() async def __aexit__(self, *args) -> None: await self.logout() + def __await__(self) -> Coroutine: + return self.login().__await__() + async def __aclose_session(self) -> None: if self.__internal_client: await self.__internal_client.close() async def __exception(self, exc) -> None: await self.__aclose_session() - raise exc from exc + raise exc def __close_session(self) -> None: if self.__internal_client: @@ -212,7 +220,7 @@ def version(self) -> APIVersion: return self.api_version() async def login(self, token: Optional[str] = None, user: Optional[str] = None, - password: Optional[str] = None) -> None: + password: Optional[str] = None) -> Callable: """Login to Zabbix API. Args: @@ -221,9 +229,9 @@ async def login(self, token: Optional[str] = None, user: Optional[str] = None, password (str, optional): Zabbix API user's password. Defaults to `None`. """ - user = user or env.get('ZABBIX_USER') or None - password = password or env.get('ZABBIX_PASSWORD') or None - token = token or env.get('ZABBIX_TOKEN') or None + token = token or self.__token or env.get('ZABBIX_TOKEN') or None + user = user or self.__user or env.get('ZABBIX_USER') or None + password = password or self.__password or env.get('ZABBIX_PASSWORD') or None if token: if self.version < 5.4: @@ -237,7 +245,7 @@ async def login(self, token: Optional[str] = None, user: Optional[str] = None, ) self.__use_token = True self.__session_id = token - return + return self if not user: await self.__exception(ProcessingError("Username is missing")) @@ -263,6 +271,8 @@ async def login(self, token: Optional[str] = None, user: Optional[str] = None, log.debug("Connected to Zabbix API version %s: %s", self.version, self.url) + return self + async def logout(self) -> None: """Logout from Zabbix API.""" diff --git a/zabbix_utils/aiosender.py b/zabbix_utils/aiosender.py index 6e51d4e..03c2584 100644 --- a/zabbix_utils/aiosender.py +++ b/zabbix_utils/aiosender.py @@ -69,6 +69,7 @@ def __init__(self, server: Optional[str] = None, port: int = 10051, self.use_ipv6 = use_ipv6 self.tls = {} + self.host = None self.source_ip = None self.chunk_size = chunk_size self.compression = compression @@ -105,6 +106,7 @@ def __read_config(self, config: configparser.SectionProxy) -> None: for cluster in server_row.split(','): self.clusters.append(Cluster(cluster.strip().split(';'))) + self.host = config.get('Hostname') if 'SourceIP' in config: self.source_ip = config.get('SourceIP') @@ -310,4 +312,4 @@ async def send_value(self, host: str, key: str, TrapperResponse: Response from Zabbix server/proxy. """ - return await self.send([ItemValue(host, key, value, clock, ns)]) + return await self.send([ItemValue(host or self.host or '', key, value, clock, ns)]) diff --git a/zabbix_utils/sender.py b/zabbix_utils/sender.py index cb34ca8..0d99ef8 100644 --- a/zabbix_utils/sender.py +++ b/zabbix_utils/sender.py @@ -66,6 +66,7 @@ def __init__(self, server: Optional[str] = None, port: int = 10051, self.use_ipv6 = use_ipv6 self.tls = {} + self.host = None self.source_ip = None self.chunk_size = chunk_size self.compression = compression @@ -102,6 +103,7 @@ def __read_config(self, config: configparser.SectionProxy) -> None: for cluster in server_row.split(','): self.clusters.append(Cluster(cluster.strip().split(';'))) + self.host = config.get('Hostname') if 'SourceIP' in config: self.source_ip = config.get('SourceIP') @@ -218,7 +220,6 @@ def __send_to_cluster(self, cluster: Cluster, packet: bytes) -> Optional[Tuple[N if response and response.get('response') != 'success': if response.get('redirect'): - print(response) log.debug( 'Packet was redirected from %s to %s. Proxy group revision: %s.', active_node, @@ -312,4 +313,4 @@ def send_value(self, host: str, key: str, TrapperResponse: Response from Zabbix server/proxy. """ - return self.send([ItemValue(host, key, value, clock, ns)]) + return self.send([ItemValue(host or self.host or '', key, value, clock, ns)]) diff --git a/zabbix_utils/version.py b/zabbix_utils/version.py index 15c3e95..2d1f19d 100644 --- a/zabbix_utils/version.py +++ b/zabbix_utils/version.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. -__version__ = "2.0.2" +__version__ = "2.0.3" -__min_supported__ = 5.0 -__max_supported__ = 7.2 +__min_supported__ = 6.0 +__max_supported__ = 7.4 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy