diff --git a/.github/scripts/additional_api_tests.py b/.github/scripts/additional_api_tests.py index 1ffe373..2ad8661 100644 --- a/.github/scripts/additional_api_tests.py +++ b/.github/scripts/additional_api_tests.py @@ -6,7 +6,6 @@ import sys import ssl -import base64 import unittest from aiohttp import ClientSession, TCPConnector @@ -18,77 +17,6 @@ ZABBIX_URL = 'https://127.0.0.1:443' ZABBIX_USER = 'Admin' ZABBIX_PASSWORD = 'zabbix' -HTTP_USER = 'http_user' -HTTP_PASSWORD = 'http_pass' - - -class IntegrationAPITest(unittest.TestCase): - """Test working with a real Zabbix API instance synchronously""" - - def setUp(self): - self.user = ZABBIX_USER - self.password = ZABBIX_PASSWORD - self.url = ZABBIX_URL + '/http_auth/' - self.api = ZabbixAPI( - url=self.url, - user=self.user, - password=self.password, - skip_version_check=True, - validate_certs=False, - http_user=HTTP_USER, - http_password=HTTP_PASSWORD - ) - - def tearDown(self): - if self.api: - self.api.logout() - - def test_login(self): - """Tests login function works properly""" - - self.assertEqual( - type(self.api), ZabbixAPI, "Login was going wrong") - self.assertEqual( - type(self.api.api_version()), APIVersion, "Version getting was going wrong") - - def test_basic_auth(self): - """Tests __basic_auth function works properly""" - - self.assertEqual( - self.api._ZabbixAPI__basic_cred, base64.b64encode( - "http_user:http_pass".encode() - ).decode(), "Basic auth credentials generation was going wrong") - - def test_version_get(self): - """Tests getting version info works properly""" - - version = None - if self.api: - version = self.api.apiinfo.version() - self.assertEqual( - version, str(self.api.api_version()), "Request apiinfo.version was going wrong") - - def test_check_auth(self): - """Tests checking authentication state works properly""" - - resp = None - if self.api: - if self.api._ZabbixAPI__session_id == self.api._ZabbixAPI__token: - resp = self.api.user.checkAuthentication(token=self.api._ZabbixAPI__session_id) - else: - resp = self.api.user.checkAuthentication(sessionid=self.api._ZabbixAPI__session_id) - self.assertEqual( - type(resp), dict, "Request user.checkAuthentication was going wrong") - - def test_user_get(self): - """Tests getting users info works properly""" - - users = None - if self.api: - users = self.api.user.get( - output=['userid', 'name'] - ) - self.assertEqual(type(users), list, "Request user.get was going wrong") class CustomCertAPITest(unittest.TestCase): @@ -154,80 +82,6 @@ def test_user_get(self): self.assertEqual(type(users), list, "Request user.get was going wrong") -class IntegrationAsyncAPITest(unittest.IsolatedAsyncioTestCase): - """Test working with a real Zabbix API instance asynchronously""" - - async def asyncSetUp(self): - self.user = ZABBIX_USER - self.password = ZABBIX_PASSWORD - self.url = ZABBIX_URL + '/http_auth/' - self.api = AsyncZabbixAPI( - url=self.url, - skip_version_check=True, - validate_certs=False, - http_user=HTTP_USER, - http_password=HTTP_PASSWORD - ) - await self.api.login( - user=self.user, - password=self.password - ) - - async def asyncTearDown(self): - if self.api: - await self.api.logout() - - async def test_login(self): - """Tests login function works properly""" - - self.assertEqual( - type(self.api), AsyncZabbixAPI, "Login was going wrong") - self.assertEqual( - type(self.api.api_version()), APIVersion, "Version getting was going wrong") - - async def test_basic_auth(self): - """Tests __basic_auth function works properly""" - - basic_auth = self.api.client_session._default_auth - - self.assertEqual( - base64.b64encode(f"{basic_auth.login}:{basic_auth.password}".encode()).decode(), - base64.b64encode(f"{HTTP_USER}:{HTTP_PASSWORD}".encode()).decode(), - "Basic auth credentials generation was going wrong" - ) - - async def test_version_get(self): - """Tests getting version info works properly""" - - version = None - if self.api: - version = await self.api.apiinfo.version() - self.assertEqual( - version, str(self.api.api_version()), "Request apiinfo.version was going wrong") - - async def test_check_auth(self): - """Tests checking authentication state works properly""" - - resp = None - if self.api: - if self.api._AsyncZabbixAPI__session_id == self.api._AsyncZabbixAPI__token: - resp = await self.api.user.checkAuthentication(token=(self.api._AsyncZabbixAPI__session_id or '')) - else: - resp = await self.api.user.checkAuthentication(sessionid=(self.api._AsyncZabbixAPI__session_id or '')) - self.assertEqual( - type(resp), dict, "Request user.checkAuthentication was going wrong") - - async def test_user_get(self): - """Tests getting users info works properly""" - - users = None - if self.api: - users = await self.api.user.get( - output=['userid', 'name'] - ) - self.assertEqual(type(users), list, "Request user.get was going wrong") - - class CustomCertAsyncAPITest(unittest.IsolatedAsyncioTestCase): """Test working with a real Zabbix API instance asynchronously""" @@ -238,14 +92,14 @@ async def asyncSetUp(self): context = ssl.create_default_context() context.load_verify_locations('/etc/nginx/ssl/nginx.crt') - session = ClientSession( + self.session = ClientSession( connector=TCPConnector(ssl=context) ) self.api = AsyncZabbixAPI( url=self.url, skip_version_check=True, - client_session=session + client_session=self.session ) await self.api.login( user=self.user, @@ -255,6 +109,8 @@ async def asyncSetUp(self): async def asyncTearDown(self): if self.api: await self.api.logout() + if not self.session.closed: + await self.session.close() async def test_login(self): """Tests login function works properly""" diff --git a/.github/scripts/depricated_tests.py b/.github/scripts/depricated_tests.py new file mode 100644 index 0000000..2113cc3 --- /dev/null +++ b/.github/scripts/depricated_tests.py @@ -0,0 +1,171 @@ +#!/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 base64 +import unittest + +sys.path.append('.') +from zabbix_utils.api import ZabbixAPI +from zabbix_utils.types import APIVersion +from zabbix_utils.aioapi import AsyncZabbixAPI + +ZABBIX_URL = 'https://127.0.0.1:443' +ZABBIX_USER = 'Admin' +ZABBIX_PASSWORD = 'zabbix' +HTTP_USER = 'http_user' +HTTP_PASSWORD = 'http_pass' + + +class BasicAuthAPITest(unittest.TestCase): + """Test working with a real Zabbix API instance using Basic auth synchronously + + Should be removed after: `June 30, 2029` + """ + + def setUp(self): + self.user = ZABBIX_USER + self.password = ZABBIX_PASSWORD + self.url = ZABBIX_URL + '/http_auth/' + self.api = ZabbixAPI( + url=self.url, + user=self.user, + password=self.password, + validate_certs=False, + http_user=HTTP_USER, + http_password=HTTP_PASSWORD + ) + + def tearDown(self): + if self.api: + self.api.logout() + + def test_login(self): + """Tests login function works properly""" + + self.assertEqual( + type(self.api), ZabbixAPI, "Login was going wrong") + self.assertEqual( + type(self.api.api_version()), APIVersion, "Version getting was going wrong") + + def test_basic_auth(self): + """Tests __basic_auth function works properly""" + + self.assertEqual( + self.api._ZabbixAPI__basic_cred, base64.b64encode( + "http_user:http_pass".encode() + ).decode(), "Basic auth credentials generation was going wrong") + + def test_version_get(self): + """Tests getting version info works properly""" + + version = None + if self.api: + version = self.api.apiinfo.version() + self.assertEqual( + version, str(self.api.api_version()), "Request apiinfo.version was going wrong") + + def test_check_auth(self): + """Tests checking authentication state works properly""" + + resp = None + if self.api: + if self.api._ZabbixAPI__session_id == self.api._ZabbixAPI__token: + resp = self.api.user.checkAuthentication(token=self.api._ZabbixAPI__session_id) + else: + resp = self.api.user.checkAuthentication(sessionid=self.api._ZabbixAPI__session_id) + self.assertEqual( + type(resp), dict, "Request user.checkAuthentication was going wrong") + + def test_user_get(self): + """Tests getting users info works properly""" + + users = None + if self.api: + users = self.api.user.get( + output=['userid', 'name'] + ) + self.assertEqual(type(users), list, "Request user.get was going wrong") + + +class BasicAuthAsyncAPITest(unittest.IsolatedAsyncioTestCase): + """Test working with a real Zabbix API instance using Basic auth asynchronously + + Should be removed after: `June 30, 2029` + """ + + async def asyncSetUp(self): + self.user = ZABBIX_USER + self.password = ZABBIX_PASSWORD + self.url = ZABBIX_URL + '/http_auth/' + self.api = AsyncZabbixAPI( + url=self.url, + validate_certs=False, + http_user=HTTP_USER, + http_password=HTTP_PASSWORD + ) + await self.api.login( + user=self.user, + password=self.password + ) + + async def asyncTearDown(self): + if self.api: + await self.api.logout() + + async def test_login(self): + """Tests login function works properly""" + + self.assertEqual( + type(self.api), AsyncZabbixAPI, "Login was going wrong") + self.assertEqual( + type(self.api.api_version()), APIVersion, "Version getting was going wrong") + + async def test_basic_auth(self): + """Tests __basic_auth function works properly""" + + basic_auth = self.api.client_session._default_auth + + self.assertEqual( + base64.b64encode(f"{basic_auth.login}:{basic_auth.password}".encode()).decode(), + base64.b64encode(f"{HTTP_USER}:{HTTP_PASSWORD}".encode()).decode(), + "Basic auth credentials generation was going wrong" + ) + + async def test_version_get(self): + """Tests getting version info works properly""" + + version = None + if self.api: + version = await self.api.apiinfo.version() + self.assertEqual( + version, str(self.api.api_version()), "Request apiinfo.version was going wrong") + + async def test_check_auth(self): + """Tests checking authentication state works properly""" + + resp = None + if self.api: + if self.api._AsyncZabbixAPI__session_id == self.api._AsyncZabbixAPI__token: + resp = await self.api.user.checkAuthentication(token=(self.api._AsyncZabbixAPI__session_id or '')) + else: + resp = await self.api.user.checkAuthentication(sessionid=(self.api._AsyncZabbixAPI__session_id or '')) + self.assertEqual( + type(resp), dict, "Request user.checkAuthentication was going wrong") + + async def test_user_get(self): + """Tests getting users info works properly""" + + users = None + if self.api: + users = await self.api.user.get( + output=['userid', 'name'] + ) + self.assertEqual(type(users), list, "Request user.get was going wrong") + + +if __name__ == '__main__': + unittest.main() diff --git a/.github/workflows/additional_tests.yaml b/.github/workflows/additional_tests.yaml index 7d06ccc..1478992 100644 --- a/.github/workflows/additional_tests.yaml +++ b/.github/workflows/additional_tests.yaml @@ -9,8 +9,7 @@ on: workflow_dispatch: env: - ZABBIX_VERSION: '7.0' - ZABBIX_BRANCH: release/$ZABBIX_VERSION + ZABBIX_BRANCH: master CONFIG_PATH: .github/configs/ TEST_FILE: additional_api_tests.py @@ -53,7 +52,7 @@ jobs: TBOT_CHAT: ${{ vars.TBOT_CHAT }} SUBJECT: Importing tests with requirements FAIL run: | - bash ./.github/scripts/library_import_tests.sh "async" "AsyncZabbixAPI" "aiohttp.client.ClientSession" > /tmp/importing.log + bash ./.github/scripts/library_import_tests.sh "async" "AsyncZabbixAPI" "Unable to connect to" > /tmp/importing.log - name: Raise an exception run: | test $(cat /tmp/importing.log | wc -l) -eq 0 || exit 1 @@ -117,7 +116,7 @@ jobs: run: | sudo apt-get install -y python3 python3-pip python-is-python3 pip install -r ./requirements.txt - - name: Additional tests + - name: Run tests continue-on-error: true run: | sleep 5 diff --git a/.github/workflows/compatibility_64.yaml b/.github/workflows/compatibility_72.yaml similarity index 66% rename from .github/workflows/compatibility_64.yaml rename to .github/workflows/compatibility_72.yaml index e26b192..73ef9d3 100644 --- a/.github/workflows/compatibility_64.yaml +++ b/.github/workflows/compatibility_72.yaml @@ -1,5 +1,5 @@ -name: zabbix_64 -run-name: Compatibility with Zabbix 6.4 test +name: zabbix_72 +run-name: Compatibility with Zabbix 7.2 test on: push: @@ -9,10 +9,10 @@ on: workflow_dispatch: env: - ZABBIX_VERSION: '6.4' + ZABBIX_VERSION: '7.2' ZABBIX_BRANCH: release/$ZABBIX_VERSION CONFIG_PATH: .github/configs/ - TEST_FILE: compatibility_api_test_6.py + TEST_FILE: compatibility_api_test_7.py jobs: compatibility: @@ -23,7 +23,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-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 - name: Build from sources run: | WORKDIR=$(pwd) @@ -35,6 +35,26 @@ 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/ @@ -66,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/depricated_tests.yaml b/.github/workflows/depricated_tests.yaml new file mode 100644 index 0000000..f76ef83 --- /dev/null +++ b/.github/workflows/depricated_tests.yaml @@ -0,0 +1,89 @@ +name: depricated_tests +run-name: Tests for deprecated features + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +env: + ZABBIX_VERSION: '7.0' + ZABBIX_BRANCH: release/$ZABBIX_VERSION + CONFIG_PATH: .github/configs/ + TEST_FILE: depricated_tests.py + +jobs: + depricated-tests: + name: Depricated tests + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - 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 + - 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 --with-postgresql + sudo make dbschema_postgresql + echo -e "CacheUpdateFrequency=1\n" >> ./conf/zabbix_server.conf + sudo mkdir -p /etc/nginx/ssl/ + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/.htpasswd /etc/nginx/.htpasswd + sudo cp $WORKDIR/${{ env.CONFIG_PATH }}/default.conf /etc/nginx/sites-enabled/default + sudo openssl req -x509 -nodes -days 1 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt -config $WORKDIR/${{ env.CONFIG_PATH }}/nginx.cnf + sudo chown -R www-data:www-data /etc/nginx/ + 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/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/Listen 80/Listen 8080/g" /etc/apache2/ports.conf + sudo sed -i "s///g" /etc/apache2/sites-enabled/000-default.conf + 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)& + 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 + - name: Start Apache & Nginx + run: | + sudo apache2ctl start + sudo nginx -g "daemon on; master_process on;" + - name: Install python3 + run: | + sudo apt-get install -y python3 python3-pip python-is-python3 + pip install -r ./requirements.txt + - name: Run tests + continue-on-error: true + run: | + sleep 5 + python ./.github/scripts/$TEST_FILE 2>/tmp/depricated.log >/dev/null + - name: Send report + env: + TBOT_TOKEN: ${{ secrets.TBOT_TOKEN }} + TBOT_CHAT: ${{ vars.TBOT_CHAT }} + SUBJECT: Zabbix API depricated tests FAIL + run: | + tail -n1 /tmp/depricated.log | grep "OK" 1>/dev/null || tail /tmp/depricated.log | python ./.github/scripts/telegram_msg.py | exit 1 diff --git a/README.md b/README.md index d891ad0..58a61c1 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ [![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 6.4](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_64.yaml/badge.svg)](https://github.com/zabbix/python-zabbix-utils/actions/workflows/compatibility_64.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_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. @@ -29,7 +29,7 @@ Supported versions: Tested on: -* Zabbix 5.0, 6.0, 6.4 and 7.0 +* Zabbix 5.0, 6.0, 7.0 and 7.2 * Python 3.8, 3.9, 3.10, 3.11 and 3.12 Dependencies: diff --git a/zabbix_utils/version.py b/zabbix_utils/version.py index 7a3edd3..04ea5ab 100644 --- a/zabbix_utils/version.py +++ b/zabbix_utils/version.py @@ -25,4 +25,4 @@ __version__ = "2.0.1" __min_supported__ = 5.0 -__max_supported__ = 7.0 +__max_supported__ = 7.2