From b868ef8793d7d6f1ddef3fbc9f14a427ebce5f0f Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Thu, 12 Dec 2024 02:59:44 +0200 Subject: [PATCH 01/14] fixed email notification GitHub action --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 72e1b88..f259dc6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -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 From cb498e80cf5a1fc8ebf03b18bc38033a46f822a1 Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Mon, 3 Mar 2025 14:57:24 +0200 Subject: [PATCH 02/14] updated github workflow action of the compatibility with the latest Zabbix version check --- .github/workflows/compatibility_latest.yaml | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 From 13f0226d211536d3b11a7cfdd0ad9e3a348fe7d4 Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 4 Mar 2025 15:21:10 +0200 Subject: [PATCH 03/14] updated workflow actions to check compatibility with all current versions of Zabbix --- .github/workflows/compatibility_50.yaml | 25 +++++++++++++------------ .github/workflows/compatibility_60.yaml | 4 ++-- .github/workflows/compatibility_70.yaml | 24 ++++++++++++------------ .github/workflows/compatibility_72.yaml | 24 ++++++++++++------------ 4 files changed, 39 insertions(+), 38 deletions(-) diff --git a/.github/workflows/compatibility_50.yaml b/.github/workflows/compatibility_50.yaml index d52c882..704f4e4 100644 --- a/.github/workflows/compatibility_50.yaml +++ b/.github/workflows/compatibility_50.yaml @@ -17,15 +17,16 @@ env: jobs: compatibility: name: Compatibility test - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - 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 add-apt-repository ppa:ondrej/php + 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 libzip-dev php7.4 libapache2-mod-php7.4 php7.4-common php7.4-fpm php7.4-gd php7.4-mbstring php7.4-xml php7.4-zip php7.4-ldap - name: Build from sources run: | WORKDIR=$(pwd) @@ -41,23 +42,23 @@ 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/13/main/pg_hba.conf + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/pg_hba.conf /etc/postgresql/14/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/7.4/fpm/php.ini + sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/7.4/fpm/php.ini + sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/7.4/fpm/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 mkdir -p /var/run/postgresql/14-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 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 sed -i 's/port = 5433/port = 5432/' /etc/postgresql/14/main/postgresql.conf + (sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf)& sleep 5 cd /tmp/zabbix-branch/database/postgresql sudo -u postgres createuser zabbix 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 From 8d57619c96cafa56990e71c0fd65ba9115507c1d Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 4 Mar 2025 15:35:58 +0200 Subject: [PATCH 04/14] updated workflow actions for additional checks --- .github/workflows/additional_tests.yaml | 4 ++-- .github/workflows/depricated_tests.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/additional_tests.yaml b/.github/workflows/additional_tests.yaml index 1478992..6d2f56e 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 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 From b06a23cf7e2736e6883f53856a529d8d8a1228ca Mon Sep 17 00:00:00 2001 From: Adam Chovanec Date: Tue, 22 Apr 2025 22:35:58 +0200 Subject: [PATCH 05/14] fix: circular reference of exceptions fixes #31 --- zabbix_utils/aioapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix_utils/aioapi.py b/zabbix_utils/aioapi.py index ccf411d..a6becf1 100644 --- a/zabbix_utils/aioapi.py +++ b/zabbix_utils/aioapi.py @@ -182,7 +182,7 @@ async def __aclose_session(self) -> None: 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: From ceb29cb08c42e646a551ef66a79003b4a4c4b32d Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 13 May 2025 14:53:46 +0300 Subject: [PATCH 06/14] fixed TLS-PSK example code issue #7 by using built-in SSL features for Python 3.13+ --- examples/get/asynchronous/tls_psk_context.py | 71 +++++++++++++++++ examples/get/synchronous/psk_wrapper.py | 12 ++- examples/get/synchronous/tls_psk_wrapper.py | 61 ++++++++++++++ .../sender/asynchronous/tls_psk_context.py | 71 +++++++++++++++++ .../tls_psk_context_from_config.py | 79 +++++++++++++++++++ examples/sender/synchronous/psk_wrapper.py | 6 +- .../sender/synchronous/tls_psk_wrapper.py | 62 +++++++++++++++ .../tls_psk_wrapper_from_config.py | 73 +++++++++++++++++ 8 files changed, 430 insertions(+), 5 deletions(-) create mode 100644 examples/get/asynchronous/tls_psk_context.py create mode 100644 examples/get/synchronous/tls_psk_wrapper.py create mode 100644 examples/sender/asynchronous/tls_psk_context.py create mode 100644 examples/sender/asynchronous/tls_psk_context_from_config.py create mode 100644 examples/sender/synchronous/tls_psk_wrapper.py create mode 100644 examples/sender/synchronous/tls_psk_wrapper_from_config.py 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/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/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") From 21a9bbfcf412129055423547e4d06dcf1cdd93bc Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 13 May 2025 15:06:40 +0300 Subject: [PATCH 07/14] limited support for Zabbix 5.0 has ended --- .github/scripts/compatibility_api_test_5.py | 385 -------------------- .github/workflows/compatibility_50.yaml | 95 ----- 2 files changed, 480 deletions(-) delete mode 100644 .github/scripts/compatibility_api_test_5.py delete mode 100644 .github/workflows/compatibility_50.yaml 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/workflows/compatibility_50.yaml b/.github/workflows/compatibility_50.yaml deleted file mode 100644 index 704f4e4..0000000 --- a/.github/workflows/compatibility_50.yaml +++ /dev/null @@ -1,95 +0,0 @@ -name: zabbix_50 -run-name: Compatibility with Zabbix 5.0 test - -on: - push: - branches: [main] - pull_request: - branches: [main] - workflow_dispatch: - -env: - ZABBIX_VERSION: '5.0' - ZABBIX_BRANCH: release/$ZABBIX_VERSION - CONFIG_PATH: .github/configs/ - TEST_FILE: compatibility_api_test_5.py - -jobs: - compatibility: - name: Compatibility test - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v3 - - 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 add-apt-repository ppa:ondrej/php - 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 libzip-dev php7.4 libapache2-mod-php7.4 php7.4-common php7.4-fpm php7.4-gd php7.4-mbstring php7.4-xml php7.4-zip php7.4-ldap - - name: Build from sources - run: | - WORKDIR=$(pwd) - cd /tmp/ - 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 - ./configure --enable-server --enable-agent --with-postgresql - sudo make dbschema_postgresql - sudo make - echo -e "CacheUpdateFrequency=1\n" >> ./conf/zabbix_server.conf - 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/14/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/7.4/fpm/php.ini - sudo sed -i "s/max_execution_time = 30/max_execution_time = 300/g" /etc/php/7.4/fpm/php.ini - sudo sed -i "s/max_input_time = 60/max_input_time = 300/g" /etc/php/7.4/fpm/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 chown -R postgres. /var/run/postgresql/ - 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 sed -i 's/port = 5433/port = 5432/' /etc/postgresql/14/main/postgresql.conf - (sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf)& - sleep 5 - cd /tmp/zabbix-branch/database/postgresql - sudo -u postgres createuser zabbix - sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix - cat schema.sql | sudo -u zabbix psql zabbix - cat images.sql | sudo -u zabbix psql zabbix - cat data.sql | sudo -u zabbix psql zabbix - sudo apache2ctl start - - name: Start Zabbix server - run: | - cd /tmp/zabbix-branch - sudo ./src/zabbix_server/zabbix_server -c ./conf/zabbix_server.conf - - name: Start Zabbix agent - run: | - cd /tmp/zabbix-branch - sudo ./src/zabbix_agent/zabbix_agentd -c ./conf/zabbix_agentd.conf - - name: Install python3 - run: | - sudo apt-get install -y python3 python3-pip python-is-python3 - pip install -r ./requirements.txt - - name: Wait for Zabbix API - run: | - python ./.github/scripts/wait_instance_zabbix.py - - name: Compatibility test - continue-on-error: true - run: | - python ./.github/scripts/$TEST_FILE 2>/tmp/compatibility.log >/dev/null - - name: Send report - env: - TBOT_TOKEN: ${{ secrets.TBOT_TOKEN }} - TBOT_CHAT: ${{ vars.TBOT_CHAT }} - SUBJECT: Compatibility with Zabbix ${{ env.ZABBIX_VERSION }} FAIL - run: | - tail -n1 /tmp/compatibility.log | grep "OK" 1>/dev/null || tail /tmp/compatibility.log | python ./.github/scripts/telegram_msg.py | exit 1 From 94b90508fa2966afa44d0ab007624cd3925f674f Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 13 May 2025 15:07:48 +0300 Subject: [PATCH 08/14] updated workflows --- .github/workflows/additional_tests.yaml | 4 ++-- .github/workflows/integration_api.yaml | 18 +++++++++--------- .github/workflows/release.yaml | 2 +- .github/workflows/tests.yaml | 1 + 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/additional_tests.yaml b/.github/workflows/additional_tests.yaml index 6d2f56e..5edf088 100644 --- a/.github/workflows/additional_tests.yaml +++ b/.github/workflows/additional_tests.yaml @@ -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/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 f259dc6..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: | 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 From 11285e6930760ff13cde6dab6ab9095fb0e950e4 Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 13 May 2025 15:20:55 +0300 Subject: [PATCH 09/14] tested compatibility with Zabbix 7.4 --- .github/scripts/compatibility_api_test_7.py | 12 +- .github/workflows/compatibility_74.yaml | 116 ++++++++++++++++++++ README.md | 6 +- tests/test_zabbix_aioapi.py | 20 ++-- tests/test_zabbix_api.py | 20 ++-- zabbix_utils/version.py | 4 +- 6 files changed, 153 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/compatibility_74.yaml 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/compatibility_74.yaml b/.github/workflows/compatibility_74.yaml new file mode 100644 index 0000000..5f7247b --- /dev/null +++ b/.github/workflows/compatibility_74.yaml @@ -0,0 +1,116 @@ +name: zabbix_74 +run-name: Compatibility with Zabbix 7.4 test + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +env: + ZABBIX_VERSION: '7.4' + ZABBIX_BRANCH: release/$ZABBIX_VERSION + CONFIG_PATH: .github/configs/ + TEST_FILE: compatibility_api_test_7.py + +jobs: + compatibility: + name: Compatibility test + 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-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 + ./configure --enable-server --enable-agent --with-postgresql + 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/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.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 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 + sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix + cat schema.sql | sudo -u zabbix psql zabbix + cat images.sql | sudo -u zabbix psql zabbix + cat data.sql | sudo -u zabbix psql zabbix + sudo apache2ctl start + - name: Start Zabbix server + 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 + sudo ./src/zabbix_agent/zabbix_agentd -c ./conf/zabbix_agentd.conf + - name: Install python3 + run: | + sudo apt-get install -y python3 python3-pip python-is-python3 + pip install -r ./requirements.txt + - name: Wait for Zabbix API + run: | + python ./.github/scripts/wait_instance_zabbix.py + - name: Compatibility test + continue-on-error: true + run: | + python ./.github/scripts/$TEST_FILE 2>/tmp/compatibility.log >/dev/null + - name: Send report + env: + TBOT_TOKEN: ${{ secrets.TBOT_TOKEN }} + TBOT_CHAT: ${{ vars.TBOT_CHAT }} + SUBJECT: Compatibility with Zabbix ${{ env.ZABBIX_VERSION }} FAIL + run: | + tail -n1 /tmp/compatibility.log | grep "OK" 1>/dev/null || tail /tmp/compatibility.log | python ./.github/scripts/telegram_msg.py | exit 1 diff --git a/README.md b/README.md index 58a61c1..5bfff9c 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,12 +24,12 @@ Supported versions: -* Zabbix 5.0+ +* Zabbix 6.0+ * Python 3.8+ Tested on: -* Zabbix 5.0, 6.0, 7.0 and 7.2 +* Zabbix 6.0, 7.0, 7.2 and 7.4 * Python 3.8, 3.9, 3.10, 3.11 and 3.12 Dependencies: diff --git a/tests/test_zabbix_aioapi.py b/tests/test_zabbix_aioapi.py index 96f1417..a25e930 100644 --- a/tests/test_zabbix_aioapi.py +++ b/tests/test_zabbix_aioapi.py @@ -375,37 +375,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/version.py b/zabbix_utils/version.py index 15c3e95..da223db 100644 --- a/zabbix_utils/version.py +++ b/zabbix_utils/version.py @@ -24,5 +24,5 @@ __version__ = "2.0.2" -__min_supported__ = 5.0 -__max_supported__ = 7.2 +__min_supported__ = 6.0 +__max_supported__ = 7.4 From daa587241c641641abe55344664e4fd2f647888d Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 13 May 2025 15:21:34 +0300 Subject: [PATCH 10/14] tested compatibility with Python 3.13 --- README.md | 2 +- setup.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5bfff9c..8371718 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Supported versions: Tested on: * Zabbix 6.0, 7.0, 7.2 and 7.4 -* Python 3.8, 3.9, 3.10, 3.11 and 3.12 +* Python 3.8, 3.9, 3.10, 3.11, 3.12 and 3.13 Dependencies: 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", From 72bb5cf33a6b34272bff39a66ec32e7cf3b513d8 Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Tue, 13 May 2025 15:54:53 +0300 Subject: [PATCH 11/14] fixed issue #18 by adding with-statement support to AsyncZabbixAPI --- tests/test_zabbix_aioapi.py | 31 +++++++++++++++++++++---------- zabbix_utils/aioapi.py | 26 ++++++++++++++++++-------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/tests/test_zabbix_aioapi.py b/tests/test_zabbix_aioapi.py index a25e930..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""" diff --git a/zabbix_utils/aioapi.py b/zabbix_utils/aioapi.py index a6becf1..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,11 +176,14 @@ 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() @@ -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.""" From 6d014fb06d86d16a3b79d6bc04515fdf646f7ce6 Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Thu, 15 May 2025 12:22:58 +0300 Subject: [PATCH 12/14] fixed issue #30 by adding Hostname support to Sender and AsyncSender --- examples/sender/asynchronous/agent_config_using.py | 2 +- examples/sender/synchronous/agent_config_using.py | 2 +- zabbix_utils/aiosender.py | 4 +++- zabbix_utils/sender.py | 5 +++-- 4 files changed, 8 insertions(+), 5 deletions(-) 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/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/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)]) From 081b4607c1eec61ed085fbc40a35dea902df8f0f Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Thu, 3 Jul 2025 11:26:01 +0300 Subject: [PATCH 13/14] fixed typos in the examples --- examples/sender/asynchronous/tls_cert_context_from_config.py | 1 + 1 file changed, 1 insertion(+) 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 ) From fbf9759efdda9eeb3894e50bb13d0d0d40367c04 Mon Sep 17 00:00:00 2001 From: Aleksandr Iantsen Date: Thu, 3 Jul 2025 11:35:59 +0300 Subject: [PATCH 14/14] updated CHANGELOG and version number --- CHANGELOG.md | 19 +++++++++++++++++++ zabbix_utils/version.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) 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/zabbix_utils/version.py b/zabbix_utils/version.py index da223db..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__ = 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