You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4131 lines
113 KiB

<?php
/*
** Zabbix
** Copyright (C) 2001-2023 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
require_once __DIR__.'/../include/CAPITest.php';
/**
* @onBefore prepareHostsData
*
* @onAfter clearData
*/
class testHost extends CAPITest {
private static $data = [
'hostgroupid' => null,
'hostids' => [
// Test host.delete if hosts are in maintenance.
'maintenance_1' => null,
'maintenance_2' => null,
'maintenance_3' => null,
'maintenance_4' => null,
'maintenance_5' => null,
'maintenance_6' => null,
'maintenance_7' => null,
// Test host.get with tags.
'tags' => null,
// Test host.get with write-only fields.
'write_only' => null,
// Host with LLD rule and host prototype.
'with_lld_and_prototype' => null,
// Discovered hosts to test host.update, host.massupdate, host.massadd, host.massremove.
'discovered_no_templates' => null,
'discovered_manual_templates' => null,
'discovered_auto_templates' => null,
'discovered_auto_and_manual_templates' => null,
'discovered_no_macros' => null,
'discovered_manual_macros' => null,
'discovered_auto_macros' => null,
'discovered_auto_and_manual_macros' => null,
// Discovered host to test if items are cleared as well.
'discovered_clear' => null,
// Discovered host to test host.get with limitSelects option.
'discovered_limit_selects' => null
],
'templategroupid' => null,
'templateids' => [
'api_test_hosts_f_tpl' => null,
'api_test_hosts_c_tpl' => null,
'api_test_hosts_a_tpl' => null,
'api_test_hosts_e_tpl' => null,
'api_test_hosts_b_tpl' => null,
'api_test_hosts_d_tpl' => null,
'api_test_hosts_tpl_with_item' => null
],
'maintenanceids' => null,
// Keys must match the macro names. For example discovered_macro_text_a => {$DISCOVERED_MACRO_TEXT_A}
'hostmacroids' => [
'discovered_macro_text_a' => null,
'discovered_macro_secret_a' => null,
'discovered_macro_vault_a' => null,
'discovered_macro_text_b' => null,
'discovered_macro_secret_b' => null,
'discovered_macro_vault_b' => null,
'manual_macro_text_c' => null,
'manual_macro_secret_c' => null,
'manual_macro_vault_c' => null,
'manual_macro_text_d' => null,
'manual_macro_secret_d' => null,
'manual_macro_vault_d' => null
],
// Created hosts during host.create test (deleted at the end).
'created' => []
];
public function prepareHostsData() {
// Create host group.
$hostgroups = CDataHelper::call('hostgroup.create', [
[
'name' => 'API test hosts'
]
]);
$this->assertArrayHasKey('groupids', $hostgroups);
self::$data['hostgroupid'] = $hostgroups['groupids'][0];
// Create hosts.
$hosts_data = [
// Both hosts are in maintenance, so only one can be deleted.
[
'host' => 'api_test_hosts_maintenance_1',
'name' => 'API test hosts - maintenance 1',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => 'api_test_hosts_maintenance_2',
'name' => 'API test hosts - maintenance 2',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
// Both hosts are in maintenance, so only one can be deleted.
[
'host' => 'api_test_hosts_maintenance_3',
'name' => 'API test hosts - maintenance 3',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => 'api_test_hosts_maintenance_4',
'name' => 'API test hosts - maintenance 4',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
// Both hosts are in maintenance, both cannot be deleted at the same time.
[
'host' => 'api_test_hosts_maintenance_5',
'name' => 'API test hosts - maintenance 5',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => 'api_test_hosts_maintenance_6',
'name' => 'API test hosts - maintenance 6',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
// One host is in maintenance. Used together with a group.
[
'host' => 'api_test_hosts_maintenance_7',
'name' => 'API test hosts - maintenance 7',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
// Host with tags.
[
'host' => 'api_test_hosts_tags',
'name' => 'API test hosts - tags',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
],
'tags' => [
[
'tag' => 'b',
'value' => 'b'
]
]
],
// Host with write-only fields.
[
'host' => 'api_test_hosts_write_only_fields',
'name' => 'API test hosts - write-only fields',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
// Host with LLD rule and host prototype.
[
'host' => 'api_test_hosts_lld',
'name' => 'API test hosts - LLD',
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
]
]
];
$hosts = CDataHelper::call('host.create', $hosts_data);
$this->assertArrayHasKey('hostids', $hosts);
self::$data['hostids'] = [
'maintenance_1' => $hosts['hostids'][0],
'maintenance_2' => $hosts['hostids'][1],
'maintenance_3' => $hosts['hostids'][2],
'maintenance_4' => $hosts['hostids'][3],
'maintenance_5' => $hosts['hostids'][4],
'maintenance_6' => $hosts['hostids'][5],
'maintenance_7' => $hosts['hostids'][6],
'tags' => $hosts['hostids'][7],
'write_only' => $hosts['hostids'][8],
'with_lld_and_prototype' => $hosts['hostids'][9]
];
// Create maintenances. Use same time period for all maintenances.
$timeperiods = [
[
'period' => 3600,
'timeperiod_type' => 3,
'start_time' => 64800,
'every' => 1,
'dayofweek' => 64
]
];
$maintenances_data = [
[
'name' => 'API test hosts - maintenance with one host',
'active_since' => '1539723600',
'active_till' => '1539810000',
'hosts' => [
[
'hostid' => self::$data['hostids']['maintenance_1']
]
],
'timeperiods' => $timeperiods
],
[
'name' => 'API test hosts - maintenance with host and group (deletable)',
'active_since' => '1539723600',
'active_till' => '1539810000',
'hosts' => [
[
'hostid' => self::$data['hostids']['maintenance_2']
]
],
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
],
'timeperiods' => $timeperiods
],
[
'name' => 'API test hosts - maintenance with two hosts (deletable)',
'active_since' => '1539723600',
'active_till' => '1539810000',
'hosts' => [
[
'hostid' => self::$data['hostids']['maintenance_3']
],
[
'hostid' => self::$data['hostids']['maintenance_4']
]
],
'timeperiods' => $timeperiods
],
[
'name' => 'API test hosts - maintenance with two hosts (non-deletable)',
'active_since' => '1539723600',
'active_till' => '1539810000',
'hosts' => [
[
'hostid' => self::$data['hostids']['maintenance_5']
],
[
'hostid' => self::$data['hostids']['maintenance_6']
]
],
'timeperiods' => $timeperiods
],
[
'name' => 'API test hosts - maintenance with host and group (non-deletable)',
'active_since' => '1539723600',
'active_till' => '1539810000',
'hosts' => [
[
'hostid' => self::$data['hostids']['maintenance_7']
]
],
'groups' => [
[
'groupid' => self::$data['hostgroupid']
]
],
'timeperiods' => $timeperiods
]
];
$maintenances = CDataHelper::call('maintenance.create', $maintenances_data);
$this->assertArrayHasKey('maintenanceids', $maintenances);
self::$data['maintenanceids'] = $maintenances['maintenanceids'];
// Create template group.
$templategroups = CDataHelper::call('templategroup.create', [
[
'name' => 'API test templates'
]
]);
$this->assertArrayHasKey('groupids', $templategroups);
self::$data['templategroupid'] = $templategroups['groupids'][0];
// Create templates that will be added to host prototypes and essentially discovered hosts.
$templates_data = [
// Templates for discovered hosts. When host.get "limitSelects" is used, templates should be sorted A-Z.
[
'host' => 'api_test_hosts_f_tpl',
'name' => 'API test hosts - F template',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
],
[
'host' => 'api_test_hosts_c_tpl',
'name' => 'API test hosts - C template',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
],
[
'host' => 'api_test_hosts_a_tpl',
'name' => 'API test hosts - A template',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
],
[
'host' => 'api_test_hosts_e_tpl',
'name' => 'API test hosts - E template',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
],
[
'host' => 'api_test_hosts_b_tpl',
'name' => 'API test hosts - B template',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
],
[
'host' => 'api_test_hosts_d_tpl',
'name' => 'API test hosts - D template',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
],
/*
* Template for discovered host, but it has one item. Using "templates_clear" option, item should also be
* removed from host, otherwise item should stay there.
*/
[
'host' => 'api_test_hosts_tpl_with_item',
'name' => 'API test hosts - template with item',
'groups' => [
[
'groupid' => self::$data['templategroupid']
]
]
]
];
$templates = CDataHelper::call('template.create', $templates_data);
$this->assertArrayHasKey('templateids', $templates);
self::$data['templateids']['api_test_hosts_f_tpl'] = $templates['templateids'][0];
self::$data['templateids']['api_test_hosts_c_tpl'] = $templates['templateids'][1];
self::$data['templateids']['api_test_hosts_a_tpl'] = $templates['templateids'][2];
self::$data['templateids']['api_test_hosts_e_tpl'] = $templates['templateids'][3];
self::$data['templateids']['api_test_hosts_b_tpl'] = $templates['templateids'][4];
self::$data['templateids']['api_test_hosts_d_tpl'] = $templates['templateids'][5];
self::$data['templateids']['api_test_hosts_tpl_with_item'] = $templates['templateids'][6];
/*
* Create item for that one template. Item IDs do not matter, because there is only one and it will removed
* after tests are complete together with this template.
*/
$items = CDataHelper::call('item.create', [
'hostid' => self::$data['templateids']['api_test_hosts_tpl_with_item'],
'name' => 'API test hosts - template item',
'key_' => 'api_test_hosts_tpl_item',
'type' => ITEM_TYPE_TRAPPER,
'value_type' => ITEM_VALUE_TYPE_FLOAT
]);
$this->assertArrayHasKey('itemids', $items);
// Create LLD rule.
$discoveryrules = CDataHelper::call('discoveryrule.create', [
'name' => 'LLD rule',
'key_' => 'lld_rule',
'hostid' => self::$data['hostids']['with_lld_and_prototype'],
'type' => ITEM_TYPE_TRAPPER
]);
$this->assertArrayHasKey('itemids', $discoveryrules);
// Create host prototypes.
$host_prototypes_data = [
[
'host' => '{#HOST}_no_templates',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => '{#HOST}_manual_templates',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => '{#HOST}_auto_templates',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
],
// First two templates.
'templates' => [
[
'templateid' => self::$data['templateids']['api_test_hosts_f_tpl']
],
[
'templateid' => self::$data['templateids']['api_test_hosts_c_tpl']
]
]
],
[
'host' => '{#HOST}_auto_and_manual_templates',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
],
// First two templates. Third and fourth templates are manually added.
'templates' => [
[
'templateid' => self::$data['templateids']['api_test_hosts_f_tpl']
],
[
'templateid' => self::$data['templateids']['api_test_hosts_c_tpl']
]
]
],
[
'host' => '{#HOST}_clear',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
],
// Template that has item.
'templates' => [
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_tpl_with_item']
]
]
],
[
'host' => '{#HOST}_limit_selects',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
],
// Does not matter if templates are manually added or automatically. Important is the order.
'templates' => [
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_f_tpl']
],
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_c_tpl']
],
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_a_tpl']
],
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_e_tpl']
],
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_b_tpl']
],
[
'templateid' => self::$data['templateids'][ 'api_test_hosts_d_tpl']
]
]
],
[
'host' => '{#HOST}_no_macros',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => '{#HOST}_manual_macros',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
]
],
[
'host' => '{#HOST}_auto_macros',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
],
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_A}',
'value' => 'discovered_macro_text_value_a',
'description' => 'discovered_macro_text_description_a',
'type' => ZBX_MACRO_TYPE_TEXT
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_A}',
'value' => 'discovered_macro_secret_value_a',
'description' => 'discovered_macro_secret_description_a',
'type' => ZBX_MACRO_TYPE_SECRET
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_A}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_a',
'type' => ZBX_MACRO_TYPE_VAULT
]
]
],
// First three macros are automatic. The rest are manually added.
[
'host' => '{#HOST}_auto_and_manual_macros',
'ruleid' => $discoveryrules['itemids'][0],
'groupLinks' => [
[
'groupid' => self::$data['hostgroupid']
]
],
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_B}',
'value' => 'discovered_macro_text_value_b',
'description' => 'discovered_macro_text_description_b',
'type' => ZBX_MACRO_TYPE_TEXT
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_B}',
'value' => 'discovered_macro_secret_value_b',
'description' => 'discovered_macro_secret_description_b',
'type' => ZBX_MACRO_TYPE_SECRET
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_B}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_b',
'type' => ZBX_MACRO_TYPE_VAULT
]
]
]
];
$host_prototypes = CDataHelper::call('hostprototype.create', $host_prototypes_data);
$this->assertArrayHasKey('hostids', $host_prototypes);
// Create discovered hosts.
$hosts_data = [];
foreach ($host_prototypes_data as $idx => $host_prototype) {
$hosts_data[] = [
'host' => str_replace('{#HOST}', 'discovered', $host_prototype['host']),
'groups' => $host_prototype['groupLinks'],
'macros' => array_key_exists('macros', $host_prototype) ? $host_prototype['macros'] : [],
'templates' => array_key_exists('templates', $host_prototype) ? $host_prototype['templates'] : []
];
}
$hosts = CDataHelper::call('host.create', $hosts_data);
$this->assertArrayHasKey('hostids', $hosts);
self::$data['hostids']['discovered_no_templates'] = $hosts['hostids'][0];
self::$data['hostids']['discovered_manual_templates'] = $hosts['hostids'][1];
self::$data['hostids']['discovered_auto_templates'] = $hosts['hostids'][2];
self::$data['hostids']['discovered_auto_and_manual_templates'] = $hosts['hostids'][3];
self::$data['hostids']['discovered_clear'] = $hosts['hostids'][4];
self::$data['hostids']['discovered_limit_selects'] = $hosts['hostids'][5];
self::$data['hostids']['discovered_no_macros'] = $hosts['hostids'][6];
self::$data['hostids']['discovered_manual_macros'] = $hosts['hostids'][7];
self::$data['hostids']['discovered_auto_macros'] = $hosts['hostids'][8];
self::$data['hostids']['discovered_auto_and_manual_macros'] = $hosts['hostids'][9];
$host_discovery = [];
$upd_hosts = [];
$upd_hosts_templates = [];
$upd_hostmacro = [];
foreach ($host_prototypes_data as $idx => $host_prototype) {
$host_discovery[] = [
'hostid' => $hosts['hostids'][$idx],
'parent_hostid' => $host_prototypes['hostids'][$idx],
'host' => $host_prototype['host'],
'lastcheck' => '1648726056'
];
$upd_hosts[] = [
'values' => ['flags' => 4],
'where' => ['hostid' => $hosts['hostids'][$idx]]
];
if (array_key_exists('templates', $host_prototype) && $host_prototype['templates']) {
foreach ($host_prototype['templates'] as $template) {
$upd_hosts_templates[] = [
'values' => ['link_type' => TEMPLATE_LINK_LLD],
'where' => [
'hostid' => $hosts['hostids'][$idx],
'templateid' => $template['templateid']
]
];
}
}
if (array_key_exists('macros', $host_prototype) && $host_prototype['macros']) {
foreach ($host_prototype['macros'] as $macro) {
$upd_hostmacro[] = [
'values' => ['automatic' => ZBX_USERMACRO_AUTOMATIC],
'where' => [
'hostid' => $hosts['hostids'][$idx],
'macro' => $macro['macro']
]
];
}
}
}
$ids = DB::insertBatch('host_discovery', $host_discovery, false);
// Since insertBatch() parameter $getids is false, it will use existing IDs. Thus it will return empty array.
$this->assertSame([], $ids);
$res = DB::update('hosts', $upd_hosts);
$this->assertSame(true, $res);
$res = DB::update('hosts_templates', $upd_hosts_templates);
$this->assertSame(true, $res);
$res = DB::update('hostmacro', $upd_hostmacro);
$this->assertSame(true, $res);
// Add hostmacroid references using the macro name as key: {$MACRO_NAME} => macro_name.
foreach ($upd_hostmacro as $hostmacro) {
$db_hostmacro = CDBHelper::getRow(
'SELECT hm.hostmacroid'.
' FROM hostmacro hm'.
' WHERE hm.hostid='.zbx_dbstr($hostmacro['where']['hostid']).
' AND hm.macro='.zbx_dbstr($hostmacro['where']['macro'])
);
$key = str_replace('{$', '', $hostmacro['where']['macro']);
$key = str_replace('}', '', $key);
$key = strtolower($key);
self::$data['hostmacroids'][$key] = $db_hostmacro['hostmacroid'];
}
/*
* Add few manual templates to discovered hosts to test the template removal. Do not use API at this point.
* Cannot use CDBHelper::getValue, because it will add "LIMIT 1" at the end of query and MySQL does not support
* a syntax like that.
*/
$nextid = CDBHelper::getAll(
'SELECT i.nextid'.
' FROM ids i'.
' WHERE i.table_name='.zbx_dbstr('hosts_templates').
' AND i.field_name='.zbx_dbstr('hosttemplateid').
' FOR UPDATE'
)[0]['nextid'] + 1;
$hosts_templates_data = [
// Host contains only manual templates.
[
'hostid' => self::$data['hostids']['discovered_manual_templates'],
'templateid' => self::$data['templateids']['api_test_hosts_a_tpl'],
'link_type' => TEMPLATE_LINK_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_manual_templates'],
'templateid' => self::$data['templateids']['api_test_hosts_e_tpl'],
'link_type' => TEMPLATE_LINK_MANUAL
],
// Host contains automatically added templates and manually added templates.
[
'hostid' => self::$data['hostids']['discovered_auto_and_manual_templates'],
'templateid' => self::$data['templateids']['api_test_hosts_a_tpl'],
'link_type' => TEMPLATE_LINK_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_auto_and_manual_templates'],
'templateid' => self::$data['templateids']['api_test_hosts_e_tpl'],
'link_type' => TEMPLATE_LINK_MANUAL
]
];
$ids = DB::insertBatch('hosts_templates', $hosts_templates_data);
$newids = array_fill($nextid, count($hosts_templates_data), true);
$this->assertEquals(array_keys($newids), $ids);
// Add few manual macros to test host.update method.
$nextid = CDBHelper::getAll(
'SELECT i.nextid'.
' FROM ids i'.
' WHERE i.table_name='.zbx_dbstr('hostmacro').
' AND i.field_name='.zbx_dbstr('hostmacroid').
' FOR UPDATE'
)[0]['nextid'] + 1;
$hostmacro_data = [
[
'hostid' => self::$data['hostids']['discovered_manual_macros'],
'macro' => '{$MANUAL_MACRO_TEXT_C}',
'value' => 'manual_macro_text_value_c',
'description' => 'manual_macro_text_description_c',
'type' => ZBX_MACRO_TYPE_TEXT,
'automatic' => ZBX_USERMACRO_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_manual_macros'],
'macro' => '{$MANUAL_MACRO_SECRET_C}',
'value' => 'manual_macro_secret_value_c',
'description' => 'manual_macro_secret_description_c',
'type' => ZBX_MACRO_TYPE_SECRET,
'automatic' => ZBX_USERMACRO_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_manual_macros'],
'macro' => '{$MANUAL_MACRO_VAULT_C}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_c',
'type' => ZBX_MACRO_TYPE_VAULT,
'automatic' => ZBX_USERMACRO_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_auto_and_manual_macros'],
'macro' => '{$MANUAL_MACRO_TEXT_D}',
'value' => 'manual_macro_text_value_d',
'description' => 'manual_macro_text_description_d',
'type' => ZBX_MACRO_TYPE_TEXT,
'automatic' => ZBX_USERMACRO_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_auto_and_manual_macros'],
'macro' => '{$MANUAL_MACRO_SECRET_D}',
'value' => 'manual_macro_secreat_value_d',
'description' => 'manual_macro_secret_description_d',
'type' => ZBX_MACRO_TYPE_SECRET,
'automatic' => ZBX_USERMACRO_MANUAL
],
[
'hostid' => self::$data['hostids']['discovered_auto_and_manual_macros'],
'macro' => '{$MANUAL_MACRO_VAULT_D}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_d',
'type' => ZBX_MACRO_TYPE_VAULT,
'automatic' => ZBX_USERMACRO_MANUAL
]
];
$ids = DB::insertBatch('hostmacro', $hostmacro_data);
$newids = array_fill($nextid, count($hostmacro_data), true);
$this->assertEquals(array_keys($newids), $ids);
self::$data['hostmacroids']['manual_macro_text_c'] = $ids[0];
self::$data['hostmacroids']['manual_macro_secret_c'] = $ids[1];
self::$data['hostmacroids']['manual_macro_vault_c'] = $ids[2];
self::$data['hostmacroids']['manual_macro_text_d'] = $ids[3];
self::$data['hostmacroids']['manual_macro_secret_d'] = $ids[4];
self::$data['hostmacroids']['manual_macro_vault_d'] = $ids[5];
}
/**
* Data provider for host.delete. Array contains valid hosts that are possible to delete.
*
* @return array
*/
public static function getHostDeleteDataValid() {
return [
'Test host.delete host that has a group in same maintenance' => [
'hostids' => [
'maintenance_2'
],
'expected_error' => null
],
'Test host.delete host that another host in same maintenance' => [
'hostids' => [
'maintenance_3'
],
'expected_error' => null
]
];
}
/**
* Data provider for host.delete. Array contains invalid hosts that are not possible to delete.
*
* @return array
*/
public static function getHostDeleteDataInvalid() {
return [
'Test host.delete single host in maintenance' => [
'hostids' => [
'maintenance_1'
],
'expected_error' => 'Cannot delete host "api_test_hosts_maintenance_1" because maintenance "API test hosts - maintenance with one host" must contain at least one host or host group.'
],
'Test host.delete two hosts in maintenance, one is allowed, the other is not' => [
'hostids' => [
'maintenance_1',
'maintenance_7'
],
'expected_error' => 'Cannot delete host "api_test_hosts_maintenance_1" because maintenance "API test hosts - maintenance with one host" must contain at least one host or host group.'
],
'Test host.delete both from one maintenance' => [
'hostids' => [
'maintenance_5',
'maintenance_6'
],
'expected_error' => 'Cannot delete hosts "api_test_hosts_maintenance_5", "api_test_hosts_maintenance_6" because maintenance "API test hosts - maintenance with two hosts (non-deletable)" must contain at least one host or host group.'
]
];
}
/**
* Test host.delete if one host is in maintenance, more than one host is in maintenance, host and group is in
* maintenance etc.
*
* @dataProvider getHostDeleteDataValid
* @dataProvider getHostDeleteDataInvalid
*/
public function testHost_Delete($hostids, $expected_error) {
// Replace ID placeholders with real IDs.
foreach ($hostids as &$hostid) {
$hostid = self::$data['hostids'][$hostid];
}
unset($hostid);
$sql_hosts = 'SELECT NULL FROM hosts';
$old_hash_hosts = CDBHelper::getHash($sql_hosts);
$this->call('host.delete', $hostids, $expected_error);
if ($expected_error === null) {
$this->assertNotSame($old_hash_hosts, CDBHelper::getHash($sql_hosts));
$this->assertEquals(0, CDBHelper::getCount(
'SELECT h.hostid FROM hosts h WHERE '.dbConditionId('h.hostid', $hostids)
));
// host.delete checks if given "hostid" exists, so they need to be removed from self::$data['hostids']
foreach ($hostids as $hostid) {
$key = array_search($hostid, self::$data['hostids']);
if ($key !== false) {
unset(self::$data['hostids'][$key]);
}
}
}
else {
$this->assertSame($old_hash_hosts, CDBHelper::getHash($sql_hosts));
}
}
/**
* Data provider for host.create. Array contains invalid hosts with mandatory fields, invalid field types etc.
*
* @return array
*/
public static function getHostCreateDataCommonInvalid() {
return [
'Test host.create common error - empty request' => [
'request' => [],
'expected_error' => 'Empty input parameter.'
],
'Test host.create common error - wrong fields' => [
'request' => [
'groups' => []
],
'expected_error' => 'Wrong fields for host "".'
],
'Test host.create common error - missing "groups"' => [
'request' => [
'host' => 'API test hosts create fail'
],
'expected_error' => 'Host "API test hosts create fail" cannot be without host group.'
],
'Test host.create common error - empty group' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => []
],
'expected_error' => 'Host "API test hosts create fail" cannot be without host group.'
],
'Test host.create common error - empty host name' => [
'request' => [
'host' => '',
'groups' => [
[
'groupid' => 'ID'
]
]
],
'expected_error' => 'Incorrect characters used for host name "".'
],
'Test host.create common error - invalid host name' => [
'request' => [
'host' => '&^@%#&^',
'groups' => [
[
'groupid' => 'ID'
]
]
],
'expected_error' => 'Incorrect characters used for host name "&^@%#&^".'
],
'Test host.create common error - missing "groupid"' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[]
]
],
'expected_error' => 'Incorrect value for field "groups": the parameter "groupid" is missing.'
],
'Test host.create common error - invalid group' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[
'groupid' => '01'
]
]
],
'expected_error' => 'No permissions to referred object or it does not exist!'
],
'Test host.create common error - host already exists' => [
'request' => [
'host' => 'Zabbix server',
'groups' => [
[
'groupid' => 'ID'
]
]
],
'expected_error' => 'Host with the same name "Zabbix server" already exists.'
]
];
}
/**
* Data provider for host.create. Array contains invalid hosts with various optional fields.
*
* @return array
*/
public static function getHostCreateDataInvalid() {
return [
// Test create interfaces.
'Test host.create interfaces (empty)' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[
'groupid' => 'ID'
]
],
'interfaces' => ''
],
'expected_error' => 'Incorrect arguments passed to function.'
],
'Test host.create interfaces (string)' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[
'groupid' => 'ID'
]
],
'interfaces' => 'string'
],
'expected_error' => 'Incorrect arguments passed to function.'
],
'Test host.create interfaces (integer)' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[
'groupid' => 'ID'
]
],
'interfaces' => '10'
],
'expected_error' => 'Incorrect arguments passed to function.'
],
// Test create macros.
'Test host.create - macros (automatic)' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[
'groupid' => 'ID'
]
],
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_NEW_FAIL_ONE}',
'value' => 'manual_macro_text_value_new_fail_one',
'description' => 'manual_macro_text_description_new_fail_one',
'type' => ZBX_MACRO_TYPE_TEXT,
'automatic' => ZBX_USERMACRO_AUTOMATIC
]
]
],
'expected_error' => 'Invalid parameter "/1/macros/1": unexpected parameter "automatic".'
],
'Test host.create - macros (manual)' => [
'request' => [
'host' => 'API test hosts create fail',
'groups' => [
[
'groupid' => 'ID'
]
],
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_NEW_FAIL_TWO}',
'value' => 'manual_macro_text_value_new_fail_two',
'description' => 'manual_macro_text_description_new_fail_two',
'type' => ZBX_MACRO_TYPE_TEXT,
'automatic' => ZBX_USERMACRO_MANUAL
]
]
],
'expected_error' => 'Invalid parameter "/1/macros/1": unexpected parameter "automatic".'
]
];
}
/**
* Data provider for host.create. Array contains valid hosts.
*
* @return array
*/
public static function getHostCreateDataValid() {
return [
'Test host.create minimal' => [
'request' => [
'host' => 'API test hosts create success minimal',
'groups' => [
[
'groupid' => 'ID'
]
]
],
'expected_error' => null
],
'Test host.create empty interfaces' => [
'request' => [
'host' => 'API test hosts create success empty interfaces',
'groups' => [
[
'groupid' => 'ID'
]
],
'interfaces' => []
],
'expected_error' => null
]
];
}
/**
* Test host.create with common errors like missing fields, optional invalid fields and valid fields.
*
* @dataProvider getHostCreateDataCommonInvalid
* @dataProvider getHostCreateDataInvalid
* @dataProvider getHostCreateDataValid
*/
public function testHost_Create($hosts, $expected_error) {
// Accept single and multiple hosts.
if (!array_key_exists(0, $hosts)) {
$hosts = zbx_toArray($hosts);
}
// Replace ID placeholders with real IDs.
foreach ($hosts as &$host) {
// Some tests that should fail may not have the required fields or they may be damaged.
if (array_key_exists('groups', $host) && $host['groups']) {
foreach ($host['groups'] as &$group) {
if (array_key_exists('groupid', $group) && $group['groupid'] === 'ID') {
$group['groupid'] = self::$data['hostgroupid'];
}
}
unset($group);
}
}
unset($host);
$sql_hosts = 'SELECT NULL FROM hosts';
$old_hash_hosts = CDBHelper::getHash($sql_hosts);
$result = $this->call('host.create', $hosts, $expected_error);
if ($expected_error === null) {
$this->assertNotSame($old_hash_hosts, CDBHelper::getHash($sql_hosts));
$this->assertEquals(count($result['result']['hostids']), count($hosts));
// Add host IDs to create array, so they can be deleted after tests are complete.
self::$data['created'] = array_merge(self::$data['created'], $result['result']['hostids']);
}
else {
$this->assertSame($old_hash_hosts, CDBHelper::getHash($sql_hosts));
}
}
/**
* Data provider for host.get. Array contains valid host with tags.
*
* @return array
*/
public static function getHostGetTagsDataValid() {
return [
'Test host.get tag as extend' => [
'params' => [
'hostids' => 'tags',
'selectTags' => API_OUTPUT_EXTEND
],
'expected_result' => [
'tags' => [
[
'tag' => 'b',
'value' => 'b',
'automatic' => '0'
]
]
]
],
'Test host.get tag excluding value' => [
'params' => [
'hostids' => 'tags',
'selectTags' => [
'tag'
]
],
'expected_result' => [
'tags' => [
[
'tag' => 'b'
]
]
]
],
'Test host.get tag excluding name' => [
'params' => [
'hostids' => 'tags',
'selectTags' => [
'value'
]
],
'expected_result' => [
'tags' => [
[
'value' => 'b'
]
]
]
]
];
}
/**
* Test host.get with "selectTags" option.
*
* @dataProvider getHostGetTagsDataValid
*/
public function testHost_SelectTags($params, $expected_result) {
// Replace ID placeholders with real IDs. Host IDs can also be one host ID as string.
$params['hostids'] = self::$data['hostids']['tags'];
$result = $this->call('host.get', $params);
foreach ($result['result'] as $host) {
foreach ($expected_result as $field => $expected_value){
$this->assertArrayHasKey($field, $host, 'Field should be present.');
$this->assertEquals($host[$field], $expected_value, 'Returned value should match.');
}
}
}
/**
* Data provider for host.get to check field presence and exclusion.
*
* @return array
*/
public static function getHostGetFieldPresenceData() {
return [
'Check if {"output": "extend"} includes "inventory_mode" and excludes write-only properties' => [
'request' => [
'output' => API_OUTPUT_EXTEND,
'hostids' => 'write_only'
],
'expected_result' => [
'hostid' => '99013',
'inventory_mode' => '-1',
// Write-only properties.
'tls_psk_identity' => null,
'tls_psk' => null,
'name_upper' => null
]
],
'Check it is not possible to select write-only fields' => [
'request' => [
'output' => ['host', 'tls_psk', 'tls_psk_identity', 'name_upper'],
'hostids' => 'write_only'
],
'expected_result' => [
'hostid' => 'write_only',
// Sample of unspecified property.
'inventory_mode' => null,
// Write-only properties.
'tls_psk_identity' => null,
'tls_psk' => null,
'name_upper' => null
]
],
'Check direct request of inventory_mode and other properties' => [
'request' => [
'output' => ['inventory_mode', 'tls_connect', 'name', 'name_upper'],
'hostids' => 'write_only'
],
'expected_result' => [
'hostid' => 'write_only',
'inventory_mode' => '-1',
// Samples of other specified properties.
'tls_connect' => '1',
'name' => 'API test hosts - write-only fields',
'name_upper' => null
]
]
];
}
/**
* Test host.get and field presence and exclusion.
*
* @dataProvider getHostGetFieldPresenceData
*/
public function testHost_GetFieldPresenceAndExclusion($request, $expected_result) {
// Replace ID placeholders with real IDs. Host IDs can also be one host ID as string.
$request['hostids'] = self::$data['hostids']['write_only'];
$expected_result['hostid'] = self::$data['hostids']['write_only'];
$result = $this->call('host.get', $request);
foreach ($result['result'] as $host) {
foreach ($expected_result as $key => $value) {
if ($value !== null) {
$this->assertArrayHasKey($key, $host, 'Key '.$key.' should be present in host output.');
$this->assertEquals($value, $host[$key], 'Value should match.');
}
else {
$this->assertArrayNotHasKey($key, $host, 'Key '.$key.' should NOT be present in host output');
}
}
}
}
/**
* Data provider for host.update to check how templates are replaced.
*
* @return array
*/
public static function getHostUpdateTemplatesData() {
return [
'Test host.update - host has no templates' => [
'request' => [
'hostid' => 'discovered_no_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Replace the templates.
'Test host.update - host has manual templates' => [
'request' => [
'hostid' => 'discovered_manual_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Try to replace with manual templates, but it's not possible. They will remain auto.
'Test host.update - host has auto templates (same)' => [
'request' => [
'hostid' => 'discovered_auto_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
// Try to replace the templates, but only manual templates are added, since original ones are auto.
'Test host.update - host has auto templates (different)' => [
'request' => [
'hostid' => 'discovered_auto_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Try to replace the templates, but only manual templates are replaced. Auto templates remain.
'Test host.update - host has manual and auto templates' => [
'request' => [
'hostid' => 'discovered_auto_and_manual_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_b_tpl'
],
[
'templateid' => 'api_test_hosts_d_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_d_tpl',
'host' => 'api_test_hosts_d_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
/*
* Possibly incorrect behavior in API in case templates that are added are same as the ones that should be
* cleared. Currently templates that are added take priority. They do not cancel each other out.
*/
'Test host.update with clear - host has no templates (same)' => [
'request' => [
'hostid' => 'discovered_no_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.update with clear - host has no templates (different)' => [
'request' => [
'hostid' => 'discovered_no_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.update with clear only - host has no templates' => [
'request' => [
'hostid' => 'discovered_no_templates',
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => []
]
],
'Test host.update with clear - host has manual templates (same)' => [
'request' => [
'hostid' => 'discovered_manual_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.update with clear non-existing - host has manual templates' => [
'request' => [
'hostid' => 'discovered_manual_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_a_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_c_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.update with clear existing - host has manual templates' => [
'request' => [
'hostid' => 'discovered_manual_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.update with clear non-existing - host has auto templates' => [
'request' => [
'hostid' => 'discovered_auto_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
'Test host.update with clear existing - host has auto templates' => [
'request' => [
'hostid' => 'discovered_auto_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_f_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
'Test host.update with clear - host has auto templates' => [
'request' => [
'hostid' => 'discovered_auto_templates',
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
],
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
]
];
}
/**
* Test host.update by adding new templates and replacing templates.
*
* @dataProvider getHostUpdateTemplatesData
*/
public function testHost_UpdateTemplates($request, $expected_result) {
// Replace ID placeholders with real IDs.
$request['hostid'] = self::$data['hostids'][$request['hostid']];
foreach (['templates', 'templates_clear'] as $field) {
if (array_key_exists($field, $request)) {
foreach ($request[$field] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
}
}
foreach ($expected_result['parentTemplates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
$hosts_old = $this->backupTemplates([$request['hostid']]);
// Update templates on hosts.
$hosts_upd = $this->call('host.update', $request);
$this->assertArrayHasKey('hostids', $hosts_upd['result']);
// Check data after update.
$hosts = $this->call('host.get', [
'output' => ['hostid', 'host'],
'selectParentTemplates' => ['templateid', 'host', 'link_type'],
'hostids' => $request['hostid']
]);
$host = reset($hosts['result']);
$this->assertSame($expected_result['parentTemplates'], $host['parentTemplates'],
'host.update with templates failed for host "'.$host['host'].'".'
);
$this->restoreTemplates($hosts_old);
}
/**
* Data provider for host.massupdate to check how templates are replaced.
*
* @return array
*/
public static function getHostMassUpdateTemplatesData() {
return [
'Test host.massupdate - host has no templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_no_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Replace the templates.
'Test host.massupdate - host has manual templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Try to replace with manual templates, but it's not possible. They will remain auto.
'Test host.massupdate - host has auto templates (same)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
// Try to replace the templates, but only manual templates are added, since original ones are auto.
'Test host.massupdate - host has auto templates (different)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Try to replace the templates, but only manual templates are replaced. Auto templates remain.
'Test host.massupdate - host has manual and auto templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_and_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_b_tpl'
],
[
'templateid' => 'api_test_hosts_d_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_d_tpl',
'host' => 'api_test_hosts_d_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
/*
* Possibly incorrect behavior in API in case templates that are added are same as the ones that should be
* cleared. Currently templates that are added take priority. They do not cancel each other out.
*/
'Test host.massupdate with clear - host has no templates (same)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_no_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massupdate with clear - host has no templates (different)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_no_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massupdate with clear only - host has no templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_no_templates'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => []
]
],
'Test host.massupdate with clear - host has manual templates (same)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massupdate with clear non-existing - host has manual templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_a_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_c_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massupdate with clear existing - host has manual templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massupdate with clear non-existing - host has auto templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
'Test host.massupdate with clear existing - host has auto templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
] ,
'templates' => [
[
'templateid' => 'api_test_hosts_c_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_f_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
'Test host.massupdate with clear - host has auto templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
],
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massupdate with clear - host has manual and auto templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_and_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_e_tpl'
],
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_b_tpl'
]
],
'templates_clear' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
],
[
'templateid' => 'api_test_hosts_d_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
]
];
}
/**
* Test host.massupdate by adding new templates and replacing templates.
*
* @dataProvider getHostMassUpdateTemplatesData
*/
public function testHost_MassUpdateTemplates($request, $expected_result) {
// Replace ID placeholders with real IDs.
$hostids = [];
foreach ($request['hosts'] as &$host) {
$host['hostid'] = self::$data['hostids'][$host['hostid']];
$hostids[] = $host['hostid'];
}
unset($host);
foreach (['templates', 'templates_clear'] as $field) {
if (array_key_exists($field, $request)) {
foreach ($request[$field] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
}
}
foreach ($expected_result['parentTemplates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
$hosts_old = $this->backupTemplates($hostids);
// Update templates on hosts.
$hosts_upd = $this->call('host.massupdate', $request);
$this->assertArrayHasKey('hostids', $hosts_upd['result']);
// Check data after update.
$hosts = $this->call('host.get', [
'output' => ['hostid', 'host'],
'selectParentTemplates' => ['templateid', 'host', 'link_type'],
'hostids' => $hostids
]);
$hosts = $hosts['result'];
foreach ($hosts as $host) {
$this->assertSame($expected_result['parentTemplates'], $host['parentTemplates'],
'host.massupdate with templates failed for host "'.$host['host'].'".'
);
}
$this->restoreTemplates($hosts_old);
}
/**
* Data provider for host.massadd to check how templates are added.
*
* @return array
*/
public static function getHostMassAddTemplatesData() {
return [
'Test host.massadd - host has no templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_no_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Add templates to existing manual templates.
'Test host.massadd - host has manual templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Add same templates to existing auto templates. Not possible, since those templates are already auto.
'Test host.massadd - host has auto templates (same)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_f_tpl'
],
[
'templateid' => 'api_test_hosts_c_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
// Add different templates to existing auto templates.
'Test host.massadd - host has auto templates (different)' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_a_tpl'
],
[
'templateid' => 'api_test_hosts_e_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
// Add templates to existing auto and manual templates.
'Test host.massadd - host has manual and auto templates' => [
'request' => [
'hosts' => [
[
'hostid' => 'discovered_auto_and_manual_templates'
]
],
'templates' => [
[
'templateid' => 'api_test_hosts_b_tpl'
],
[
'templateid' => 'api_test_hosts_d_tpl'
]
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_d_tpl',
'host' => 'api_test_hosts_d_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
]
];
}
/**
* Test host.massadd by adding new templates to existing manual and auto templates.
*
* @dataProvider getHostMassAddTemplatesData
*/
public function testHost_MassAddTemplates($request, $expected_result) {
// Replace ID placeholders with real IDs.
$hostids = [];
foreach ($request['hosts'] as &$host) {
$host['hostid'] = self::$data['hostids'][$host['hostid']];
$hostids[] = $host['hostid'];
}
unset($host);
foreach ($request['templates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
foreach ($expected_result['parentTemplates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
$hosts_old = $this->backupTemplates($hostids);
// Add templates on hosts.
$hosts_upd = $this->call('host.massadd', $request);
$this->assertArrayHasKey('hostids', $hosts_upd['result']);
// Check data after update.
$hosts = $this->call('host.get', [
'output' => ['hostid', 'host'],
'selectParentTemplates' => ['templateid', 'host', 'link_type'],
'hostids' => $hostids
]);
$hosts = $hosts['result'];
foreach ($hosts as $host) {
$this->assertSame($expected_result['parentTemplates'], $host['parentTemplates'],
'host.massadd with templates failed for host "'.$host['host'].'".'
);
}
$this->restoreTemplates($hosts_old);
}
/**
* Data provider for host.massremove to check how templates are removed.
*
* @return array
*/
public static function getHostMassRemoveTemplatesData() {
return [
'Test host.massremove - host has no templates' => [
'request' => [
'hostids' => [
'discovered_no_templates'
],
'templateids' => [
'api_test_hosts_f_tpl',
'api_test_hosts_c_tpl'
]
],
'expected_result' => [
'parentTemplates' => []
]
],
'Test host.massremove - host has manual templates' => [
'request' => [
'hostids' => [
'discovered_manual_templates'
],
'templateids' => [
'api_test_hosts_a_tpl'
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
],
'Test host.massremove - host has auto templates' => [
'request' => [
'hostids' => [
'discovered_auto_templates'
],
'templateids' => [
'api_test_hosts_f_tpl'
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
],
'Test host.massremove - host has manual and auto templates' => [
'request' => [
'hostids' => [
'discovered_auto_and_manual_templates'
],
'templateids' => [
'api_test_hosts_f_tpl',
'api_test_hosts_a_tpl'
]
],
'expected_result' => [
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
]
];
}
/**
* Test host.massremove to remove the templates from hosts.
*
* @dataProvider getHostMassRemoveTemplatesData
*/
public function testHost_MassRemoveTemplates($request, $expected_result) {
// Replace ID placeholders with real IDs.
foreach ($request['hostids'] as &$hostid) {
$hostid = self::$data['hostids'][$hostid];
}
unset($hostid);
foreach ($request['templateids'] as &$templateid) {
$templateid = self::$data['templateids'][$templateid];
}
unset($templateid);
foreach ($expected_result['parentTemplates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
$hosts_old = $this->backupTemplates($request['hostids']);
// Add templates on hosts.
$hosts_upd = $this->call('host.massremove', $request);
$this->assertArrayHasKey('hostids', $hosts_upd['result']);
// Check data after update.
$hosts = $this->call('host.get', [
'output' => ['hostid', 'host'],
'selectParentTemplates' => ['templateid', 'host', 'link_type'],
'hostids' => $request['hostids']
]);
$hosts = $hosts['result'];
foreach ($hosts as $host) {
$this->assertSame($expected_result['parentTemplates'], $host['parentTemplates'],
'host.massremove with templates failed for host "'.$host['host'].'".'
);
}
$this->restoreTemplates($hosts_old);
}
/**
* Data provider for host.update to check inheritance.
*
* @return array
*/
public static function getHostInheritanceData() {
return [
'Test host.update inheritance - host has no templates' => [
'request' => [
'hostid' => 'discovered_no_templates',
// Add template and then check if results match.
'templates' => [
[
'templateid' => 'api_test_hosts_tpl_with_item'
]
]
],
'expected_results' => [
'update' => [
'item_keys' => [
'api_test_hosts_tpl_item'
]
],
'unlink' => [
'item_keys' => [
'api_test_hosts_tpl_item'
]
],
'clear' => [
'item_keys' => []
]
]
],
'Test host.update inheritance - host has auto templates' => [
'request' => [
'hostid' => 'discovered_clear',
// This does not matter because auto templates cannot be replaced.
'templates' => []
],
'expected_results' => [
'update' => [
'item_keys' => [
'api_test_hosts_tpl_item'
]
],
'unlink' => [
'item_keys' => [
'api_test_hosts_tpl_item'
]
],
'clear' => [
'item_keys' => [
'api_test_hosts_tpl_item'
]
]
]
]
];
}
/**
* Test host.update and check if item(s) exist on host after template has been added. Test unlink and check if items
* remain on host. Test clear and check if items are removed from host as well.
*
* @dataProvider getHostInheritanceData
*/
public function testHost_Inheritance($host, $expected_results) {
// Replace ID placeholder with real ID.
$host['hostid'] = self::$data['hostids'][$host['hostid']];
foreach ($host['templates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
$hosts_old = $this->backupTemplates([$host['hostid']]);
// Add/replace templates on host and check if items are inherited on host.
$this->call('host.update', $host);
$item_keys = $this->getItemKeysOnHost($host['hostid']);
$this->assertSame($expected_results['update']['item_keys'], $item_keys,
'Updating templates failed: mismatching results on host with ID "'.$host['hostid'].'".'
);
// Then unlink the template from host and check if item still exists on host.
$this->restoreTemplates($hosts_old);
$item_keys = $this->getItemKeysOnHost($host['hostid']);
$this->assertSame($expected_results['unlink']['item_keys'], $item_keys,
'Unlinking templates failed: mismatching results on host with ID "'.$host['hostid'].'".'
);
// Add/replace templates on host again to make the link and check if items are still on host.
$this->call('host.update', $host);
$item_keys = $this->getItemKeysOnHost($host['hostid']);
$this->assertSame($expected_results['update']['item_keys'], $item_keys,
'Re-updating templates failed: mismatching results on host with ID "'.$host['hostid'].'".'
);
// Then clear the template from host and check if items no longer exist on host.
$hosts = $this->call('host.get', [
'output' => ['hostid', 'host'],
'selectParentTemplates' => ['templateid'],
'hostids' => [$host['hostid']]
]);
$this->restoreTemplates($hosts['result'], true);
$item_keys = $this->getItemKeysOnHost($host['hostid']);
$this->assertSame($expected_results['clear']['item_keys'], $item_keys,
'Clearing templates failed: mismatching results on host with ID "'.$host['hostid'].'".'
);
}
/**
* Data provider for host.get to check templates.
*
* @return array
*/
public static function getHostGetTemplatesData() {
return [
'Test host.get - host has no templates' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_no_templates'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
]
],
'expected_results' => [
[
'hostid' => 'discovered_no_templates',
'parentTemplates' => []
]
]
],
'Test host.get - host has manual templates' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_manual_templates'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
]
],
'expected_results' => [
[
'hostid' => 'discovered_manual_templates',
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
]
],
'Test host.get - host has auto templates' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_auto_templates'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
]
],
'expected_results' => [
[
'hostid' => 'discovered_auto_templates',
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
]
],
'Test host.get - host has auto and manual templates' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_auto_and_manual_templates'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
]
],
'expected_results' => [
[
'hostid' => 'discovered_auto_and_manual_templates',
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_MANUAL
]
]
]
]
],
'Test host.get with limits null' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_limit_selects'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
],
'limitSelects' => null
],
'expected_results' => [
[
'hostid' => 'discovered_limit_selects',
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_d_tpl',
'host' => 'api_test_hosts_d_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
]
],
'Test host.get with limits zero' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_limit_selects'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
],
'limitSelects' => '0'
],
'expected_results' => [
[
'hostid' => 'discovered_limit_selects',
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_d_tpl',
'host' => 'api_test_hosts_d_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_e_tpl',
'host' => 'api_test_hosts_e_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_f_tpl',
'host' => 'api_test_hosts_f_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
]
],
'Test host.get with limits three' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_limit_selects'
],
'selectParentTemplates' => [
'templateid', 'host', 'link_type'
],
'limitSelects' => '3'
],
'expected_results' => [
[
'hostid' => 'discovered_limit_selects',
'parentTemplates' => [
[
'templateid' => 'api_test_hosts_a_tpl',
'host' => 'api_test_hosts_a_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_b_tpl',
'host' => 'api_test_hosts_b_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
],
[
'templateid' => 'api_test_hosts_c_tpl',
'host' => 'api_test_hosts_c_tpl',
'link_type' => (string) TEMPLATE_LINK_LLD
]
]
]
]
]
];
}
/**
* Test host.get to check if hosts have the necessary templates and order.
*
* @dataProvider getHostGetTemplatesData
*/
public function testHost_GetTemplates($request, $expected_results) {
// Replace ID placeholder with real ID.
foreach ($request['hostids'] as &$hostid) {
$hostid = self::$data['hostids'][$hostid];
}
unset($hostid);
foreach ($expected_results as &$result) {
$result['hostid'] = self::$data['hostids'][$result['hostid']];
foreach ($result['parentTemplates'] as &$template) {
$template['templateid'] = self::$data['templateids'][$template['templateid']];
}
unset($template);
}
unset($result);
$host = $this->call('host.get', $request);
$this->assertSame($expected_results, $host['result']);
}
/**
* Data provider for host.get to check macros.
*
* @return array
*/
public static function getHostGetMacrosData() {
return [
'Test host.get - host has no macros' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_no_macros'
],
'selectMacros' => [
'macro', 'value', 'description', 'type', 'automatic'
]
],
'expected_results' => [
[
'hostid' => 'discovered_no_macros',
'macros' => []
]
]
],
'Test host.get - host has manual macros' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_manual_macros'
],
'selectMacros' => [
'macro', 'value', 'description', 'type', 'automatic'
]
],
'expected_results' => [
[
'hostid' => 'discovered_manual_macros',
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_C}',
'value' => 'manual_macro_text_value_c',
'description' => 'manual_macro_text_description_c',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_SECRET_C}',
'description' => 'manual_macro_secret_description_c',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_VAULT_C}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_c',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
]
]
],
'Test host.get - host has auto macros' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_auto_macros'
],
'selectMacros' => [
'macro', 'value', 'description', 'type', 'automatic'
]
],
'expected_results' => [
[
'hostid' => 'discovered_auto_macros',
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_A}',
'value' => 'discovered_macro_text_value_a',
'description' => 'discovered_macro_text_description_a',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_A}',
'description' => 'discovered_macro_secret_description_a',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_A}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_a',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
]
]
]
]
],
'Test host.get - host has auto and manual macros' => [
'request' => [
'output' => ['hostid'],
'hostids' => [
'discovered_auto_and_manual_macros'
],
'selectMacros' => [
'macro', 'value', 'description', 'type', 'automatic'
]
],
'expected_results' => [
[
'hostid' => 'discovered_auto_and_manual_macros',
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_B}',
'value' => 'discovered_macro_text_value_b',
'description' => 'discovered_macro_text_description_b',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_B}',
'description' => 'discovered_macro_secret_description_b',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_B}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_b',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$MANUAL_MACRO_TEXT_D}',
'value' => 'manual_macro_text_value_d',
'description' => 'manual_macro_text_description_d',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_SECRET_D}',
'description' => 'manual_macro_secret_description_d',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_VAULT_D}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_d',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
]
]
]
];
}
/**
* Test host.get to check if hosts have various macros and their properties.
*
* @dataProvider getHostGetMacrosData
*/
public function testHost_GetMacros($request, $expected_results) {
// Replace ID placeholder with real ID.
foreach ($request['hostids'] as &$hostid) {
$hostid = self::$data['hostids'][$hostid];
}
unset($hostid);
foreach ($expected_results as &$result) {
$result['hostid'] = self::$data['hostids'][$result['hostid']];
}
unset($result);
$host = $this->call('host.get', $request);
// Ignore the order due to MySQL returning macros in different order.
$this->assertEqualsCanonicalizing($expected_results, $host['result']);
}
/**
* Data provider for host.update to check how macros are replaced and converted from automatic to manual.
*
* @return array
*/
public static function getHostUpdateMacrosDataValid() {
return [
// Add manual macros to discovered host.
'Test host.update - host has no macros' => [
'request' => [
'hostid' => 'discovered_no_macros',
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_NEW}',
'value' => 'manual_macro_text_value_new',
'description' => 'manual_macro_text_description_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT
],
[
'macro' => '{$MANUAL_MACRO_SECRET_NEW}',
'value' => 'manual_macro_secret_value_new',
'description' => 'manual_macro_secret_description_new',
'type' => (string) ZBX_MACRO_TYPE_SECRET
],
[
'macro' => '{$MANUAL_MACRO_VAULT_NEW}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_new',
'type' => (string) ZBX_MACRO_TYPE_VAULT
]
]
],
'expected_result' => [
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_NEW}',
'value' => 'manual_macro_text_value_new',
'description' => 'manual_macro_text_description_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_SECRET_NEW}',
'value' => 'manual_macro_secret_value_new',
'description' => 'manual_macro_secret_description_new',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_VAULT_NEW}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_new',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
],
'expected_error' => null
],
// Replace macros leaving some old, changing and adding new.
'Test host.update - host has manual macros' => [
'request' => [
'hostid' => 'discovered_manual_macros',
'macros' => [
// Leave macro as is.
[
'hostmacroid' => 'manual_macro_text_c'
],
// Change macro name {$MANUAL_MACRO_SECRET_C}.
[
'hostmacroid' => 'manual_macro_secret_c',
'macro' => '{$MANUAL_MACRO_SECRET_C_CHANGED_NAME}'
],
// Replace macro {$MANUAL_MACRO_VAULT_C} with this one.
[
'macro' => '{$MANUAL_MACRO_VAULT_C_NEW}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_c_new',
'type' => (string) ZBX_MACRO_TYPE_VAULT
]
]
],
'expected_result' => [
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_C}',
'value' => 'manual_macro_text_value_c',
'description' => 'manual_macro_text_description_c',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_SECRET_C_CHANGED_NAME}',
'value' => 'manual_macro_secret_value_c',
'description' => 'manual_macro_secret_description_c',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_VAULT_C_NEW}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_c_new',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
],
'expected_error' => null
],
// Don't change host macros, leave them automatic.
'Test host.update - host has auto macros (same)' => [
'request' => [
'hostid' => 'discovered_auto_macros',
'macros' => [
[
'hostmacroid' => 'discovered_macro_text_a'
],
[
'hostmacroid' => 'discovered_macro_secret_a'
],
[
'hostmacroid' => 'discovered_macro_vault_a'
]
]
],
'expected_result' => [
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_A}',
'value' => 'discovered_macro_text_value_a',
'description' => 'discovered_macro_text_description_a',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_A}',
'value' => 'discovered_macro_secret_value_a',
'description' => 'discovered_macro_secret_description_a',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_A}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_a',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
]
]
],
'expected_error' => null
],
// Change host macros from automatic to manual.
'Test host.update - host has auto macros (convert)' => [
'request' => [
'hostid' => 'discovered_auto_macros',
'macros' => [
// Just convert the macro to manual.
[
'hostmacroid' => 'discovered_macro_text_a',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
// Convert macro to manual and change value and description.
[
'hostmacroid' => 'discovered_macro_secret_a',
'value' => 'discovered_macro_secret_value_a_changed',
'description' => 'discovered_macro_secret_description_a_changed',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
// Convert macro to manual and change macro name.
[
'hostmacroid' => 'discovered_macro_vault_a',
'macro' => '{$DISCOVERED_MACRO_VAULT_A_CHANGED}',
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
],
'expected_result' => [
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_A}',
'value' => 'discovered_macro_text_value_a',
'description' => 'discovered_macro_text_description_a',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_A}',
'value' => 'discovered_macro_secret_value_a_changed',
'description' => 'discovered_macro_secret_description_a_changed',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_A_CHANGED}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_a',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
],
'expected_error' => null
],
// Convert automatic macros to manual, leave some original, add new.
'Test host.update - host has auto and manual macros' => [
'request' => [
'hostid' => 'discovered_auto_and_manual_macros',
'macros' => [
[
// Converts automatic macro to manual with no changes.
'hostmacroid' => 'discovered_macro_text_b'
],
[
// Converts automatic macro to manual with no changes (value is the same).
'hostmacroid' => 'discovered_macro_secret_b',
'value' => 'discovered_macro_secret_value_b',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
// Converts automatic macro to manual with new name and description.
'hostmacroid' => 'discovered_macro_vault_b',
'macro' => '{$DISCOVERED_MACRO_VAULT_B_CHANGED}',
'description' => 'discovered_macro_vault_description_b_changed',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
// No conversion will happen, because it's already manual macro.
'hostmacroid' => 'manual_macro_text_d',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
// No conversion will happen, because it's already manual macro.
'hostmacroid' => 'manual_macro_secret_d',
'value' => 'manual_macro_secret_value_d',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
// Change macro name and description. No conversion will happen. Already manual macro.
'hostmacroid' => 'manual_macro_vault_d',
'macro' => '{$MANUAL_MACRO_VAULT_D_CHANGED}',
'description' => 'manual_macro_vault_description_d_changed',
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
// Add new macro. No conversion possible. Already manual macro.
'macro' => '{$MANUAL_MACRO_TEXT_E_NEW}',
'value' => 'manual_macro_text_value_e_new',
'description' => 'manual_macro_text_description_e_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT
],[
// Add new macro and try to add the property. No conversion possible. Already manual macro.
'macro' => '{$MANUAL_MACRO_TEXT_F_NEW}',
'value' => 'manual_macro_text_value_f_new',
'description' => 'manual_macro_text_description_f_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
],
'expected_result' => [
'macros' => [
[
'macro' => '{$DISCOVERED_MACRO_TEXT_B}',
'value' => 'discovered_macro_text_value_b',
'description' => 'discovered_macro_text_description_b',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
],
[
'macro' => '{$DISCOVERED_MACRO_SECRET_B}',
'value' => 'discovered_macro_secret_value_b',
'description' => 'discovered_macro_secret_description_b',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$DISCOVERED_MACRO_VAULT_B_CHANGED}',
'value' => 'path/to:macro',
'description' => 'discovered_macro_vault_description_b_changed',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_TEXT_D}',
'value' => 'manual_macro_text_value_d',
'description' => 'manual_macro_text_description_d',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_SECRET_D}',
'value' => 'manual_macro_secret_value_d',
'description' => 'manual_macro_secret_description_d',
'type' => (string) ZBX_MACRO_TYPE_SECRET,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_VAULT_D_CHANGED}',
'value' => 'path/to:macro',
'description' => 'manual_macro_vault_description_d_changed',
'type' => (string) ZBX_MACRO_TYPE_VAULT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_TEXT_E_NEW}',
'value' => 'manual_macro_text_value_e_new',
'description' => 'manual_macro_text_description_e_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
],
[
'macro' => '{$MANUAL_MACRO_TEXT_F_NEW}',
'value' => 'manual_macro_text_value_f_new',
'description' => 'manual_macro_text_description_f_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_MANUAL
]
]
],
'expected_error' => null
],
'Test host.update - remove automatic and manual macros' => [
'request' => [
'hostid' => 'discovered_auto_and_manual_macros',
'macros' => []
],
'expected_result' => [
'macros' => []
],
'expected_error' => null
]
];
}
public static function getHostUpdateMacrosDataInvalid() {
return [
'Test host.update - automatic new macro' => [
'request' => [
'hostid' => 'discovered_no_macros',
'macros' => [
[
'macro' => '{$MANUAL_MACRO_TEXT_NEW}',
'value' => 'manual_macro_text_value_new',
'description' => 'manual_macro_text_description_new',
'type' => (string) ZBX_MACRO_TYPE_TEXT,
'automatic' => (string) ZBX_USERMACRO_AUTOMATIC
]
]
],
'expected_result' => [],
'expected_error' => 'Invalid parameter "/1/macros/1/automatic": value must be '.ZBX_USERMACRO_MANUAL.'.'
],
'Test host.update - change existing automatic macro (missing param)' => [
'request' => [
'hostid' => 'discovered_auto_macros',
'macros' => [
[
'hostmacroid' => 'discovered_macro_text_a',
'macro' => '{$DISCOVERED_MACRO_TEXT_A_NEW}'
// Parameter "automatic" is mandatory if something needs to be changed on automatic macro.
]
]
],
'expected_result' => [],
'expected_error' => 'Not allowed to modify automatic user macro "{$DISCOVERED_MACRO_TEXT_A}".'
],
'Test host.update - change existing automatic macro (incorrect value)' => [
'request' => [
'hostid' => 'discovered_auto_macros',
'macros' => [
[
'hostmacroid' => 'discovered_macro_text_a',
'macro' => '{$DISCOVERED_MACRO_TEXT_A_NEW}',
'automatic' => ZBX_USERMACRO_AUTOMATIC
]
]
],
'expected_result' => [],
'expected_error' => 'Invalid parameter "/1/macros/1/automatic": value must be '.ZBX_USERMACRO_MANUAL.'.'
]
];
}
/**
* Test host macro update. Check if 'automatic' property is changed for discovered host macros, macros are properly
* updated to new macros etc.
*
* @dataProvider getHostUpdateMacrosDataValid
* @dataProvider getHostUpdateMacrosDataInvalid
*/
public function testHost_UpdateMacros($request, $expected_result, $expected_error) {
// Replace ID placeholders with real IDs.
$request['hostid'] = self::$data['hostids'][$request['hostid']];
foreach ($request['macros'] as &$macro) {
if (array_key_exists('hostmacroid', $macro)) {
$macro['hostmacroid'] = self::$data['hostmacroids'][$macro['hostmacroid']];
}
}
unset($macro);
$hosts_old = $this->backupMacros([$request['hostid']]);
$hosts_upd = $this->call('host.update', $request, $expected_error);
if ($expected_error === null) {
$this->assertArrayHasKey('hostids', $hosts_upd['result']);
$db_hosts = $this->getMacros([$request['hostid']]);
$db_host = reset($db_hosts);
foreach ($db_host['macros'] as &$macro) {
unset($macro['hostid'], $macro['hostmacroid']);
}
unset($macro);
// Ignore the order in which $db_host macros are returned when comparing.
$this->assertEqualsCanonicalizing($expected_result['macros'], $db_host['macros'],
'host.update with macros failed for host "'.$db_host['host'].'".'
);
$this->restoreMacros($hosts_old);
}
}
/**
* Get a list of items keys on host.
*
* @param string $hostid
*/
private function getItemKeysOnHost(string $hostid) {
$items_new = $this->call('item.get', [
'output' => ['key_'],
'hostids' => $hostid
]);
$items_new = $items_new['result'];
$items = [];
foreach ($items_new as $item) {
$items[] = $item['key_'];
}
return $items;
}
/**
* Get the original host templates.
*
* @param array $hostids
*
* @return array
*/
private function backupTemplates(array $hostids) {
// Get data before update.
$db_hosts = $this->call('host.get', [
'output' => ['hostid', 'host'],
'selectParentTemplates' => ['templateid'],
'hostids' => $hostids
]);
return $db_hosts['result'];
}
/**
* Get current host macros. Due the host.get selectMacros not returning secret values, use regular DB function.
*
* @param array $hostids
*
* @return array
*/
private function getMacros(array $hostids) {
$db_hosts = CDBHelper::getAll(
'SELECT h.host,h.hostid,hm.hostmacroid,hm.macro,hm.value,hm.description,hm.type,hm.automatic'.
' FROM hosts h'.
' LEFT JOIN hostmacro hm ON hm.hostid=h.hostid'.
' WHERE '.dbConditionId('h.hostid', $hostids)
);
$result = [];
foreach ($db_hosts as $db_host) {
if (!array_key_exists($db_host['hostid'], $result)) {
$result[$db_host['hostid']] = [
'hostid' => $db_host['hostid'],
'host' => $db_host['host'],
'macros' => []
];
}
if ($db_host['hostmacroid'] != 0) {
$result[$db_host['hostid']]['macros'][] = [
'hostmacroid' => $db_host['hostmacroid'],
'hostid' => $db_host['hostid'],
'macro' => $db_host['macro'],
'value' => $db_host['value'],
'description' => $db_host['description'],
'type' => $db_host['type'],
'automatic' => $db_host['automatic']
];
}
}
return $result;
}
/**
* Get the original host macros before update.
*
* @param array $hostids
*
* @return array
*/
private function backupMacros(array $hostids) {
return $this->getMacros($hostids);
}
/**
* Revert host templates back to original state before the update to test other cases like massupdate, massremove
* and other methods.
*
* @param array $hosts Array of hosts.
* @param string $hosts[]['hostid'] Host ID that will have the data reverted.
* @param string $hosts[]['host'] Host technical name in case of error.
* @param string $hosts[]['parentTemplates'] Array of host original templates.
*/
private function restoreTemplates(array $hosts, $clear = false) {
foreach ($hosts as $host) {
$name = $host['host'];
if ($clear) {
$host['templates_clear'] = $host['parentTemplates'];
}
else {
$host['templates'] = $host['parentTemplates'];
}
unset($host['host'], $host['parentTemplates']);
$host_upd = $this->call('host.update', $host);
$this->assertArrayHasKey('hostids', $host_upd['result'], 'host.update failed for host "'.$name.'"');
}
}
/**
* Revert host macros back to original state before the update. Instead of using @backup that will backup and
* restore all related tables that could take hours, focus only on host macros.
*
* @param array $hosts Array of hosts and their macros.
* @param string $hosts[<hostid>]['host'] Host technical name in case of error.
* @param string $hosts[<hostid>]['hostid'] Host ID.
* @param string $hosts[<hostid>]['macros'] Array of host original macros.
*/
private function restoreMacros(array $hosts) {
$res = true;
// Records after update has been made. Possibly new macros are stored.
$records_current = CDBHelper::getAll(
'SELECT hm.hostmacroid,hm.hostid,hm.macro,hm.value,hm.description,hm.type,hm.automatic'.
' FROM hostmacro hm'.
' WHERE '.dbConditionId('hm.hostid', array_keys($hosts))
);
// Otherwise if no records exist, they must have been deleted, so in any case old recods need to be restored.
foreach ($hosts as $host) {
$host['macros'] = zbx_toHash($host['macros'], 'hostmacroid');
$records_current = zbx_toHash($records_current, 'hostmacroid');
// Host had macros before. Try to restore them.
if ($host['macros']) {
$ins_macros = [];
$del_macros = [];
$ins_macros = array_diff_key($host['macros'], $records_current);
$del_macros = array_diff_key($records_current, $host['macros']);
if ($ins_macros) {
// Remove old host macro IDs from references that will be re-instertd.
foreach (self::$data['hostmacroids'] as $key => $hostmacroid) {
foreach ($ins_macros as $macro) {
if (bccomp($macro['hostmacroid'], $hostmacroid) == 0) {
unset(self::$data['hostmacroids'][$key]);
}
}
}
foreach ($ins_macros as &$macro) {
unset($macro['hostmacroid']);
}
unset($macro);
// Prepare the new host macro IDs.
$nextid = CDBHelper::getAll(
'SELECT i.nextid'.
' FROM ids i'.
' WHERE i.table_name='.zbx_dbstr('hostmacro').
' AND i.field_name='.zbx_dbstr('hostmacroid').
' FOR UPDATE'
)[0]['nextid'] + 1;
$ids = DB::insertBatch('hostmacro', $ins_macros);
$newids = array_fill($nextid, count($ins_macros), true);
$this->assertEquals(array_keys($newids), array_values($ids),
'host.update with macros failed for host "'.$host['host'].'".'
);
// Again the macro name must match the key.
foreach ($ins_macros as $macro) {
$db_hostmacro = CDBHelper::getRow(
'SELECT hm.hostmacroid'.
' FROM hostmacro hm'.
' WHERE hm.hostid='.zbx_dbstr($macro['hostid']).
' AND hm.macro='.zbx_dbstr($macro['macro'])
);
$key = str_replace('{$', '', $macro['macro']);
$key = str_replace('}', '', $key);
$key = strtolower($key);
}
// Add macros to references just like in data preparation.
self::$data['hostmacroids'][$key] = $db_hostmacro['hostmacroid'];
}
if ($del_macros) {
// Delete the macros that were inserted in host.update method.
$res = $res && DB::delete('hostmacro', [
'hostmacroid' => array_column($del_macros, 'hostmacroid')
]);
// Inserted macros during tests were not added to references. So there is nothing to remove.
}
// Check the old records.
foreach ($host['macros'] as $macro) {
// If old host macro ID still exists, update it.
if (in_array($macro['hostmacroid'], self::$data['hostmacroids'])) {
// Update the macro to previous value regardless of what it was before.
$hostmacroid = $macro['hostmacroid'];
unset($macro['hostmacroid']);
$res = $res && DB::update('hostmacro', [
'values' => $macro,
'where' => [
'hostmacroid' => $hostmacroid
]
]);
}
}
}
// Host did not have macros, but new were added in host.update method. Remove the added ones.
elseif ($records_current) {
$res = $res && DB::delete('hostmacro', [
'hostmacroid' => array_column($records_current, 'hostmacroid')
]);
}
$this->assertSame(true, $res, 'host.update failed for host "'.$host['host'].'"');
}
}
/**
* Delete all created data after test.
*/
public static function clearData() {
// Delete maintenances.
CDataHelper::call('maintenance.delete', self::$data['maintenanceids']);
// Delete hosts and templates.
$hostids = array_values(self::$data['hostids']);
$hostids = array_merge($hostids, self::$data['created']);
CDataHelper::call('host.delete', $hostids);
CDataHelper::call('template.delete', array_values(self::$data['templateids']));
// Delete groups.
CDataHelper::call('hostgroup.delete', [self::$data['hostgroupid']]);
CDataHelper::call('templategroup.delete', [self::$data['templategroupid']]);
}
}