<?php /* ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ require_once dirname(__FILE__).'/../include/CIntegrationTest.php'; /** * Test suite for autoregistration * * @required-components server, agent * @configurationDataProvider agentConfigurationProvider * @backup ids,hosts,items,actions,operations,optag,host_tag * @backup auditlog,changelog,config,ha_node */ class testAutoregistration extends CIntegrationTest { const HOST_METADATA1 = "autoreg 1"; const HOST_METADATA2 = "autoreg 2"; const AUTOREG_ACTION_NAME1 = 'Test autoregistration action 1'; const AUTOREG_ACTION_NAME2 = 'Test autoregistration action 2'; const ITEM_KEY = "item_key"; const LLD_KEY = "lld_key"; public static $HOST_METADATA = self::HOST_METADATA1; public static $items = [ [ 'name' => self::ITEM_KEY, 'key_' => self::ITEM_KEY, 'type' => ITEM_TYPE_TRAPPER, 'value_type' => ITEM_VALUE_TYPE_UINT64 ] ]; public static $lldrules = [ [ 'name' => self::LLD_KEY, 'key_' => self::LLD_KEY, 'type' => ITEM_TYPE_TRAPPER, 'lifetime_type' => 0, 'lifetime' => '1d', 'enabled_lifetime_type' => 0, 'enabled_lifetime' => '3h' ] ]; private function waitForAutoreg($expectedTags) { $max_attempts = 5; $sleep_time = 2; for ($i = 0; $i < $max_attempts; $i++) { try { $response = $this->call('host.get', [ 'selectTags' => ['tag', 'value'] ]); $this->assertArrayHasKey('result', $response, 'Failed to autoregister host before timeout'); $this->assertCount(1, $response['result'], 'Failed to autoregister host before timeout'); $this->assertArrayHasKey('tags', $response['result'][0], 'Failed to autoregister host before timeout'); $autoregHost = $response['result'][0]; $this->assertArrayHasKey('hostid', $autoregHost, 'Failed to get host ID of the autoregistered host'); $tags = $autoregHost['tags']; $this->assertCount(count($expectedTags), $tags, 'Unexpected tags count was detected'); foreach ($expectedTags as $tag) { $this->assertContains($tag, $tags); } break; } catch (Exception $e) { if ($i == $max_attempts - 1) throw $e; else sleep($sleep_time); } } return $autoregHost['hostid']; } /** * Component configuration provider for agent related tests. * * @return array */ public function agentConfigurationProvider() { return [ self::COMPONENT_AGENT => [ 'Hostname' => self::COMPONENT_AGENT, 'ServerActive' => '127.0.0.1:'.self::getConfigurationValue(self::COMPONENT_SERVER, 'ListenPort'), 'HostMetadata' => self::$HOST_METADATA ] ]; } /** * @inheritdoc */ public function prepareData() { $response = $this->call('host.get', []); $hostids = array(); foreach ($response['result'] as $host) { $hostids[] = $host['hostid']; } $this->call('host.delete', $hostids); $response = $this->call('host.get', []); $this->assertArrayHasKey('result', $response, 'Failed to clear existing hosts during test setup'); $this->assertCount(0, $response['result'], 'Failed to clear existing hosts during test setup'); $response = $this->call('templategroup.get', [ 'filter' => [ 'name' => 'Templates' ] ]); $this->assertCount(1, $response['result']); $templategroupid = $response['result'][0]['groupid']; $response = $this->call('template.create', [ 'host' => 'test_template', 'groups' => [ 'groupid' => $templategroupid ] ]); $this->assertCount(1, $response['result']['templateids']); $templateid = $response['result']['templateids'][0]; $items = []; foreach (self::$items as $item) { $items[] = [ 'name' => $item['name'], 'key_' => $item['key_'], 'type' => $item['type'], 'value_type' => $item['value_type'], 'hostid' => $templateid ]; } $response = $this->call('item.create', $items); $this->assertCount(count($items), $response['result']['itemids']); $lldrules = []; foreach (self::$lldrules as $lldrule) { $lldrules[] = [ 'name' => $lldrule['name'], 'key_' => $lldrule['key_'], 'type' => $lldrule['type'], 'lifetime_type' => $lldrule['lifetime_type'], 'lifetime' => $lldrule['lifetime'], 'enabled_lifetime_type' => $lldrule['enabled_lifetime_type'], 'enabled_lifetime' => $lldrule['enabled_lifetime'], 'hostid' => $templateid ]; } $response = $this->call('discoveryrule.create', $lldrules); $this->assertCount(count($lldrules), $response['result']['itemids']); $response = $this->call('action.create', [ [ 'name' => self::AUTOREG_ACTION_NAME1, 'eventsource' => EVENT_SOURCE_AUTOREGISTRATION, 'status' => ACTION_STATUS_ENABLED, 'filter' => [ 'conditions' => [ [ 'conditiontype' => ZBX_CONDITION_TYPE_HOST_NAME, 'operator' => CONDITION_OPERATOR_LIKE, 'value' => self::COMPONENT_AGENT ], [ 'conditiontype' => ZBX_CONDITION_TYPE_HOST_METADATA, 'operator' => CONDITION_OPERATOR_LIKE, 'value' => self::HOST_METADATA1 ] ], 'evaltype' => CONDITION_EVAL_TYPE_AND_OR ], 'operations' => [ /* OPERATION_TYPE_HOST_ADD is intentionally missing. It is expected to be run by */ /* Zabbix server, because OPERATION_TYPE_HOST_TAGS_ADD is present. */ [ 'operationtype' => OPERATION_TYPE_HOST_TAGS_ADD, 'optag' => [ [ 'tag' => 'a1', 'value' => 'autoreg 1' ], [ 'tag' => 'tag1', 'value' => 'value 1' ] ] ], [ 'operationtype' => OPERATION_TYPE_HOST_TAGS_REMOVE, 'optag' => [ [ 'tag' => 'a2', 'value' => 'autoreg 2' ], [ 'tag' => 'tag2', 'value' => 'value 2' ] ] ], [ 'operationtype' => OPERATION_TYPE_TEMPLATE_ADD, 'optemplate' => [ [ 'templateid' => $templateid ] ] ] ] ], [ 'name' => self::AUTOREG_ACTION_NAME2, 'eventsource' => EVENT_SOURCE_AUTOREGISTRATION, 'status' => ACTION_STATUS_ENABLED, 'filter' => [ 'conditions' => [ [ 'conditiontype' => ZBX_CONDITION_TYPE_HOST_NAME, 'operator' => CONDITION_OPERATOR_LIKE, 'value' => self::COMPONENT_AGENT ], [ 'conditiontype' => ZBX_CONDITION_TYPE_HOST_METADATA, 'operator' => CONDITION_OPERATOR_LIKE, 'value' => self::HOST_METADATA2 ] ], 'evaltype' => CONDITION_EVAL_TYPE_AND_OR ], 'operations' => [ /* OPERATION_TYPE_HOST_ADD is intentionally missing. It is expected to be run by */ /* Zabbix server, because OPERATION_TYPE_HOST_TAGS_ADD is present. */ [ 'operationtype' => OPERATION_TYPE_HOST_TAGS_ADD, 'optag' => [ [ 'tag' => 'a2', 'value' => 'autoreg 2' ], [ 'tag' => 'tag2', 'value' => 'value 2' ] ] ], [ 'operationtype' => OPERATION_TYPE_HOST_TAGS_REMOVE, 'optag' => [ [ 'tag' => 'a1', 'value' => 'autoreg 1' ], [ 'tag' => 'tag1', 'value' => 'value 1' ] ] ] ] ]]); $this->assertArrayHasKey('result', $response, 'Failed to create an autoregistration action'); $this->assertArrayHasKey('actionids', $response['result'], 'Failed to create an autoregistration action'); $actionids = $response['result']['actionids']; $this->assertCount(2, $actionids, 'Failed to create an autoregistration action'); } /** * @required-components agent * @configurationDataProvider agentConfigurationProvider */ public function testAutoregistration_autoregHost1FirstTime() { $hostid = $this->waitForAutoreg([ ['tag' => 'a1', 'value' => 'autoreg 1'], ['tag' => 'tag1', 'value' => 'value 1'] ]); $response = $this->call('item.get', [ 'hostids' => [ $hostid ], 'output' => [ 'name', 'key_', 'type', 'value_type' ] ]); $this->assertCount(count(self::$items), $response['result']); for ($i = 0; $i < count($response['result']); $i++) { unset($response['result'][$i]['itemid']); $this->assertContains($response['result'][$i], self::$items); } $response = $this->call('discoveryrule.get', [ 'hostids' => [ $hostid ], 'output' => [ 'name', 'key_', 'type', 'lifetime_type', 'lifetime', 'enabled_lifetime_type', 'enabled_lifetime' ] ]); $this->assertCount(count(self::$lldrules), $response['result']); for ($i = 0; $i < count($response['result']); $i++) { unset($response['result'][$i]['itemid']); $this->assertContains($response['result'][$i], self::$lldrules); } self::$HOST_METADATA = self::HOST_METADATA2; } /** * @required-components agent * @configurationDataProvider agentConfigurationProvider * @depends testAutoregistration_autoregHost1FirstTime */ public function testAutoregistration_autoregHost2() { $this->waitForAutoreg([ ['tag' => 'a2', 'value' => 'autoreg 2'], ['tag' => 'tag2', 'value' => 'value 2'] ]); self::$HOST_METADATA = self::HOST_METADATA1; } /** * @required-components agent * @configurationDataProvider agentConfigurationProvider * @depends testAutoregistration_autoregHost2 */ public function testAutoregistration_autoregHost1SecondTime() { $this->waitForAutoreg([ ['tag' => 'a1', 'value' => 'autoreg 1'], ['tag' => 'tag1', 'value' => 'value 1'] ]); } }