diff options
author | Andris Zeila <andris.zeila@zabbix.com> | 2022-09-19 16:31:15 +0300 |
---|---|---|
committer | Andris Zeila <andris.zeila@zabbix.com> | 2022-09-19 16:31:15 +0300 |
commit | 6fed6ddf908c0b0b7197a223bc1d4215d42694a2 (patch) | |
tree | 87e72ce9a349294ad527fb817fc58c0c977c572a /ui | |
parent | 9a6a0d184be443a538bdbe706a0ae76a91008e4c (diff) | |
parent | 5b9ab82fe550a7c87763703ab4a7320c69aaf9bb (diff) |
.......... [ZBXNEXT-3290] merged branch 'master' of ssh://git.zabbix.com:7999/zbx/zabbix into feature/ZBXNEXT-3290-6.3
Diffstat (limited to 'ui')
34 files changed, 2402 insertions, 817 deletions
diff --git a/ui/app/controllers/CControllerPopupMassupdateHost.php b/ui/app/controllers/CControllerPopupMassupdateHost.php index 5345e1e8b18..fe02dfd79d3 100644 --- a/ui/app/controllers/CControllerPopupMassupdateHost.php +++ b/ui/app/controllers/CControllerPopupMassupdateHost.php @@ -540,7 +540,7 @@ class CControllerPopupMassupdateHost extends CControllerPopupMassupdateAbstract ]; $data['proxies'] = API::Proxy()->get([ - 'output' => ['hostid', 'host'], + 'output' => ['proxyid', 'host'], 'filter' => [ 'status' => [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE] ], diff --git a/ui/app/controllers/CControllerProxyList.php b/ui/app/controllers/CControllerProxyList.php index e4c3aa86b52..ba906f1b551 100644 --- a/ui/app/controllers/CControllerProxyList.php +++ b/ui/app/controllers/CControllerProxyList.php @@ -27,13 +27,14 @@ class CControllerProxyList extends CController { protected function checkInput(): bool { $fields = [ - 'sort' => 'in host', - 'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP, 'uncheck' => 'in 1', 'filter_set' => 'in 1', 'filter_rst' => 'in 1', 'filter_name' => 'string', - 'filter_status' => 'in -1,'.HOST_STATUS_PROXY_ACTIVE.','.HOST_STATUS_PROXY_PASSIVE + 'sort' => 'in '.implode(',', ['host', 'status', 'tls_accept', 'version', 'lastaccess']), + 'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP, + 'filter_status' => 'in '.implode(',', ['-1', HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE]), + 'filter_version' => 'in '.implode(',', ['-1', ZBX_PROXY_VERSION_CURRENT, ZBX_PROXY_VERSION_ALL_OUTDATED]) ]; $ret = $this->validateInput($fields); @@ -60,15 +61,18 @@ class CControllerProxyList extends CController { if ($this->hasInput('filter_set')) { CProfile::update('web.proxies.filter_name', $this->getInput('filter_name', ''), PROFILE_TYPE_STR); CProfile::update('web.proxies.filter_status', $this->getInput('filter_status', -1), PROFILE_TYPE_INT); + CProfile::update('web.proxies.filter_version', $this->getInput('filter_version', -1), PROFILE_TYPE_INT); } elseif ($this->hasInput('filter_rst')) { CProfile::delete('web.proxies.filter_name'); CProfile::delete('web.proxies.filter_status'); + CProfile::delete('web.proxies.filter_version'); } $filter = [ 'name' => CProfile::get('web.proxies.filter_name', ''), - 'status' => CProfile::get('web.proxies.filter_status', -1) + 'status' => CProfile::get('web.proxies.filter_status', -1), + 'version' => CProfile::get('web.proxies.filter_version', -1) ]; $data = [ @@ -80,6 +84,10 @@ class CControllerProxyList extends CController { 'allowed_ui_conf_hosts' => $this->checkAccess(CRoleHelper::UI_CONFIGURATION_HOSTS) ]; + if ($filter['version'] == ZBX_PROXY_VERSION_ALL_OUTDATED) { + $filter['version'] = [ZBX_PROXY_VERSION_OUTDATED, ZBX_PROXY_VERSION_UNSUPPORTED]; + } + $limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1; $data['proxies'] = API::Proxy()->get([ 'output' => ['proxyid', $sortField], @@ -87,25 +95,18 @@ class CControllerProxyList extends CController { 'host' => ($filter['name'] === '') ? null : $filter['name'] ], 'filter' => [ - 'status' => ($filter['status'] == -1) ? null : $filter['status'] + 'status' => ($filter['status'] == -1) ? null : $filter['status'], + 'compatibility' => ($filter['version'] == -1) ? null : $filter['version'] ], - 'sortfield' => $sortField, 'limit' => $limit, 'editable' => true, 'preservekeys' => true ]); - // data sort and pager - order_result($data['proxies'], $sortField, $sortOrder); - - $page_num = getRequest('page', 1); - CPagerHelper::savePage('proxy.list', $page_num); - $data['paging'] = CPagerHelper::paginate($page_num, $data['proxies'], $sortOrder, - (new CUrl('zabbix.php'))->setArgument('action', $this->getAction()) - ); - $data['proxies'] = API::Proxy()->get([ - 'output' => ['proxyid', 'host', 'status', 'lastaccess', 'tls_connect', 'tls_accept', 'auto_compress'], + 'output' => ['proxyid', 'host', 'status', 'lastaccess', 'tls_connect', 'tls_accept', 'version', + 'compatibility' + ], 'selectHosts' => ['hostid', 'name', 'status'], 'proxyids' => array_keys($data['proxies']), 'editable' => true, @@ -113,8 +114,20 @@ class CControllerProxyList extends CController { ]); order_result($data['proxies'], $sortField, $sortOrder); + $page_num = getRequest('page', 1); + CPagerHelper::savePage('proxy.list', $page_num); + $data['paging'] = CPagerHelper::paginate($page_num, $data['proxies'], $sortOrder, + (new CUrl('zabbix.php'))->setArgument('action', $this->getAction()) + ); + foreach ($data['proxies'] as &$proxy) { - order_result($proxy['hosts'], 'name'); + // Convert proxy version to readable format. + $proxy['version'] = $proxy['version'] != 0 + ? (intdiv($proxy['version'], 10000) % 100).'.'.(intdiv($proxy['version'], 100) % 100).'.'. + ($proxy['version'] % 100) + : ''; + + CArrayHelper::sort($proxy['hosts'], ['name']); $proxy['hosts'] = array_slice($proxy['hosts'], 0, CSettingsHelper::get(CSettingsHelper::MAX_IN_TABLE) + 1); } unset($proxy); @@ -169,9 +182,13 @@ class CControllerProxyList extends CController { } } } - $data['config'] = ['max_in_table' => CSettingsHelper::get(CSettingsHelper::MAX_IN_TABLE)]; + $server_version = CSettingsHelper::getGlobal(CSettingsHelper::SERVER_STATUS); + if ($server_version !== '') { + $data['server_version'] = preg_split('/[a-z]/i', json_decode($server_version, true)['version'], 2)[0]; + } + $response = new CControllerResponseData($data); $response->setTitle(_('Configuration of proxies')); $this->setResponse($response); diff --git a/ui/app/views/proxy.list.php b/ui/app/views/proxy.list.php index af69a6abf22..48f331ea475 100644 --- a/ui/app/views/proxy.list.php +++ b/ui/app/views/proxy.list.php @@ -55,6 +55,18 @@ $filter = (new CFilter()) ->addValue(_('Passive'), HOST_STATUS_PROXY_PASSIVE) ->setModern(true) ) + ]), + (new CFormGrid()) + ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE) + ->addItem([ + new CLabel(_('Version')), + new CFormField( + (new CRadioButtonList('filter_version', (int) $data['filter']['version'])) + ->addValue(_('Any'), -1) + ->addValue(_('Current'), ZBX_PROXY_VERSION_CURRENT) + ->addValue(_('Outdated'), ZBX_PROXY_VERSION_ALL_OUTDATED) + ->setModern(true) + ) ]) ]); @@ -62,28 +74,46 @@ $form = (new CForm()) ->setId('proxy-list') ->setName('proxy_list'); +$view_url = (new CUrl('zabbix.php')) + ->setArgument('action', 'proxy.list') + ->getUrl(); + $proxy_list = (new CTableInfo()) ->setHeader([ (new CColHeader( (new CCheckBox('all_hosts'))->onClick("checkAll('".$form->getName()."', 'all_hosts', 'proxyids');") ))->addClass(ZBX_STYLE_CELL_WIDTH), - make_sorting_header(_('Name'), 'host', $data['sort'], $data['sortorder'], - (new CUrl('zabbix.php')) - ->setArgument('action', 'proxy.list') - ->getUrl() - ), - _('Mode'), - _('Encryption'), - _('Compression'), - _('Last seen (age)'), + make_sorting_header(_('Name'), 'host', $data['sort'], $data['sortorder'], $view_url), + make_sorting_header(_('Mode'), 'status', $data['sort'], $data['sortorder'], $view_url), + make_sorting_header(_('Encryption'), 'tls_accept', $data['sort'], $data['sortorder'], $view_url), + make_sorting_header(_('Version'), 'version', $data['sort'], $data['sortorder'], $view_url), + make_sorting_header(_('Last seen (age)'), 'lastaccess', $data['sort'], $data['sortorder'], $view_url), _('Host count'), _('Item count'), - _('Required performance (vps)'), + _('Required vps'), _('Hosts') ]); foreach ($data['proxies'] as $proxyid => $proxy) { $hosts = []; + $version = $proxy['version']; + $compatibility = $proxy['compatibility']; + + // Info icons. + $info_icons = []; + if ($compatibility == ZBX_PROXY_VERSION_OUTDATED) { + $version = (new CSpan($version))->addClass(ZBX_STYLE_RED); + $info_icons[] = makeWarningIcon(_s( + 'Proxy version is outdated, only data collection and remote execution is available with server version %1$s.', + $data['server_version'] + )); + } + elseif ($compatibility == ZBX_PROXY_VERSION_UNSUPPORTED) { + $version = (new CSpan($version))->addClass(ZBX_STYLE_RED); + $info_icons[] = makeErrorIcon( + _s('Proxy version is not supported by server version %1$s.', $data['server_version']) + ); + } foreach ($proxy['hosts'] as $host_index => $host) { if ($host_index >= $data['config']['max_in_table']) { @@ -157,10 +187,8 @@ foreach ($data['proxies'] as $proxyid => $proxy) { ))->addClass(ZBX_STYLE_WORDBREAK), $proxy['status'] == HOST_STATUS_PROXY_ACTIVE ? _('Active') : _('Passive'), $encryption, - ($proxy['auto_compress'] == HOST_COMPRESSION_ON) - ? (new CSpan(_('On')))->addClass(ZBX_STYLE_STATUS_GREEN) - : (new CSpan(_('Off')))->addClass(ZBX_STYLE_STATUS_GREY), - ($proxy['lastaccess'] == 0) + $info_icons ? [$version, ' ', makeInformationList($info_icons)] : $version, + $proxy['lastaccess'] == 0 ? (new CSpan(_('Never')))->addClass(ZBX_STYLE_RED) : zbx_date2age($proxy['lastaccess']), array_key_exists('host_count', $proxy) ? $proxy['host_count'] : '', diff --git a/ui/include/classes/api/services/CProxy.php b/ui/include/classes/api/services/CProxy.php index b5aea094c6f..b42427b0d2e 100644 --- a/ui/include/classes/api/services/CProxy.php +++ b/ui/include/classes/api/services/CProxy.php @@ -36,161 +36,173 @@ class CProxy extends CApiService { protected $sortColumns = ['hostid', 'host', 'status']; /** - * Get proxy data. + * @param array $options * - * @param array $options - * @param array $options['proxyids'] - * @param bool $options['editable'] only with read-write permission. Ignored for SuperAdmins - * @param int $options['count'] returns value in rowscount - * @param string $options['pattern'] - * @param int $options['limit'] - * @param string $options['sortfield'] - * @param string $options['sortorder'] + * @throws APIException * - * @return array + * @return array|string */ - public function get($options = []) { - $result = []; + public function get(array $options = []) { + $output_fields = ['proxyid', 'host', 'status', 'description', 'lastaccess', 'tls_connect', 'tls_accept', + 'tls_issuer', 'tls_subject', 'proxy_address', 'auto_compress', 'version', 'compatibility' + ]; - $sqlParts = [ - 'select' => ['hostid' => 'h.hostid'], - 'from' => ['hosts' => 'hosts h'], - 'where' => ['h.status IN ('.HOST_STATUS_PROXY_ACTIVE.','.HOST_STATUS_PROXY_PASSIVE.')'], - 'order' => [], - 'limit' => null + /* + * For internal calls, it is possible to get the write-only fields if they were specified in output. + * Specify write-only fields in output only if they will not appear in debug mode. + */ + if (APP::getMode() !== APP::EXEC_MODE_API) { + $output_fields[] = 'tls_psk_identity'; + $output_fields[] = 'tls_psk'; + } + + $host_fields = ['hostid', 'proxy_hostid', 'host', 'status', 'ipmi_authtype', 'ipmi_privilege', 'ipmi_username', + 'ipmi_password', 'maintenanceid', 'maintenance_status', 'maintenance_type', 'maintenance_from', 'name', + 'flags', 'description', 'tls_connect', 'tls_accept', 'tls_issuer', 'tls_subject', 'inventory_mode', + 'active_available' + ]; + $interface_fields = ['interfaceid', 'hostid', 'main', 'type', 'useip', 'ip', 'dns', 'port', 'available', + 'error', 'errors_from', 'disable_until' ]; - $defOptions = [ - 'proxyids' => null, - 'editable' => false, - 'nopermissions' => null, - // filter - 'filter' => null, - 'search' => null, - 'searchByAny' => null, - 'startSearch' => false, - 'excludeSearch' => false, - 'searchWildcardsEnabled' => null, + $api_input_rules = ['type' => API_OBJECT, 'fields' => [ + 'proxyids' => ['type' => API_IDS, 'flags' => API_ALLOW_NULL | API_NORMALIZE, 'default' => null], + 'filter' => ['type' => API_OBJECT, 'flags' => API_ALLOW_NULL, 'default' => null, 'fields' => [ + 'host' => ['type' => API_STRINGS_UTF8, 'flags' => API_ALLOW_NULL | API_NORMALIZE], + 'status' => ['type' => API_INTS32, 'flags' => API_ALLOW_NULL | API_NORMALIZE, 'in' => implode(',', [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE])], + 'lastaccess' => ['type' => API_INTS32, 'flags' => API_ALLOW_NULL | API_NORMALIZE, 'in' => '0:'.ZBX_MAX_DATE], + 'version' => ['type' => API_STRINGS_UTF8, 'flags' => API_ALLOW_NULL | API_NORMALIZE], + 'compatibility' => ['type' => API_INTS32, 'flags' => API_ALLOW_NULL | API_NORMALIZE, 'in' => implode(',', [ZBX_PROXY_VERSION_UNDEFINED, ZBX_PROXY_VERSION_CURRENT, ZBX_PROXY_VERSION_OUTDATED, ZBX_PROXY_VERSION_UNSUPPORTED])] + ]], + 'search' => ['type' => API_OBJECT, 'flags' => API_ALLOW_NULL, 'default' => null, 'fields' => [ + 'host' => ['type' => API_STRINGS_UTF8, 'flags' => API_ALLOW_NULL | API_NORMALIZE], + 'description' => ['type' => API_STRINGS_UTF8, 'flags' => API_ALLOW_NULL | API_NORMALIZE] + ]], + 'searchByAny' => ['type' => API_BOOLEAN, 'default' => false], + 'startSearch' => ['type' => API_FLAG, 'default' => false], + 'excludeSearch' => ['type' => API_FLAG, 'default' => false], + 'searchWildcardsEnabled' => ['type' => API_BOOLEAN, 'default' => false], // output - 'output' => API_OUTPUT_EXTEND, - 'countOutput' => false, - 'preservekeys' => false, - 'selectHosts' => null, - 'selectInterface' => null, - 'sortfield' => '', - 'sortorder' => '', - 'limit' => null + 'output' => ['type' => API_OUTPUT, 'in' => implode(',', $output_fields), 'default' => API_OUTPUT_EXTEND], + 'countOutput' => ['type' => API_FLAG, 'default' => false], + 'selectHosts' => ['type' => API_OUTPUT, 'flags' => API_ALLOW_NULL, 'in' => implode(',', $host_fields), 'default' => null], + 'selectInterface' => ['type' => API_OUTPUT, 'flags' => API_ALLOW_NULL, 'in' => implode(',', $interface_fields), 'default' => null], + // sort and limit + 'sortfield' => ['type' => API_STRINGS_UTF8, 'flags' => API_NORMALIZE, 'in' => implode(',', $this->sortColumns), 'uniq' => true, 'default' => []], + 'sortorder' => ['type' => API_SORTORDER, 'default' => []], + 'limit' => ['type' => API_INT32, 'flags' => API_ALLOW_NULL, 'in' => '1:'.ZBX_MAX_INT32, 'default' => null], + // flags + 'editable' => ['type' => API_BOOLEAN, 'default' => false], + 'preservekeys' => ['type' => API_BOOLEAN, 'default' => false], + 'nopermissions' => ['type' => API_BOOLEAN, 'default' => false] + ]]; + + if (!CApiInputValidator::validate($api_input_rules, $options, '/', $error)) { + self::exception(ZBX_API_ERROR_PARAMETERS, $error); + } + + $sql_parts = [ + 'select' => ['hostid' => 'h.hostid'], + 'from' => ['hosts' => 'hosts h'], + 'where' => [], + 'order' => [] ]; - $options = zbx_array_merge($defOptions, $options); // editable + PERMISSION CHECK if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN && !$options['nopermissions']) { $permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ; + if ($permission == PERM_READ_WRITE) { - return []; + return $options['countOutput'] ? '0' : []; } } + $count_output = $options['countOutput']; + + if ($count_output) { + $options['output'] = ['proxyid']; + $options['countOutput'] = false; + } + elseif ($options['output'] === API_OUTPUT_EXTEND) { + $options['output'] = $output_fields; + } + // proxyids - if (!is_null($options['proxyids'])) { - zbx_value2array($options['proxyids']); - $sqlParts['where'][] = dbConditionInt('h.hostid', $options['proxyids']); + if ($options['proxyids'] !== null) { + $sql_parts['where'][] = dbConditionInt('h.hostid', $options['proxyids']); } // filter - if (is_array($options['filter'])) { - $this->dbFilter('hosts h', $options, $sqlParts); - - $rt_filter = array_intersect_key($options['filter'], ['lastaccess' => '']); - - if ($rt_filter && $rt_filter['lastaccess'] !== null) { - $this->dbFilter('host_rtdata hr', ['filter' => $rt_filter] + $options, - $sqlParts - ); - } + if ($options['filter'] === null) { + $options['filter'] = []; } - // search - if (is_array($options['search'])) { - zbx_db_search('hosts h', $options, $sqlParts); + if (!array_key_exists('status', $options['filter']) || $options['filter']['status'] === null) { + $options['filter']['status'] = [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE]; } - // output - $fields = [ - 'proxyid', 'host', 'status', 'description', 'lastaccess', 'tls_connect', 'tls_accept', 'tls_issuer', - 'tls_subject', 'proxy_address', 'auto_compress' - ]; - $options['output'] = ($options['output'] === API_OUTPUT_EXTEND) ? $fields : (array) $options['output']; + $this->dbFilter('hosts h', $options, $sql_parts); - /* - * For internal calls of API method, is possible to get the write-only fields if they were specified in output. - * Specify write-only fields in output only if they will not appear in debug mode. - */ - if (APP::getMode() !== APP::EXEC_MODE_API) { - $fields[] = 'tls_psk_identity'; - $fields[] = 'tls_psk'; + $rt_filter = []; + foreach (['lastaccess', 'version', 'compatibility'] as $field) { + if (array_key_exists($field, $options['filter']) && $options['filter'][$field] !== null) { + $rt_filter[$field] = $options['filter'][$field]; + } } - $options['output'] = array_intersect($options['output'], $fields); - - // countOutput - if ($options['countOutput']) { - $options['sortfield'] = ''; - $sqlParts['select'] = ['COUNT(DISTINCT h.hostid) AS rowscount']; + if ($rt_filter) { + $this->dbFilter('host_rtdata hr', ['filter' => $rt_filter] + $options, $sql_parts); } - // limit - if (zbx_ctype_digit($options['limit']) && $options['limit']) { - $sqlParts['limit'] = $options['limit']; + // search + if ($options['search'] !== null) { + zbx_db_search('hosts h', $options, $sql_parts); } - $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); - while ($proxy = DBfetch($res)) { - if ($options['countOutput']) { - $result = $proxy['rowscount']; - } - else { - $proxy['proxyid'] = $proxy['hostid']; - unset($proxy['hostid']); + $sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); + $sql_parts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); + $resource = DBselect(self::createSelectQueryFromParts($sql_parts), $options['limit']); - $result[$proxy['proxyid']] = $proxy; - } - } + $db_proxies = []; - if ($options['countOutput']) { - return $result; + while ($row = DBfetch($resource)) { + $row['proxyid'] = $row['hostid']; + unset($row['hostid']); + + $db_proxies[$row['proxyid']] = $row; } - if ($result) { - $result = $this->addRelatedObjects($options, $result); - $result = $this->unsetExtraFields($result, ['hostid'], $options['output']); + if ($count_output) { + return (string) count($db_proxies); } - // removing keys (hash -> array) - if (!$options['preservekeys']) { - $result = zbx_cleanHashes($result); + if ($db_proxies) { + $db_proxies = $this->addRelatedObjects($options, $db_proxies); + $db_proxies = $this->unsetExtraFields($db_proxies, ['proxyid'], $options['output']); + + if (!$options['preservekeys']) { + $db_proxies = array_values($db_proxies); + } } - return $result; + return $db_proxies; } /** - * Create proxy. - * * @param array $proxies * + * @throws APIException + * * @return array */ - public function create(array $proxies) { + public function create(array $proxies): array { if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { self::exception(ZBX_API_ERROR_PERMISSIONS, _s('No permissions to call "%1$s.%2$s".', 'proxy', __FUNCTION__) ); } - $this->validateCreate($proxies); + self::validateCreate($proxies); $proxyids = DB::insert('hosts', $proxies); $host_rtdata = []; @@ -202,8 +214,8 @@ class CProxy extends CApiService { unset($proxy); DB::insert('host_rtdata', $host_rtdata, false); - self::updateInterfaces($proxies, __FUNCTION__); - self::updateHosts($proxies, __FUNCTION__); + self::updateInterfaces($proxies); + self::updateHosts($proxies); self::addAuditLog(CAudit::ACTION_ADD, CAudit::RESOURCE_PROXY, $proxies); @@ -211,13 +223,13 @@ class CProxy extends CApiService { } /** - * Update proxy. - * * @param array $proxies * + * @throws APIException + * * @return array */ - public function update(array $proxies) { + public function update(array $proxies): array { if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { self::exception(ZBX_API_ERROR_PERMISSIONS, _s('No permissions to call "%1$s.%2$s".', 'proxy', __FUNCTION__) @@ -243,8 +255,8 @@ class CProxy extends CApiService { DB::update('hosts', $upd_proxies); } - self::updateInterfaces($proxies, __FUNCTION__, $db_proxies); - self::updateHosts($proxies, __FUNCTION__, $db_proxies); + self::updateInterfaces($proxies, $db_proxies); + self::updateHosts($proxies, $db_proxies); self::addAuditLog(CAudit::ACTION_UPDATE, CAudit::RESOURCE_PROXY, $proxies, $db_proxies); @@ -252,15 +264,10 @@ class CProxy extends CApiService { } /** - * Update table "interface". - * - * @static - * * @param array $proxies - * @param string $method - * @param null|array $db_proxies + * @param array|null $db_proxies */ - private static function updateInterfaces(array &$proxies, string $method, array $db_proxies = null): void { + private static function updateInterfaces(array &$proxies, array $db_proxies = null): void { $ins_interfaces = []; $upd_interfaces = []; $del_interfaceids = []; @@ -270,7 +277,7 @@ class CProxy extends CApiService { continue; } - $db_interface = ($method == 'update') ? $db_proxies[$proxy['proxyid']]['interface'] : []; + $db_interface = $db_proxies !== null ? $db_proxies[$proxy['proxyid']]['interface'] : []; if ($proxy['interface']) { if ($db_interface) { @@ -319,15 +326,10 @@ class CProxy extends CApiService { } /** - * Update table "hosts". - * - * @static - * * @param array $proxies - * @param string $method - * @param null|array $db_proxies + * @param array|null $db_proxies */ - private static function updateHosts(array &$proxies, string $method, array $db_proxies = null): void { + private static function updateHosts(array &$proxies, array $db_proxies = null): void { $upd_hosts = []; foreach ($proxies as &$proxy) { @@ -335,7 +337,7 @@ class CProxy extends CApiService { continue; } - $db_hosts = ($method == 'update') ? $db_proxies[$proxy['proxyid']]['hosts'] : []; + $db_hosts = $db_proxies !== null ? $db_proxies[$proxy['proxyid']]['hosts'] : []; foreach ($proxy['hosts'] as $host) { if (!array_key_exists($host['hostid'], $db_hosts)) { @@ -366,11 +368,11 @@ class CProxy extends CApiService { } /** - * @param array $proxyids + * @param array $proxyids * * @return array */ - public function delete(array $proxyids) { + public function delete(array $proxyids): array { $this->validateDelete($proxyids, $db_proxies); DB::delete('host_rtdata', ['hostid' => $proxyids]); @@ -383,12 +385,12 @@ class CProxy extends CApiService { } /** - * @param array $proxyids - * @param array $db_proxies + * @param array $proxyids + * @param array|null $db_proxies * - * @throws APIException if the input is invalid. + * @throws APIException */ - private function validateDelete(array &$proxyids, array &$db_proxies = null) { + private function validateDelete(array &$proxyids, ?array &$db_proxies): void { if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { self::exception(ZBX_API_ERROR_PERMISSIONS, _s('No permissions to call "%1$s.%2$s".', 'proxy', __FUNCTION__) @@ -412,9 +414,9 @@ class CProxy extends CApiService { self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!')); } - $this->checkUsedInDiscovery($db_proxies); - $this->checkUsedInHosts($db_proxies); - $this->checkUsedInActions($db_proxies); + self::checkUsedInDiscovery($db_proxies); + self::checkUsedInHosts($db_proxies); + self::checkUsedInActions($db_proxies); } /** @@ -422,8 +424,10 @@ class CProxy extends CApiService { * * @param array $proxies * @param string $proxies[<proxyid>]['host'] + * + * @throws APIException */ - private function checkUsedInDiscovery(array $proxies) { + private static function checkUsedInDiscovery(array $proxies): void { $db_drules = DB::select('drules', [ 'output' => ['proxy_hostid', 'name'], 'filter' => ['proxy_hostid' => array_keys($proxies)], @@ -442,8 +446,10 @@ class CProxy extends CApiService { * * @param array $proxies * @param string $proxies[<proxyid>]['host'] + * + * @throws APIException */ - protected function checkUsedInHosts(array $proxies) { + private static function checkUsedInHosts(array $proxies): void { $db_hosts = DB::select('hosts', [ 'output' => ['proxy_hostid', 'name'], 'filter' => ['proxy_hostid' => array_keys($proxies)], @@ -462,8 +468,10 @@ class CProxy extends CApiService { * * @param array $proxies * @param string $proxies[<proxyid>]['host'] + * + * @throws APIException */ - private function checkUsedInActions(array $proxies) { + private static function checkUsedInActions(array $proxies): void { $db_actions = DBfetchArray(DBselect( 'SELECT a.name,c.value AS proxy_hostid'. ' FROM actions a,conditions c'. @@ -483,18 +491,27 @@ class CProxy extends CApiService { protected function applyQueryOutputOptions($tableName, $tableAlias, array $options, array $sqlParts) { $sqlParts = parent::applyQueryOutputOptions($tableName, $tableAlias, $options, $sqlParts); - if (!$options['countOutput'] && $options['selectInterface'] !== null) { - $sqlParts = $this->addQuerySelect('h.hostid', $sqlParts); - } + if (!$options['countOutput']) { + if ($options['selectInterface'] !== null) { + $sqlParts = $this->addQuerySelect('h.hostid', $sqlParts); + } - if ((!$options['countOutput'] && $this->outputIsRequested('lastaccess', $options['output']) - || (is_array($options['filter']) && array_key_exists('lastaccess', $options['filter'])))) { - $sqlParts['left_join'][] = ['alias' => 'hr', 'table' => 'host_rtdata', 'using' => 'hostid']; - $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; - } + $host_rtdata = false; + foreach (['lastaccess', 'version', 'compatibility'] as $field) { + if ($this->outputIsRequested($field, $options['output'])) { + $sqlParts = $this->addQuerySelect('hr.'.$field, $sqlParts); + $host_rtdata = true; + } + + if (is_array($options['filter']) && array_key_exists($field, $options['filter'])) { + $host_rtdata = true; + } + } - if (!$options['countOutput'] && $this->outputIsRequested('lastaccess', $options['output'])) { - $sqlParts = $this->addQuerySelect('hr.lastaccess', $sqlParts); + if ($host_rtdata) { + $sqlParts['left_join'][] = ['alias' => 'hr', 'table' => 'host_rtdata', 'using' => 'hostid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; + } } return $sqlParts; @@ -542,13 +559,11 @@ class CProxy extends CApiService { } /** - * Validates the input parameters for the create() method. - * * @param array $proxies * - * @throws APIException if the input is invalid. + * @throws APIException */ - protected function validateCreate(array &$proxies) { + private static function validateCreate(array &$proxies): void { $api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'uniq' => [['host']], 'fields' => [ 'host' => ['type' => API_H_NAME, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('hosts', 'host')], 'status' => ['type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(',', [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE])], @@ -624,16 +639,12 @@ class CProxy extends CApiService { } /** - * Check for unique proxy names. - * - * @static - * * @param array $proxies * @param array|null $db_proxies * - * @throws APIException if proxy names are not unique. + * @throws APIException */ - protected static function checkDuplicates(array $proxies, array $db_proxies = null): void { + private static function checkDuplicates(array $proxies, array $db_proxies = null): void { $names = []; foreach ($proxies as $proxy) { @@ -665,16 +676,12 @@ class CProxy extends CApiService { } /** - * Check for valid hosts. - * - * @static - * * @param array $proxies * @param array|null $db_proxies * - * @throws APIException if hosts are not valid. + * @throws APIException */ - protected static function checkHosts(array $proxies, array $db_proxies = null): void { + private static function checkHosts(array $proxies, array $db_proxies = null): void { $hostids = []; foreach ($proxies as $proxy) { @@ -683,7 +690,7 @@ class CProxy extends CApiService { } $proxy_hostids = array_column($proxy['hosts'], null, 'hostid'); - $db_proxy_hostids = ($db_proxies !== null) + $db_proxy_hostids = $db_proxies !== null ? array_column($db_proxies[$proxy['proxyid']]['hosts'], null, 'hostid') : []; @@ -694,7 +701,6 @@ class CProxy extends CApiService { return; } - // Check if host exists. $db_hosts = API::Host()->get([ 'output' => ['hostid', 'host', 'flags'], 'hostids' => array_keys($hostids), @@ -715,15 +721,11 @@ class CProxy extends CApiService { } /** - * Check for valid proxy address field. - * - * @static - * * @param array $proxies * - * @throws APIException if proxy addresses are not valid. + * @throws APIException */ - protected static function checkProxyAddress(array &$proxies): void { + private static function checkProxyAddress(array &$proxies): void { foreach ($proxies as $i => &$proxy) { if ($proxy['status'] == HOST_STATUS_PROXY_PASSIVE) { $proxy += ['proxy_address' => '']; @@ -739,16 +741,12 @@ class CProxy extends CApiService { } /** - * Check for valid interface. - * - * @static - * * @param array $proxies * @param string $method * - * @throws APIException if proxy interface is not valid. + * @throws APIException */ - protected static function checkInterface(array &$proxies, string $method): void { + private static function checkInterface(array &$proxies, string $method): void { foreach ($proxies as $i => &$proxy) { if ($proxy['status'] == HOST_STATUS_PROXY_ACTIVE) { $proxy += ['interface' => []]; @@ -793,14 +791,12 @@ class CProxy extends CApiService { } /** - * Validates the input parameters for the update() method. - * * @param array $proxies * @param array|null $db_proxies * - * @throws APIException if the input is invalid. + * @throws APIException */ - protected function validateUpdate(array &$proxies, array &$db_proxies = null) { + private function validateUpdate(array &$proxies, ?array &$db_proxies): void { $api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE | API_ALLOW_UNEXPECTED, 'uniq' => [['proxyid']], 'fields' => [ 'proxyid' => ['type' => API_ID, 'flags' => API_REQUIRED], 'status' => ['type' => API_INT32, 'in' => implode(',', [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE])], @@ -954,10 +950,6 @@ class CProxy extends CApiService { } /** - * Add the existing hosts and host interfaces to $db_proxies whether these are affected by the update. - * - * @static - * * @param array $proxies * @param array $db_proxies */ diff --git a/ui/include/classes/api/services/CSettings.php b/ui/include/classes/api/services/CSettings.php index 7c7aa2ef265..706bb81ea2c 100644 --- a/ui/include/classes/api/services/CSettings.php +++ b/ui/include/classes/api/services/CSettings.php @@ -98,7 +98,7 @@ class CSettings extends CApiService { $output_fields = ['default_theme', 'show_technical_errors', 'severity_color_0', 'severity_color_1', 'severity_color_2', 'severity_color_3', 'severity_color_4', 'severity_color_5', 'custom_color', 'problem_unack_color', 'problem_ack_color', 'ok_unack_color', 'ok_ack_color', 'default_lang', - 'x_frame_options', 'default_timezone', 'session_key', 'dbversion_status' + 'x_frame_options', 'default_timezone', 'session_key', 'dbversion_status', 'server_status' ]; $api_input_rules = ['type' => API_OBJECT, 'fields' => [ 'output' => ['type' => API_OUTPUT, 'in' => implode(',', $output_fields), 'default' => API_OUTPUT_EXTEND] diff --git a/ui/include/classes/data/CItemData.php b/ui/include/classes/data/CItemData.php index 561ce8d7040..1a2f90d521f 100644 --- a/ui/include/classes/data/CItemData.php +++ b/ui/include/classes/data/CItemData.php @@ -367,6 +367,7 @@ final class CItemData { 'zabbix[preprocessing_queue]', 'zabbix[process,<type>,<mode>,<state>]', 'zabbix[proxy,<name>,<param>]', + 'zabbix[proxy,discovery]', 'zabbix[proxy_history]', 'zabbix[queue,<from>,<to>]', 'zabbix[rcache,<cache>,<mode>]', @@ -1826,6 +1827,10 @@ final class CItemData { 'description' => _('Time of proxy last access. Name - proxy name. Valid params are: lastaccess - Unix timestamp, delay - seconds.'), 'value_type' => ITEM_VALUE_TYPE_UINT64 ], + 'zabbix[proxy,discovery]' => [ + 'description' => _('List of Zabbix proxies with name, mode, encryption, compression, version, last seen, host count, item count, required values per second (vps) and compatibility (current/outdated/unsupported). Returns JSON.'), + 'value_type' => ITEM_VALUE_TYPE_TEXT + ], 'zabbix[proxy_history]' => [ 'description' => _('Number of items in proxy history that are not yet sent to the server'), 'value_type' => ITEM_VALUE_TYPE_UINT64 diff --git a/ui/include/classes/helpers/CSettingsHelper.php b/ui/include/classes/helpers/CSettingsHelper.php index b06642fc1fb..3ed183d7492 100644 --- a/ui/include/classes/helpers/CSettingsHelper.php +++ b/ui/include/classes/helpers/CSettingsHelper.php @@ -79,6 +79,7 @@ class CSettingsHelper extends CConfigGeneralHelper { public const URL = 'url'; public const SCHEDULED_REPORT_TEST_TIMEOUT = 'report_test_timeout'; public const DBVERSION_STATUS = 'dbversion_status'; + public const SERVER_STATUS = 'server_status'; public const AUDITLOG_ENABLED = 'auditlog_enabled'; public const GEOMAPS_TILE_PROVIDER = 'geomaps_tile_provider'; public const GEOMAPS_TILE_URL = 'geomaps_tile_url'; diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php index 77b8ff2317c..93e48ccf657 100644 --- a/ui/include/defines.inc.php +++ b/ui/include/defines.inc.php @@ -18,11 +18,11 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -define('ZABBIX_VERSION', '6.4.0alpha1'); +define('ZABBIX_VERSION', '6.4.0alpha2'); define('ZABBIX_API_VERSION', '6.4.0'); define('ZABBIX_EXPORT_VERSION', '6.4'); -define('ZABBIX_DB_VERSION', 6030053); +define('ZABBIX_DB_VERSION', 6030056); define('DB_VERSION_SUPPORTED', 0); define('DB_VERSION_LOWER_THAN_MINIMUM', 1); @@ -117,6 +117,12 @@ define('ZBX_SCRIPT_EXECUTE_ON_AGENT', 0); define('ZBX_SCRIPT_EXECUTE_ON_SERVER', 1); define('ZBX_SCRIPT_EXECUTE_ON_PROXY', 2); +define('ZBX_PROXY_VERSION_UNDEFINED', 0); +define('ZBX_PROXY_VERSION_CURRENT', 1); +define('ZBX_PROXY_VERSION_OUTDATED', 2); +define('ZBX_PROXY_VERSION_UNSUPPORTED', 3); +define('ZBX_PROXY_VERSION_ALL_OUTDATED', 4); + define('ZBX_FLAG_DISCOVERY_NORMAL', 0x0); define('ZBX_FLAG_DISCOVERY_RULE', 0x1); define('ZBX_FLAG_DISCOVERY_PROTOTYPE', 0x2); diff --git a/ui/include/schema.inc.php b/ui/include/schema.inc.php index 46197f125a7..81342a71631 100644 --- a/ui/include/schema.inc.php +++ b/ui/include/schema.inc.php @@ -2787,6 +2787,11 @@ return [ 'default' => NULL, 'ref_table' => 'userdirectory', 'ref_field' => 'userdirectoryid' + ], + 'server_status' => [ + 'null' => false, + 'type' => DB::FIELD_TYPE_TEXT, + 'default' => '' ] ] ], @@ -8924,6 +8929,18 @@ return [ 'type' => DB::FIELD_TYPE_INT, 'length' => 10, 'default' => '0' + ], + 'version' => [ + 'null' => false, + 'type' => DB::FIELD_TYPE_INT, + 'length' => 10, + 'default' => '0' + ], + 'compatibility' => [ + 'null' => false, + 'type' => DB::FIELD_TYPE_INT, + 'length' => 10, + 'default' => '0' ] ] ], diff --git a/ui/locale/fr/LC_MESSAGES/frontend.po b/ui/locale/fr/LC_MESSAGES/frontend.po index 8c9d402df70..fa4facd63a4 100644 --- a/ui/locale/fr/LC_MESSAGES/frontend.po +++ b/ui/locale/fr/LC_MESSAGES/frontend.po @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Zabbix 6.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-03-17 15:53+0200\n" -"PO-Revision-Date: 2022-09-02 18:47+0000\n" +"PO-Revision-Date: 2022-09-14 18:35+0000\n" "Last-Translator: ERIC <eric78.zabbix@orange.fr>\n" "Language-Team: Zabbix <info@zabbix.com>\n" "Language: fr\n" @@ -2745,7 +2745,7 @@ msgstr "Impossible d'évaluer l'expression" #: include/classes/api/services/CScript.php:1064 msgid "Cannot execute URL type script." -msgstr "" +msgstr "Impossible d'exécuter le script de type URL." #: app/controllers/CControllerItemMassCheckNow.php:243 #: app/controllers/CControllerItemMassCheckNow.php:251 @@ -13745,7 +13745,7 @@ msgstr "Seuls les déclencheurs assignés à des hôtes activés et dépendant d #: app/views/administration.script.edit.php:193 msgid "Open in a new window" -msgstr "" +msgstr "Ouvrir dans une nouvelle fenêtre" #: include/httptest.inc.php:421 msgid "Opera" @@ -23563,7 +23563,7 @@ msgstr "via" #: include/func.inc.php:659 msgctxt "week short" msgid "w" -msgstr "" +msgstr "s" #: include/classes/api/services/CTask.php:443 msgid "wrong discovery rule type" diff --git a/ui/locale/sk/LC_MESSAGES/frontend.po b/ui/locale/sk/LC_MESSAGES/frontend.po index f8c7ba409a1..4a04942b6a4 100644 --- a/ui/locale/sk/LC_MESSAGES/frontend.po +++ b/ui/locale/sk/LC_MESSAGES/frontend.po @@ -4,8 +4,8 @@ msgstr "" "Project-Id-Version: Zabbix 6.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-03-17 15:53+0200\n" -"PO-Revision-Date: 2022-09-14 06:54+0000\n" -"Last-Translator: Jurijs <jurijs.klopovskis@zabbix.com>\n" +"PO-Revision-Date: 2022-09-15 07:34+0000\n" +"Last-Translator: Tomáš Heřmánek <tomas.hermanek@initmax.cz>\n" "Language-Team: Zabbix translation team\n" "Language: sk\n" "MIME-Version: 1.0\n" @@ -89,8 +89,8 @@ msgstr "%1$d znakov prekračuje maximálnu dĺžku %2$d znakov" #, c-format msgid "%1$d day" msgid_plural "%1$d days" -msgstr[0] "%1$d dni" -msgstr[1] "%1$d dní" +msgstr[0] "%1$d deň" +msgstr[1] "%1$d dni" msgstr[2] "%1$d dní" #: jsLoader.php:347 @@ -2818,7 +2818,7 @@ msgstr "Nedá sa vyhodnotiť výraz" #: include/classes/api/services/CScript.php:1064 msgid "Cannot execute URL type script." -msgstr "" +msgstr "Nedá sa spustiť skript typu URL." #: app/controllers/CControllerItemMassCheckNow.php:243 #: app/controllers/CControllerItemMassCheckNow.php:251 @@ -13863,7 +13863,7 @@ msgstr "Len spúšťače priradené k monitorovaným hostom alebo závislé na m #: app/views/administration.script.edit.php:193 msgid "Open in a new window" -msgstr "" +msgstr "Otvoriť v novom okne" #: include/httptest.inc.php:421 msgid "Opera" @@ -23708,7 +23708,7 @@ msgstr "cez" #: include/func.inc.php:659 msgctxt "week short" msgid "w" -msgstr "" +msgstr "w" #: include/classes/api/services/CTask.php:443 msgid "wrong discovery rule type" diff --git a/ui/locale/zh_CN/LC_MESSAGES/frontend.po b/ui/locale/zh_CN/LC_MESSAGES/frontend.po index f71342d8083..f55ce12db35 100644 --- a/ui/locale/zh_CN/LC_MESSAGES/frontend.po +++ b/ui/locale/zh_CN/LC_MESSAGES/frontend.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: Zabbix 6.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-03-17 15:53+0200\n" -"PO-Revision-Date: 2022-09-09 02:38+0000\n" +"PO-Revision-Date: 2022-09-16 02:58+0000\n" "Last-Translator: 璞玉 <puyu@bbqi.cc>\n" "Language-Team: Zabbix <info@zabbix.com>\n" "Language: zh_CN\n" @@ -2676,7 +2676,7 @@ msgstr "无法计算表达式" #: include/classes/api/services/CScript.php:1064 msgid "Cannot execute URL type script." -msgstr "" +msgstr "无法执行 URL 类型脚本。" #: app/controllers/CControllerItemMassCheckNow.php:243 #: app/controllers/CControllerItemMassCheckNow.php:251 @@ -13632,7 +13632,7 @@ msgstr "只计算指派给启用的主机的和相依于启用的项目的触发 #: app/views/administration.script.edit.php:193 msgid "Open in a new window" -msgstr "" +msgstr "在新窗口中打开" #: include/httptest.inc.php:421 msgid "Opera" @@ -23423,7 +23423,7 @@ msgstr "通过" #: include/func.inc.php:659 msgctxt "week short" msgid "w" -msgstr "" +msgstr "周" #: include/classes/api/services/CTask.php:443 msgid "wrong discovery rule type" diff --git a/ui/tests/api_json/data/data_test.sql b/ui/tests/api_json/data/data_test.sql index 7e61fc54f92..6018f00553e 100644 --- a/ui/tests/api_json/data/data_test.sql +++ b/ui/tests/api_json/data/data_test.sql @@ -239,21 +239,6 @@ INSERT INTO httpstepitem (httpstepitemid, httpstepid, itemid, type) VALUES (1501 INSERT INTO httpstepitem (httpstepitemid, httpstepid, itemid, type) VALUES (150158, 15016, 150158, 1); INSERT INTO httpstepitem (httpstepitemid, httpstepid, itemid, type) VALUES (150159, 15016, 150159, 0); --- proxy -INSERT INTO hosts (hostid, host, status, description) VALUES (99000, 'Api active proxy for delete0', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (99001, 'Api active proxy for delete1', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (99002, 'Api passive proxy for delete', 6, ''); -INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (99002, 99002,1, 0, 1, '127.0.0.1', 'localhost', 10051); -INSERT INTO hosts (hostid, host, status, description) VALUES (99003, 'Api active proxy in action', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (99004, 'Api active proxy with host', 5, ''); -INSERT INTO hosts (hostid, proxy_hostid, host, name, status, description) VALUES (99005, 99004,'API Host monitored with proxy', 'API Host monitored with proxy', 0, ''); -INSERT INTO interface (interfaceid,hostid,main,type,useip,ip,dns,port) values (99003,99005,1,1,1,'127.0.0.1','','10050'); -INSERT INTO actions (actionid, name, eventsource, evaltype, status, esc_period) VALUES (90, 'API action with proxy', 1, 0, 0, '1h'); -INSERT INTO operations (operationid, actionid, operationtype, esc_period, esc_step_from, esc_step_to, evaltype) VALUES (90, 90, 0, 0, 1, 1, 0); -INSERT INTO opmessage (operationid, default_msg, subject, message, mediatypeid) VALUES (90, 0, 'Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}', 'Discovery rule: {DISCOVERY.RULE.NAME}', NULL); -INSERT INTO opmessage_grp (opmessage_grpid, operationid, usrgrpid) VALUES (90, 90, 7); -INSERT INTO conditions (conditionid, actionid, conditiontype, operator, value, value2) VALUES (90,90,20,0,99003,''); - -- sysmaps INSERT INTO sysmaps (sysmapid, name, width, height, backgroundid, label_type, label_location, highlight, expandproblem, markelements, show_unack, userid, private) VALUES (10001, 'A', 800, 600, NULL, 0, 0, 1, 1, 1, 2, 1, 0); INSERT INTO sysmaps (sysmapid, name, width, height, backgroundid, label_type, label_location, highlight, expandproblem, markelements, show_unack, userid, private) VALUES (10002, 'B', 800, 600, NULL, 0, 0, 1, 1, 1, 2, 1, 1); @@ -268,6 +253,14 @@ INSERT INTO sysmaps_elements (selementid, sysmapid, elementid, elementtype, icon INSERT INTO interface (interfaceid,hostid,main,type,useip,ip,dns,port) values (99004,10084,1,2,1,'127.0.0.1','','161'); INSERT INTO interface_snmp (interfaceid, version, bulk, community) values (99004, 2, 1, '{$SNMP_COMMUNITY}'); +-- discovery action +INSERT INTO hosts (hostid, host, status, description) VALUES (99000, 'API active proxy for discovery action', 5, ''); +INSERT INTO actions (actionid, name, eventsource, evaltype, status, esc_period) VALUES (90, 'API action with proxy', 1, 0, 0, '1h'); +INSERT INTO operations (operationid, actionid, operationtype, esc_period, esc_step_from, esc_step_to, evaltype) VALUES (90, 90, 0, 0, 1, 1, 0); +INSERT INTO opmessage (operationid, default_msg, subject, message, mediatypeid) VALUES (90, 0, 'Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}', 'Discovery rule: {DISCOVERY.RULE.NAME}', NULL); +INSERT INTO opmessage_grp (opmessage_grpid, operationid, usrgrpid) VALUES (90, 90, 7); +INSERT INTO conditions (conditionid, actionid, conditiontype, operator, value, value2) VALUES (90,90,20,0,99000,''); + -- autoregistration action INSERT INTO usrgrp (usrgrpid, name) VALUES (47, 'User group for action delete'); INSERT INTO users (userid, username, passwd, autologin, autologout, lang, refresh, roleid, theme, attempt_failed, attempt_clock, rows_per_page) VALUES (53, 'action-user', '$2a$10$gFL5ORa/Ml0VBDGraHI3tuE1WuiKOX8ef497bAfzNiSXUx4Vrrn.y', 0, 0, 'en_US', '30s', 1, 'default', 0, 0, 50); diff --git a/ui/tests/api_json/testProxy.php b/ui/tests/api_json/testProxy.php index ddd35bb91ac..eb2fc1a32b5 100644 --- a/ui/tests/api_json/testProxy.php +++ b/ui/tests/api_json/testProxy.php @@ -19,85 +19,1687 @@ **/ -require_once dirname(__FILE__).'/../include/CAPITest.php'; +require_once __DIR__.'/../include/CAPITest.php'; /** - * @backup hosts + * @onBefore prepareTestData + * + * @onAfter clearData */ class testProxy extends CAPITest { - public static function proxy_delete() { - return [ - // Check proxy id validation. + private static $data = [ + 'proxyids' => [ + 'get_active_defaults' => null, + 'get_passive_defaults' => null, + 'get_version_undefined' => null, + 'get_version_current' => null, + 'get_version_outdated' => null, + 'get_version_unsupported' => null, + 'update_active_defaults' => null, + 'update_passive_defaults' => null, + 'update_active_psk' => null, + 'update_active_cert' => null, + 'update_active_any' => null, + 'update_passive_dns' => null, + 'update_passive_ip' => null, + 'update_passive_psk' => null, + 'update_passive_cert' => null, + 'update_hosts' => null, + 'delete_single' => null, + 'delete_multiple_1' => null, + 'delete_multiple_2' => null, + 'delete_used_in_host' => null, + 'delete_used_in_action' => null, + 'delete_used_in_discovery' => null + ], + 'groupids' => null, + 'hostids' => [ + 'with_proxy' => null, + 'without_proxy_1' => null, + 'without_proxy_2' => null + ], + 'actionids' => null, + 'druleids' => null, + + // Created proxies during proxy.create test (deleted at the end). + 'created' => [] + ]; + + /** + * Prepare data for tests. Create host groups, hosts, proxies, actions, discovery rules. + */ + public function prepareTestData(): void { + // Create proxies. + $proxies_data = [ [ - 'proxy' => [''], - 'expected_error' => 'Invalid parameter "/1": a number is expected.' + 'host' => 'API test proxy.get - active', + 'status' => HOST_STATUS_PROXY_ACTIVE ], [ - 'proxy' => ['abc'], - 'expected_error' => 'Invalid parameter "/1": a number is expected.' + 'host' => 'API test proxy.get - passive', + 'status' => HOST_STATUS_PROXY_PASSIVE, + 'interface' => [ + 'useip' => INTERFACE_USE_IP, + 'ip' => '127.0.0.1', + 'dns' => 'localhost', + 'port' => '10050' + ] ], [ - 'proxy' => ['1.1'], - 'expected_error' => 'Invalid parameter "/1": a number is expected.' + 'host' => 'API test proxy.get for filter - version undefined', + 'status' => HOST_STATUS_PROXY_ACTIVE ], [ - 'proxy' => ['123456'], - 'expected_error' => 'No permissions to referred object or it does not exist!' + 'host' => 'API test proxy.get for filter - version current', + 'status' => HOST_STATUS_PROXY_ACTIVE ], [ - 'proxy' => ['99000', '99000'], - 'expected_error' => 'Invalid parameter "/2": value (99000) already exists.' + 'host' => 'API test proxy.get for filter - version outdated', + 'status' => HOST_STATUS_PROXY_ACTIVE ], [ - 'proxy' => ['99000', 'abcd'], - 'expected_error' => 'Invalid parameter "/2": a number is expected.' + 'host' => 'API test proxy.get for filter - version unsupported', + 'status' => HOST_STATUS_PROXY_ACTIVE ], - // Check if proxy used in actions. [ - 'proxy' => ['99003'], - 'expected_error' => 'Proxy "Api active proxy in action" is used by action "API action with proxy".' + 'host' => 'API test proxy.update - active defaults', + 'status' => HOST_STATUS_PROXY_ACTIVE ], [ - 'proxy' => ['99000', '99003'], - 'expected_error' => 'Proxy "Api active proxy in action" is used by action "API action with proxy".' + 'host' => 'API test proxy.update - passive defaults', + 'status' => HOST_STATUS_PROXY_PASSIVE, + 'interface' => [ + 'useip' => INTERFACE_USE_IP, + 'ip' => '127.0.0.1', + 'dns' => 'localhost', + 'port' => '10050' + ] ], - // Check if proxy used in host. [ - 'proxy' => ['99004'], - 'expected_error' => 'Host "API Host monitored with proxy" is monitored by proxy "Api active proxy with host".' + 'host' => 'API test proxy.update - active with PSK-based connections from proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_accept' => HOST_ENCRYPTION_PSK, + 'tls_psk_identity' => 'Test PSK', + 'tls_psk' => '9b8eafedfaae00cece62e85d5f4792c7d9c9bcc851b23216a1d300311cc4f7cb' ], [ - 'proxy' => ['99000', '99004'], - 'expected_error' => 'Host "API Host monitored with proxy" is monitored by proxy "Api active proxy with host".' + 'host' => 'API test proxy.update - active with certificate-based connections from proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_accept' => HOST_ENCRYPTION_CERTIFICATE ], - // Check if proxy used in discovery rule. [ - 'proxy' => ['99006'], - 'expected_error' => 'Proxy "Api active proxy for discovery" is used by discovery rule "API discovery rule for delete with proxy".' + 'host' => 'API test proxy.update - active with any connections from proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_accept' => HOST_ENCRYPTION_NONE + HOST_ENCRYPTION_PSK + HOST_ENCRYPTION_CERTIFICATE, + 'tls_psk_identity' => 'Test PSK', + 'tls_psk' => '9b8eafedfaae00cece62e85d5f4792c7d9c9bcc851b23216a1d300311cc4f7cb' ], - // Successfully delete proxy. [ - 'proxy' => ['99000'], - 'expected_error' => null + 'host' => 'API test proxy.update - passive with DNS name', + 'status' => HOST_STATUS_PROXY_PASSIVE, + 'interface' => [ + 'useip' => INTERFACE_USE_DNS, + 'ip' => '127.0.0.1', + 'dns' => 'localhost', + 'port' => '10050' + ] + ], + [ + 'host' => 'API test proxy.update - passive with IP address', + 'status' => HOST_STATUS_PROXY_PASSIVE, + 'interface' => [ + 'useip' => INTERFACE_USE_IP, + 'ip' => '127.0.0.1', + 'dns' => 'localhost', + 'port' => '10050' + ] + ], + [ + 'host' => 'API test proxy.update - passive with PSK-based connections to proxy', + 'status' => HOST_STATUS_PROXY_PASSIVE, + 'interface' => [ + 'useip' => INTERFACE_USE_IP, + 'ip' => '127.0.0.1', + 'dns' => 'localhost', + 'port' => '10050' + ], + 'tls_connect' => HOST_ENCRYPTION_PSK + ], + [ + 'host' => 'API test proxy.update - passive with certificate-based connections to proxy', + 'status' => HOST_STATUS_PROXY_PASSIVE, + 'interface' => [ + 'useip' => INTERFACE_USE_IP, + 'ip' => '127.0.0.1', + 'dns' => 'localhost', + 'port' => '10050' + ], + 'tls_connect' => HOST_ENCRYPTION_CERTIFICATE + ], + [ + 'host' => 'API test proxy.update - hosts', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API test proxy.delete - single', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API test proxy.delete - multiple 1', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API test proxy.delete - multiple 2', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API test proxy.delete - used in hosts', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API test proxy.delete - used in actions', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API test proxy.delete - used in discovery rules', + 'status' => HOST_STATUS_PROXY_ACTIVE + ] + ]; + $proxies = CDataHelper::call('proxy.create', $proxies_data); + $this->assertArrayHasKey('proxyids', $proxies, __FUNCTION__.'() failed: Could not create proxies.'); + self::$data['proxyids'] = array_combine(array_keys(self::$data['proxyids']), $proxies['proxyids']); + + // Manually update "host_rtdata" table. + $proxy_rtdata = [ + $proxies['proxyids'][3] => [ + 'lastaccess' => 1662034530, + 'version' => 60400, + 'compatibility' => ZBX_PROXY_VERSION_CURRENT + ], + $proxies['proxyids'][4] => [ + 'lastaccess' => 1662034225, + 'version' => 60200, + 'compatibility' => ZBX_PROXY_VERSION_OUTDATED + ], + $proxies['proxyids'][5] => [ + 'lastaccess' => 1651407015, + 'version' => 50401, + 'compatibility' => ZBX_PROXY_VERSION_UNSUPPORTED + ] + ]; + + $upd_proxy_rtdata = []; + foreach ($proxy_rtdata as $proxyid => $rtdata) { + $upd_proxy_rtdata[] = [ + 'values' => [ + 'lastaccess' => $rtdata['lastaccess'], + 'version' => $rtdata['version'], + 'compatibility' => $rtdata['compatibility'] + ], + 'where' => ['hostid' => $proxyid] + ]; + } + + DB::update('host_rtdata', $upd_proxy_rtdata); + + // Create host group. + $hostgroups = CDataHelper::call('hostgroup.create', [ + 'name' => 'API test host group' + ]); + $this->assertArrayHasKey('groupids', $hostgroups, __FUNCTION__.'() failed: Could not create host groups.'); + self::$data['groupids'] = $hostgroups['groupids']; + + // Create host. + $hosts_data = [ + [ + 'host' => 'api_test_host_with_proxy', + 'name' => 'API test host - with proxy', + 'proxy_hostid' => self::$data['proxyids']['delete_used_in_host'], + 'groups' => [ + [ + 'groupid' => self::$data['groupids'][0] + ] + ] + ], + [ + 'host' => 'api_test_host_without_proxy_1', + 'name' => 'API test host - without proxy 1', + 'groups' => [ + [ + 'groupid' => self::$data['groupids'][0] + ] + ] ], [ - 'proxy' => ['99001', '99002'], + 'host' => 'api_test_host_without_proxy_2', + 'name' => 'API test host - without proxy 2', + 'groups' => [ + [ + 'groupid' => self::$data['groupids'][0] + ] + ] + ] + ]; + $hosts = CDataHelper::call('host.create', $hosts_data); + $this->assertArrayHasKey('hostids', $hosts, __FUNCTION__.'() failed: Could not create hosts.'); + self::$data['hostids'] = array_combine(array_keys(self::$data['hostids']), $hosts['hostids']); + + // actions + $actions_data = [ + 'name' => 'API test discovery action', + 'eventsource' => EVENT_SOURCE_DISCOVERY, + 'filter' => [ + 'evaltype' => CONDITION_EVAL_TYPE_AND_OR, + 'conditions' => [ + [ + 'conditiontype' => CONDITION_TYPE_PROXY, + 'operator' => CONDITION_OPERATOR_EQUAL, + 'value' => self::$data['proxyids']['delete_used_in_action'] + ] + ] + ], + 'operations' => [ + [ + 'operationtype' => OPERATION_TYPE_MESSAGE, + 'opmessage_grp' => [ + [ + 'usrgrpid' => 7 + ] + ], + 'opmessage' => [ + 'mediatypeid' => 0, + 'default_msg' => 1 + ] + ] + ] + ]; + $actions = CDataHelper::call('action.create', $actions_data); + $this->assertArrayHasKey('actionids', $actions, __FUNCTION__.'() failed: Could not create actions.'); + self::$data['actionids'] = $actions['actionids']; + + // discovery rules + $drules_data = [ + 'name' => 'API test discovery rule', + 'iprange' => '192.168.1.1-255', + 'proxy_hostid' => self::$data['proxyids']['delete_used_in_discovery'], + 'dchecks' => [ + [ + 'type' => SVC_AGENT, + 'key_' => 'system.uname', + 'ports' => 10050, + 'uniq' => 0 + ] + ] + ]; + $drules = CDataHelper::call('drule.create', $drules_data); + $this->assertArrayHasKey('druleids', $drules, __FUNCTION__.'() failed: Could not create discovery rules.'); + self::$data['druleids'] = $drules['druleids']; + } + + /** + * Data provider for proxy.create. Array contains invalid proxies. + * + * @return array + */ + public static function getProxyCreateDataInvalid(): array { + return [ + 'Test proxy.create: empty request' => [ + 'proxy' => [], + 'expected_error' => 'Invalid parameter "/": cannot be empty.' + ], + 'Test proxy.create: unexpected parameter' => [ + 'proxy' => [ + 'abc' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1": unexpected parameter "abc".' + ], + + // Check "host". + 'Test proxy.create: missing "host"' => [ + 'proxy' => [ + 'description' => '' + ], + 'expected_error' => 'Invalid parameter "/1": the parameter "host" is missing.' + ], + 'Test proxy.create: invalid "host" (empty string)' => [ + 'proxy' => [ + 'host' => '' + ], + 'expected_error' => 'Invalid parameter "/1/host": cannot be empty.' + ], + 'Test proxy.create: invalid "host" (UTF-8 string)' => [ + 'proxy' => [ + 'host' => 'АПИ прокси УТФ-8' + ], + 'expected_error' => 'Invalid parameter "/1/host": invalid host name.' + ], + 'Test proxy.create: invalid "host" (does not match naming pattern)' => [ + 'proxy' => [ + 'host' => 'API create proxy?' + ], + 'expected_error' => 'Invalid parameter "/1/host": invalid host name.' + ], + 'Test proxy.create: invalid "host" (too long)' => [ + 'proxy' => [ + 'host' => str_repeat('h', DB::getFieldLength('hosts', 'host') + 1) + ], + 'expected_error' => 'Invalid parameter "/1/host": value is too long.' + ], + 'Test proxy.create: multiple proxies with the same "host"' => [ + 'proxy' => [ + [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE + ] + ], + 'expected_error' => 'Invalid parameter "/2": value (host)=(API create proxy) already exists.' + ], + 'Test proxy.create: invalid "host" (duplicate)' => [ + 'proxy' => [ + 'host' => 'API test proxy.get - active', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + 'expected_error' => 'Proxy "API test proxy.get - active" already exists.' + ], + + // Check "status". + 'Test proxy.create: missing "status"' => [ + 'proxy' => [ + 'host' => 'API create proxy' + ], + 'expected_error' => 'Invalid parameter "/1": the parameter "status" is missing.' + ], + 'Test proxy.create: invalid "status" (string)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1/status": an integer is expected.' + ], + 'Test proxy.create: invalid "status" (not in range)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => 999999 + ], + 'expected_error' => 'Invalid parameter "/1/status": value must be one of '. + implode(', ', [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE]).'.' + ], + + // Check "description". + 'Test proxy.create: invalid "description" (bool)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'description' => false + ], + 'expected_error' => 'Invalid parameter "/1/description": a character string is expected.' + ], + 'Test proxy.create: invalid "description" (too long)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'description' => str_repeat('d', DB::getFieldLength('hosts', 'description') + 1) + ], + 'expected_error' => 'Invalid parameter "/1/description": value is too long.' + ], + + // Check "proxy_address". + 'Test proxy.create: invalid "proxy_address" (bool)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'proxy_address' => false + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": a character string is expected.' + ], + 'Test proxy.create: invalid "proxy_address" (IP address range)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'proxy_address' => '192.168.0-255.0/30' + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": invalid address range "192.168.0-255.0/30".' + ], + 'Test proxy.create: invalid "proxy_address" (IPv6 address range)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'proxy_address' => '::ff-0ffff' + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": invalid address range "::ff-0ffff".' + ], + 'Test proxy.create: invalid "proxy_address" (user macro)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'proxy_address' => '{$MACRO}' + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": invalid address range "{$MACRO}".' + ], + 'Test proxy.create: invalid "proxy_address" (too long)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'proxy_address' => str_repeat('a', DB::getFieldLength('hosts', 'proxy_address') + 1) + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": value is too long.' + ], + + // Check "hosts". + 'Test proxy.create: invalid "hosts" (string)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1/hosts": an array is expected.' + ], + 'Test proxy.create: invalid "hosts" (array with string)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => ['abc'] + ], + 'expected_error' => 'Invalid parameter "/1/hosts/1": an array is expected.' + ], + 'Test proxy.create: missing "hostid" for "hosts"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => [ + [] + ] + ], + 'expected_error' => 'Invalid parameter "/1/hosts/1": the parameter "hostid" is missing.' + ], + 'Test proxy.create: unexpected parameter for "hosts"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => [ + ['abc' => ''] + ] + ], + 'expected_error' => 'Invalid parameter "/1/hosts/1": unexpected parameter "abc".' + ], + 'Test proxy.create: invalid "hostid" (string) for "hosts"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => [ + ['hostid' => 'abc'] + ] + ], + 'expected_error' => 'Invalid parameter "/1/hosts/1/hostid": a number is expected.' + ], + 'Test proxy.create: invalid "hostid" (non-existent) for "hosts"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => [ + ['hostid' => 999999] + ] + ], + 'expected_error' => 'No permissions to referred object or it does not exist!' + ], + 'Test proxy.create: invalid "hostid" (duplicate) for "hosts"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'hosts' => [ + ['hostid' => 0], + ['hostid' => 0] + ] + ], + 'expected_error' => 'Invalid parameter "/1/hosts/2": value (hostid)=(0) already exists.' + ], + + // Check "interface". + 'Test proxy.create: invalid "interface" (string)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1/interface": an array is expected.' + ], + 'Test proxy.create: unexpected parameter for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'abc' => '' + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface": unexpected parameter "abc".' + ], + 'Test proxy.create: invalid "useip" (string) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'useip' => 'abc' + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/useip": an integer is expected.' + ], + 'Test proxy.create: invalid "useip" (not in range) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'useip' => 999999 + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/useip": value must be one of '. + implode(', ', [INTERFACE_USE_DNS, INTERFACE_USE_IP]).'.' + ], + 'Test proxy.create: invalid "ip" (string) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'ip' => 'abc' + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/ip": an IP address is expected.' + ], + 'Test proxy.create: invalid "ip" (too long) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'ip' => str_repeat('i', DB::getFieldLength('interface', 'ip') + 1) + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/ip": value is too long.' + ], + 'Test proxy.create: invalid "dns" (bool) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'dns' => false + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/dns": a character string is expected.' + ], + 'Test proxy.create: invalid "dns" (too long) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'dns' => str_repeat('d', DB::getFieldLength('interface', 'dns') + 1) + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/dns": value is too long.' + ], + 'Test proxy.create: invalid "port" (string) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'port' => 'abc' + ] + ], + 'expected_error' => 'Invalid parameter "/1/interface/port": an integer is expected.' + ], + 'Test proxy.create: invalid "port" (not in range) for "interface"' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'interface' => [ + 'port' => 999999 + ] + ], + 'expected_error' => + 'Invalid parameter "/1/interface/port": value must be one of 0-'.ZBX_MAX_PORT_NUMBER.'.' + ], + 'Test proxy.create: invalid "tls_connect" (string)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_connect' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1/tls_connect": an integer is expected.' + ], + 'Test proxy.create: invalid "tls_connect" (not in range) for active proxy' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_connect' => 999999 + ], + 'expected_error' => 'Invalid parameter "/1/tls_connect": value must be '.HOST_ENCRYPTION_NONE.'.' + ], + 'Test proxy.create: invalid "tls_accept" (string)' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_accept' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1/tls_accept": an integer is expected.' + ], + 'Test proxy.create: invalid "tls_accept" (not in range) for active proxy' => [ + 'proxy' => [ + 'host' => 'API create proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE, + 'tls_accept' => 999999 + ], + 'expected_error' => 'Invalid parameter "/1/tls_accept": value must be one of 1-7.' + ] + + // TODO: add more test cases + ]; + } + + /** + * Data provider for proxy.create. Array contains valid proxies. + * + * @return array + */ + public static function getProxyCreateDataValid(): array { + return [ + 'Test proxy.create: single proxy' => [ + 'proxy' => [ + 'host' => 'API create single proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + 'expected_error' => null + ], + 'Test proxy.create: multiple proxies' => [ + 'proxy' => [ + [ + 'host' => 'API create first proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE + ], + [ + 'host' => 'API create second proxy', + 'status' => HOST_STATUS_PROXY_ACTIVE + ] + ], 'expected_error' => null ] + + // TODO: add more test cases ]; } /** - * @dataProvider proxy_delete - */ - public function testProxy_Delete($proxy, $expected_error) { - $result = $this->call('proxy.delete', $proxy, $expected_error); + * Test proxy.create with errors like missing fields, optional invalid fields and valid fields. + * + * @dataProvider getProxyCreateDataInvalid + * @dataProvider getProxyCreateDataValid + */ + public function testProxy_Create(array $proxies, ?string $expected_error): void { + // Accept single and multiple proxies just like API method. Work with multidimensional array in result. + if (!array_key_exists(0, $proxies)) { + $proxies = zbx_toArray($proxies); + } + + $sql_proxies = 'SELECT NULL FROM hosts h WHERE '.dbConditionInt('h.status', [ + HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE + ]); + $old_hash_proxies = CDBHelper::getHash($sql_proxies); + + $result = $this->call('proxy.create', $proxies, $expected_error); if ($expected_error === null) { - foreach ($result['result']['proxyids'] as $id) { - $this->assertEquals(0, CDBHelper::getCount('SELECT NULL FROM hosts WHERE hostid='.zbx_dbstr($id))); + // Something was changed in DB. + $this->assertNotSame($old_hash_proxies, CDBHelper::getHash($sql_proxies)); + $this->assertEquals(count($proxies), count($result['result']['proxyids'])); + + // Add proxy IDs to create array, so they can be deleted after tests are complete. + self::$data['created'] = array_merge(self::$data['created'], $result['result']['proxyids']); + + // Check individual fields according to each proxy status. + foreach ($result['result']['proxyids'] as $num => $proxyid) { + $db_proxies = $this->getProxies([$proxyid]); + $db_proxy = $db_proxies[$proxyid]; + + // Required fields. + $this->assertNotEmpty($db_proxy['host']); + $this->assertSame($proxies[$num]['host'], $db_proxy['host']); + $this->assertEquals($proxies[$num]['status'], $db_proxy['status']); + + if (array_key_exists('description', $proxies[$num])) { + $this->assertSame($proxies[$num]['description'], $db_proxy['description']); + } + else { + $this->assertEmpty($db_proxy['description']); + } + + if (array_key_exists('proxy_address', $proxies[$num])) { + $this->assertSame($proxies[$num]['proxy_address'], $db_proxy['proxy_address']); + } + else { + $this->assertEmpty($db_proxy['proxy_address']); + } + + foreach (['hosts', 'interface'] as $field) { + if (array_key_exists($field, $proxies[$num]) && $proxies[$num][$field]) { + $this->assertEqualsCanonicalizing($proxies[$num][$field], $db_proxy[$field]); + } + else { + $this->assertEmpty($db_proxy[$field]); + } + } + + foreach (['tls_connect', 'tls_accept'] as $field) { + if (array_key_exists($field, $proxies[$num])) { + $this->assertEquals($proxies[$num][$field], $db_proxy[$field]); + } + else { + $this->assertSame(DB::getDefault('hosts', $field), $db_proxy[$field]); + } + } + + foreach (['tls_issuer', 'tls_subject', 'tls_psk_identity', 'tls_psk'] as $field) { + if (array_key_exists($field, $proxies[$num])) { + $this->assertSame($proxies[$num][$field], $db_proxy[$field]); + } + else { + $this->assertEmpty($db_proxy[$field]); + } + } } } + else { + $this->assertSame($old_hash_proxies, CDBHelper::getHash($sql_proxies)); + } + } + + /** + * Data provider for proxy.get. Array contains invalid proxy parameters. + * + * @return array + */ + public static function getProxyGetDataInvalid(): array { + return [ + // Check unexpected params. + 'Test proxy.get: unexpected parameter' => [ + 'request' => [ + 'abc' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/": unexpected parameter "abc".' + ], + + // Check "proxyids" field. + 'Test proxy.get: invalid "proxyids" (empty string)' => [ + 'request' => [ + 'proxyids' => '' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/proxyids": an array is expected.' + ], + 'Test proxy.get: invalid "proxyids" (array with empty string)' => [ + 'request' => [ + 'proxyids' => [''] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/proxyids/1": a number is expected.' + ], + + // Check filter. + 'Test proxy.get: invalid "filter" (empty string)' => [ + 'request' => [ + 'filter' => '' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter": an array is expected.' + ], + + // Check unexpected parameters that exist in object, but not in filter. + 'Test proxy.get: unexpected parameter in "filter"' => [ + 'request' => [ + 'filter' => [ + 'proxy_address' => 'proxy_address' + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter": unexpected parameter "proxy_address".' + ], + + 'Test proxy.get: invalid "status" (string) in "filter"' => [ + 'request' => [ + 'filter' => [ + 'status' => 'abc' + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/status": an array is expected.' + ], + 'Test proxy.get: invalid "status" in "filter"' => [ + 'request' => [ + 'filter' => [ + 'status' => 999999 + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/status/1": value must be one of '. + implode(', ', [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE]).'.' + ], + 'Test proxy.get: invalid "lastaccess" (string) in "filter"' => [ + 'request' => [ + 'filter' => [ + 'lastaccess' => 'abc' + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/lastaccess": an array is expected.' + ], + 'Test proxy.get: invalid "lastaccess" (array with string) in "filter"' => [ + 'request' => [ + 'filter' => [ + 'lastaccess' => ['abc'] + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/lastaccess/1": an integer is expected.' + ], + 'Test proxy.get: invalid "lastaccess" (not in range) in "filter"' => [ + 'request' => [ + 'filter' => [ + 'lastaccess' => [-1] + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/lastaccess/1": value must be one of 0-'.ZBX_MAX_DATE.'.' + ], + 'Test proxy.get: invalid "lastaccess" (too large) in "filter"' => [ + 'request' => [ + 'filter' => [ + 'lastaccess' => [ZBX_MAX_DATE + 1] + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/lastaccess/1": a number is too large.' + ], + 'Test proxy.get: invalid "compatibility" (string) for "filter"' => [ + 'request' => [ + 'filter' => [ + 'compatibility' => 'abc' + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/compatibility": an array is expected.' + ], + 'Test proxy.get: invalid "compatibility" (not in range) for "filter"' => [ + 'request' => [ + 'filter' => [ + 'compatibility' => 999999 + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/filter/compatibility/1": value must be one of '. + implode(', ', [ + ZBX_PROXY_VERSION_UNDEFINED, ZBX_PROXY_VERSION_CURRENT, ZBX_PROXY_VERSION_OUTDATED, + ZBX_PROXY_VERSION_UNSUPPORTED + ]).'.' + ], + + // Check "search" option. + 'Test proxy.get: invalid "search" (string)' => [ + 'request' => [ + 'search' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/search": an array is expected.' + ], + + // Check unexpected parameters that exist in object, but not in search. + 'Test proxy.get: unexpected parameter in "search"' => [ + 'request' => [ + 'search' => [ + 'proxyid' => 'proxyid' + ] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/search": unexpected parameter "proxyid".' + ], + + // Check "output" option. + 'Test proxy.get: invalid parameter "output" (string)' => [ + 'request' => [ + 'output' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/output": value must be "'.API_OUTPUT_EXTEND.'".' + ], + 'Test proxy.get: invalid parameter "output" (array with string)' => [ + 'request' => [ + 'output' => ['abc'] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/output/1": value must be one of "proxyid", "host", "status", "description", "lastaccess", "tls_connect", "tls_accept", "tls_issuer", "tls_subject", "proxy_address", "auto_compress", "version", "compatibility".' + ], + + // Check write-only fields are not returned. + 'Test proxy.get: write-only field "tls_psk_identity"' => [ + 'request' => [ + 'output' => ['tls_psk_identity'] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/output/1": value must be one of "proxyid", "host", "status", "description", "lastaccess", "tls_connect", "tls_accept", "tls_issuer", "tls_subject", "proxy_address", "auto_compress", "version", "compatibility".' + ], + 'Test proxy.get: write-only field "tls_psk"' => [ + 'request' => [ + 'output' => ['tls_psk'] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/output/1": value must be one of "proxyid", "host", "status", "description", "lastaccess", "tls_connect", "tls_accept", "tls_issuer", "tls_subject", "proxy_address", "auto_compress", "version", "compatibility".' + ], + + // Check "selectHosts" option. + 'Test proxy.get: invalid parameter "selectHosts" (string)' => [ + 'request' => [ + 'selectHosts' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/selectHosts": value must be "'.API_OUTPUT_EXTEND.'".' + ], + 'Test proxy.get: invalid parameter "selectHosts" (array with string)' => [ + 'request' => [ + 'selectHosts' => ['abc'] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/selectHosts/1": value must be one of "hostid", "proxy_hostid", "host", "status", "ipmi_authtype", "ipmi_privilege", "ipmi_username", "ipmi_password", "maintenanceid", "maintenance_status", "maintenance_type", "maintenance_from", "name", "flags", "description", "tls_connect", "tls_accept", "tls_issuer", "tls_subject", "inventory_mode", "active_available".' + ], + + // Check "selectInterface" option. + 'Test proxy.get: invalid parameter "selectInterface" (string)' => [ + 'request' => [ + 'selectInterface' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/selectInterface": value must be "'.API_OUTPUT_EXTEND.'".' + ], + 'Test proxy.get: invalid parameter "selectInterface" (array with string)' => [ + 'request' => [ + 'selectInterface' => ['abc'] + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/selectInterface/1": value must be one of "interfaceid", "hostid", "main", "type", "useip", "ip", "dns", "port", "available", "error", "errors_from", "disable_until".' + ], + + // Check common fields that are not flags, but require strict validation. + 'Test proxy.get: invalid parameter "searchByAny" (string)' => [ + 'request' => [ + 'searchByAny' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/searchByAny": a boolean is expected.' + ], + 'Test proxy.get: invalid parameter "searchWildcardsEnabled" (string)' => [ + 'request' => [ + 'searchWildcardsEnabled' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/searchWildcardsEnabled": a boolean is expected.' + ], + 'Test proxy.get: invalid parameter "sortfield" (bool)' => [ + 'request' => [ + 'sortfield' => false + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/sortfield": an array is expected.' + ], + 'Test proxy.get: invalid parameter "sortfield"' => [ + 'request' => [ + 'sortfield' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/sortfield/1": value must be one of "hostid", "host", "status".' + ], + 'Test proxy.get: invalid parameter "sortorder" (bool)' => [ + 'request' => [ + 'sortorder' => false + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/sortorder": an array or a character string is expected.' + ], + 'Test proxy.get: invalid parameter "sortorder" (not in range)' => [ + 'request' => [ + 'sortorder' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => + 'Invalid parameter "/sortorder": value must be one of "'.ZBX_SORT_UP.'", "'.ZBX_SORT_DOWN.'".' + ], + 'Test proxy.get: invalid parameter "limit" (bool)' => [ + 'request' => [ + 'limit' => false + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/limit": an integer is expected.' + ], + 'Test proxy.get: invalid parameter "editable" (string)' => [ + 'request' => [ + 'editable' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/editable": a boolean is expected.' + ], + 'Test proxy.get: invalid parameter "preservekeys" (string)' => [ + 'request' => [ + 'preservekeys' => 'abc' + ], + 'expected_result' => [], + 'expected_error' => 'Invalid parameter "/preservekeys": a boolean is expected.' + ] + ]; + } + + /** + * Data provider for proxy.get. Array contains valid proxy parameters. + * + * @return array + */ + public static function getProxyGetDataValid(): array { + return [ + // Check validity of "proxyids" without getting any results. + 'Test proxy.get: empty "proxyids"' => [ + 'request' => [ + 'proxyids' => [] + ], + 'expected_result' => [], + 'expected_error' => null + ], + + // Check no fields are returned on empty selection. + 'Test proxy.get: empty "output"' => [ + 'request' => [ + 'output' => [], + 'proxyids' => ['get_active_defaults', 'get_passive_defaults'] + ], + 'expected_result' => [ + [], + [] + ], + 'expected_error' => null + ], + + // Check fields from "host_rtdata" table are returned. + 'Test proxy.get: "lastaccess", "version", "compatibility"' => [ + 'request' => [ + 'output' => ['lastaccess', 'version', 'compatibility'], + 'proxyids' => ['get_version_current', 'get_version_outdated', 'get_version_unsupported'] + ], + 'expected_result' => [ + [ + 'lastaccess' => '1662034530', + 'version' => '60400', + 'compatibility' => '1' + ], + [ + 'lastaccess' => '1662034225', + 'version' => '60200', + 'compatibility' => '2' + ], + [ + 'lastaccess' => '1651407015', + 'version' => '50401', + 'compatibility' => '3' + ] + ], + 'expected_error' => null + ], + + // Filter by proxy mode. + 'Test proxy.get: filter by "status"' => [ + 'request' => [ + 'output' => ['host', 'status'], + 'proxyids' => ['get_active_defaults', 'get_passive_defaults'], + 'filter' => [ + 'status' => HOST_STATUS_PROXY_ACTIVE + ] + ], + 'expected_result' => [ + [ + 'host' => 'API test proxy.get - active', + 'status' => '5' + ] + ], + 'expected_error' => null + ], + + // Filter by Zabbix version. + 'Test proxy.get: filter by "version"' => [ + 'request' => [ + 'output' => ['host', 'version'], + 'proxyids' => ['get_version_current', 'get_version_outdated', 'get_version_unsupported'], + 'filter' => [ + 'version' => ['60000', '60200', '60400'] + ] + ], + 'expected_result' => [ + [ + 'host' => 'API test proxy.get for filter - version current', + 'version' => '60400' + ], + [ + 'host' => 'API test proxy.get for filter - version outdated', + 'version' => '60200' + ] + ], + 'expected_error' => null + ], + + // Filter by version compatibility. + 'Test proxy.get: filter by "compatibility"' => [ + 'request' => [ + 'output' => ['host', 'compatibility'], + 'proxyids' => ['get_version_current', 'get_version_outdated', 'get_version_unsupported'], + 'filter' => [ + 'compatibility' => [ZBX_PROXY_VERSION_OUTDATED, ZBX_PROXY_VERSION_UNSUPPORTED] + ] + ], + 'expected_result' => [ + [ + 'host' => 'API test proxy.get for filter - version outdated', + 'compatibility' => '2' + ], + [ + 'host' => 'API test proxy.get for filter - version unsupported', + 'compatibility' => '3' + ] + ], + 'expected_error' => null + ], + + // Search by proxy name. + 'Test proxy.get: search by "host"' => [ + 'request' => [ + 'output' => ['host'], + 'search' => [ + 'host' => 'API test proxy.get - active' + ] + ], + 'expected_result' => [ + ['host' => 'API test proxy.get - active'] + ], + 'expected_error' => null + ] + ]; + } + + /** + * Test proxy.get with all options. + * + * @dataProvider getProxyGetDataInvalid + * @dataProvider getProxyGetDataValid + */ + public function testProxy_Get(array $request, array $expected_result, ?string $expected_error): void { + // Replace ID placeholders with real IDs. + $request = self::resolveIds($request); + + foreach ($expected_result as &$proxy) { + $proxy = self::resolveIds($proxy); + } + unset($proxy); + + $result = $this->call('proxy.get', $request, $expected_error); + + if ($expected_error === null) { + $this->assertSame($expected_result, $result['result']); + } + } + + /** + * Data provider for proxy.update. Array contains invalid proxy parameters. + * + * @return array + */ + public static function getProxyUpdateDataInvalid(): array { + return [ + 'Test proxy.update: empty request' => [ + 'proxy' => [], + 'expected_error' => 'Invalid parameter "/": cannot be empty.' + ], + + // Check "proxyid". + 'Test proxy.update: missing "proxyid"' => [ + 'proxy' => [ + 'host' => 'API update proxy' + ], + 'expected_error' => 'Invalid parameter "/1": the parameter "proxyid" is missing.' + ], + 'Test proxy.update: invalid "proxyid" (empty string)' => [ + 'proxy' => [ + 'proxyid' => '' + ], + 'expected_error' => 'Invalid parameter "/1/proxyid": a number is expected.' + ], + 'Test proxy.update: invalid "proxyid" (non-existent)' => [ + 'proxy' => [ + 'proxyid' => 999999 + ], + 'expected_error' => 'No permissions to referred object or it does not exist!' + ], + 'Test proxy.update: multiple proxies with the same "proxyid"' => [ + 'proxy' => [ + ['proxyid' => 0], + ['proxyid' => 0] + ], + 'expected_error' => 'Invalid parameter "/2": value (proxyid)=(0) already exists.' + ], + + // Check "status". + 'Test proxy.update: invalid "status" (string)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'status' => 'abc' + ], + 'expected_error' => 'Invalid parameter "/1/status": an integer is expected.' + ], + 'Test proxy.update: invalid "status" (not in range)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'status' => 999999 + ], + 'expected_error' => 'Invalid parameter "/1/status": value must be one of '. + implode(', ', [HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE]).'.' + ], + + // Check "host". + 'Test proxy.update: invalid "host" (bool)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'host' => false + ], + 'expected_error' => 'Invalid parameter "/1/host": a character string is expected.' + ], + 'Test proxy.update: invalid "host" (empty string)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'host' => '' + ], + 'expected_error' => 'Invalid parameter "/1/host": cannot be empty.' + ], + 'Test proxy.update: invalid "host" (too long)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'host' => str_repeat('d', DB::getFieldLength('hosts', 'host') + 1) + ], + 'expected_error' => 'Invalid parameter "/1/host": value is too long.' + ], + + // Check "description". + 'Test proxy.update: invalid "description" (bool)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'description' => false + ], + 'expected_error' => 'Invalid parameter "/1/description": a character string is expected.' + ], + 'Test proxy.update: invalid "description" (too long)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'description' => str_repeat('d', DB::getFieldLength('hosts', 'description') + 1) + ], + 'expected_error' => 'Invalid parameter "/1/description": value is too long.' + ], + + // Check "proxy_address". + 'Test proxy.update: invalid "proxy_address" (bool)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'proxy_address' => false + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": a character string is expected.' + ], + 'Test proxy.update: invalid "proxy_address" (too long)' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults', + 'proxy_address' => str_repeat('a', DB::getFieldLength('hosts', 'proxy_address') + 1) + ], + 'expected_error' => 'Invalid parameter "/1/proxy_address": value is too long.' + ] + + // TODO: add more test cases + ]; + } + + /** + * Data provider for proxy.update. Array contains valid proxy parameters. + * + * @return array + */ + public static function getProxyUpdateDataValid(): array { + return [ + 'Test proxy.update: update single proxy without changes' => [ + 'proxy' => [ + 'proxyid' => 'update_active_defaults' + ], + 'expected_error' => null + ], + 'Test proxy.update: update multiple proxies' => [ + 'proxy' => [ + [ + 'proxyid' => 'update_active_defaults', + 'host' => 'API test proxy.update - active proxy updated', + 'description' => 'Active proxy' + ], + [ + 'proxyid' => 'update_passive_defaults', + 'host' => 'API test proxy.update - passive proxy updated', + 'description' => 'Passive proxy' + ] + ], + 'expected_error' => null + ], + + 'Test proxy.update: assign proxy to single host' => [ + 'proxy' => [ + 'proxyid' => 'update_hosts', + 'hosts' => [ + ['hostid' => 'without_proxy_1'] + ] + ], + 'expected_error' => null + ], + 'Test proxy.update: assign proxy to multiple hosts' => [ + 'proxy' => [ + 'proxyid' => 'update_hosts', + 'hosts' => [ + ['hostid' => 'without_proxy_1'], + ['hostid' => 'without_proxy_2'] + ] + ], + 'expected_error' => null + ] + + // TODO: add more test cases + ]; + } + + /** + * Test proxy.update method. + * + * @dataProvider getProxyUpdateDataInvalid + * @dataProvider getProxyUpdateDataValid + */ + public function testProxy_Update(array $proxies, ?string $expected_error): void { + // Accept single and multiple proxies just like API method. Work with multidimensional array in result. + if (!array_key_exists(0, $proxies)) { + $proxies = zbx_toArray($proxies); + } + + // Replace ID placeholders with real IDs. + foreach ($proxies as &$proxy) { + $proxy = self::resolveIds($proxy); + } + unset($proxy); + + $sql_proxies = 'SELECT NULL FROM hosts h WHERE '.dbConditionInt('h.status', [ + HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE + ]); + $old_hash_proxies = CDBHelper::getHash($sql_proxies); + + if ($expected_error === null) { + $proxyids = array_column($proxies, 'proxyid'); + $db_proxies = $this->getProxies($proxyids); + + $this->call('proxy.update', $proxies, $expected_error); + + $proxies_upd = $this->getProxies($proxyids); + + // Compare records from DB before and after API call. + foreach ($proxies as $proxy) { + $db_proxy = $db_proxies[$proxy['proxyid']]; + $proxy_upd = $proxies_upd[$proxy['proxyid']]; + + // Check name. + $this->assertNotEmpty($proxy_upd['host']); + + if (array_key_exists('host', $proxy)) { + $this->assertSame($proxy['host'], $proxy_upd['host']); + } + else { + $this->assertSame($db_proxy['host'], $proxy_upd['host']); + } + + // TODO: add more asserts + } + + // Restore proxy original data after each test. + $this->restoreProxies($db_proxies); + } + else { + // Call method and make sure it really returns the error. + $this->call('proxy.update', $proxies, $expected_error); + + // Make sure nothing has changed as well. + $this->assertSame($old_hash_proxies, CDBHelper::getHash($sql_proxies)); + } + } + + /** + * Data provider for proxy.delete. Array contains invalid proxies that are not possible to delete. + * + * @return array + */ + public static function getProxyDeleteDataInvalid(): array { + return [ + // Check proxy IDs. + 'Test proxy.delete: empty ID' => [ + 'proxyids' => [''], + 'expected_error' => 'Invalid parameter "/1": a number is expected.' + ], + 'Test proxy.delete: non-existent ID' => [ + 'proxyids' => [999999], + 'expected_error' => 'No permissions to referred object or it does not exist!' + ], + 'Test proxy.delete: with two same IDs' => [ + 'proxyids' => [0, 0], + 'expected_error' => 'Invalid parameter "/2": value (0) already exists.' + ], + + // Check if deleted proxies used to monitor hosts. + 'Test proxy.delete: used in host' => [ + 'proxyids' => ['delete_used_in_host'], + 'expected_error' => + 'Host "API test host - with proxy" is monitored by proxy "API test proxy.delete - used in hosts".' + ], + + // Check if deleted proxies used in actions. + 'Test proxy.delete: used in action' => [ + 'proxyids' => ['delete_used_in_action'], + 'expected_error' => + 'Proxy "API test proxy.delete - used in actions" is used by action "API test discovery action".' + ], + + // Check if deleted proxies used in network discovery rules. + 'Test proxy.delete: used in discovery rule' => [ + 'proxyids' => ['delete_used_in_discovery'], + 'expected_error' => 'Proxy "API test proxy.delete - used in discovery rules" is used by discovery rule "API test discovery rule".' + ] + ]; + } + + /** + * Data provider for proxy.delete. Array contains valid proxies. + * + * @return array + */ + public static function getProxyDeleteDataValid(): array { + return [ + 'Test proxy.delete: delete single' => [ + 'proxy' => ['delete_single'], + 'expected_error' => null + ], + 'Test proxy.delete: delete multiple' => [ + 'proxy' => [ + 'delete_multiple_1', + 'delete_multiple_2' + ], + 'expected_error' => null + ] + ]; + } + + /** + * Test proxy.delete method. + * + * @dataProvider getProxyDeleteDataInvalid + * @dataProvider getProxyDeleteDataValid + */ + public function testProxy_Delete(array $proxyids, ?string $expected_error): void { + // Replace ID placeholders with real IDs. + foreach ($proxyids as &$proxyid) { + if (self::isValidIdPlaceholder($proxyid)) { + $proxyid = self::$data['proxyids'][$proxyid]; + } + } + unset($proxyid); + + $sql_proxies = 'SELECT NULL FROM hosts h WHERE '.dbConditionInt('h.status', [ + HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE + ]); + $old_hash_proxies = CDBHelper::getHash($sql_proxies); + + $this->call('proxy.delete', $proxyids, $expected_error); + + if ($expected_error === null) { + $this->assertNotSame($old_hash_proxies, CDBHelper::getHash($sql_proxies)); + $this->assertEquals(0, CDBHelper::getCount( + 'SELECT h.hostid FROM hosts h WHERE '.dbConditionId('h.hostid', $proxyids) + )); + + // proxy.delete checks if given "proxyid" exists, so they need to be removed from self::$data['proxyids'] + foreach ($proxyids as $proxyid) { + $key = array_search($proxyid, self::$data['proxyids']); + if ($key !== false) { + unset(self::$data['proxyids'][$key]); + } + } + } + else { + $this->assertSame($old_hash_proxies, CDBHelper::getHash($sql_proxies)); + } + } + + /** + * Get the original proxies before update. + * + * @param array $proxyids + * + * @return array + */ + private function getProxies(array $proxyids): array { + $response = $this->call('proxy.get', [ + 'output' => ['proxyid', 'host', 'status', 'description', 'lastaccess', 'tls_connect', 'tls_accept', + 'tls_issuer', 'tls_subject', 'proxy_address', 'auto_compress', 'version', 'compatibility' + ], + 'selectHosts' => ['hostid'], + 'selectInterface' => ['useip', 'ip', 'dns', 'port'], + 'proxyids' => $proxyids, + 'preservekeys' => true, + 'nopermissions' => true + ]); + + $options = [ + 'output' => ['hostid', 'tls_psk_identity', 'tls_psk'], + 'filter' => ['hostid' => $proxyids] + ]; + $db_proxies = DBselect(DB::makeSql('hosts', $options)); + + while ($db_proxy = DBfetch($db_proxies)) { + $response['result'][$db_proxy['hostid']]['tls_psk_identity'] = $db_proxy['tls_psk_identity']; + $response['result'][$db_proxy['hostid']]['tls_psk'] = $db_proxy['tls_psk']; + } + + return $response['result']; + } + + /** + * Restore proxies to their original state. + * + * @param array $proxies + */ + private function restoreProxies(array $proxies): void { + foreach ($proxies as &$proxy) { + unset($proxy['hosts'], $proxy['interface']); + } + unset($proxy); + + $this->call('proxy.update', $proxies); + } + + /** + * Delete all created data after test. + */ + public static function clearData(): void { + // Delete actions. + CDataHelper::call('action.delete', self::$data['actionids']); + + // Delete discovery rules. + CDataHelper::call('drule.delete', self::$data['druleids']); + + // Delete hosts. + CDataHelper::call('host.delete', array_values(self::$data['hostids'])); + + // Delete host groups. + CDataHelper::call('hostgroup.delete', self::$data['groupids']); + + // Delete proxies. + $proxyids = array_values(self::$data['proxyids']); + $proxyids = array_merge($proxyids, self::$data['created']); + CDataHelper::call('proxy.delete', $proxyids); + } + + /** + * Helper method to convert placeholders to real IDs. + * + * @param array $request + * + * @return array + */ + private static function resolveIds(array $request): array { + if (array_key_exists('proxyids', $request)) { + if (is_array($request['proxyids'])) { + foreach ($request['proxyids'] as &$id) { + if (self::isValidIdPlaceholder($id)) { + $id = self::$data['proxyids'][$id]; + } + } + unset($id); + } + elseif (self::isValidIdPlaceholder($request['proxyids'])) { + $request['proxyids'] = self::$data['proxyids'][$request['proxyids']]; + } + } + elseif (array_key_exists('proxyid', $request) && self::isValidIdPlaceholder($request['proxyid'])) { + $request['proxyid'] = self::$data['proxyids'][$request['proxyid']]; + } + + if (array_key_exists('hosts', $request) && is_array($request['hosts'])) { + foreach ($request['hosts'] as &$host) { + if (is_array($host) && array_key_exists('hostid', $host) + && self::isValidIdPlaceholder($host['hostid'])) { + $host['hostid'] = self::$data['hostids'][$host['hostid']]; + } + } + unset($host); + } + + return $request; + } + + /** + * Helper method to check ID placeholder. + * + * @param $id + * + * @return bool + */ + private static function isValidIdPlaceholder($id): bool { + // Do not compare != 0 (it will not work) or !== 0 or !== '0' (avoid type check here). + return !is_array($id) && $id != '0' && $id !== '' && $id !== null && $id != 999999; } } diff --git a/ui/tests/selenium/SeleniumTests.php b/ui/tests/selenium/SeleniumTests.php index cc3a5e3df00..6d5a69bca00 100644 --- a/ui/tests/selenium/SeleniumTests.php +++ b/ui/tests/selenium/SeleniumTests.php @@ -76,8 +76,8 @@ require_once dirname(__FILE__).'/testFormAction.php'; require_once dirname(__FILE__).'/testFormAdministrationAuthenticationHttp.php'; require_once dirname(__FILE__).'/testFormAdministrationAuthenticationLdap.php'; require_once dirname(__FILE__).'/testFormAdministrationAuthenticationSaml.php'; -require_once dirname(__FILE__).'/proxies/testFormAdministrationGeneralProxies.php'; -require_once dirname(__FILE__).'/proxies/testPageAdministrationGeneralProxies.php'; +require_once dirname(__FILE__).'/proxies/testFormAdministrationProxies.php'; +require_once dirname(__FILE__).'/proxies/testPageAdministrationProxies.php'; require_once dirname(__FILE__).'/testFormAdministrationGeneralAuditLog.php'; require_once dirname(__FILE__).'/testFormAdministrationGeneralGUI.php'; require_once dirname(__FILE__).'/testFormAdministrationGeneralIconMapping.php'; @@ -278,8 +278,8 @@ class SeleniumTests { $suite->addTestSuite('testFormAdministrationAuthenticationSaml'); $suite->addTestSuite('testFormAdministrationAuthenticationHttp'); $suite->addTestSuite('testFormAdministrationAuthenticationLdap'); - $suite->addTestSuite('testFormAdministrationGeneralProxies'); - $suite->addTestSuite('testPageAdministrationGeneralProxies'); + $suite->addTestSuite('testFormAdministrationProxies'); + $suite->addTestSuite('testPageAdministrationProxies'); $suite->addTestSuite('testFormAdministrationGeneralAuditLog'); $suite->addTestSuite('testFormAdministrationGeneralGUI'); $suite->addTestSuite('testFormAdministrationGeneralIconMapping'); diff --git a/ui/tests/selenium/common/testFormHost.php b/ui/tests/selenium/common/testFormHost.php index 2f61e605c40..6b05c462432 100644 --- a/ui/tests/selenium/common/testFormHost.php +++ b/ui/tests/selenium/common/testFormHost.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../../include/CWebTest.php'; require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php'; require_once dirname(__FILE__).'/../../include/helpers/CDataHelper.php'; @@ -177,7 +178,7 @@ class testFormHost extends CWebTest { 'description' => 'Created host via API to test update functionality in host form and interfaces', 'interfaces' => $interfaces, 'groups' => $groups, - 'proxy_hostid' => 20001, + 'proxy_hostid' => 20000, 'status' => HOST_STATUS_MONITORED ], [ @@ -185,7 +186,7 @@ class testFormHost extends CWebTest { 'description' => 'Created host via API to test clone functionality in host form and interfaces 😀', 'interfaces' => $interfaces, 'groups' => $groups, - 'proxy_hostid' => 20001, + 'proxy_hostid' => 20000, 'status' => HOST_STATUS_NOT_MONITORED, 'items' => [ [ @@ -733,7 +734,7 @@ class testFormHost extends CWebTest { 'Visible name' => 'Host with all interfaces visible name', 'Host groups' => 'Zabbix servers', 'Description' => 'Added description for host with all interfaces', - 'Monitored by proxy' => 'Active proxy 1', + 'Monitored by proxy' => 'Proxy for Discovery rule', 'Enabled' => false ], 'interfaces' => [ @@ -1439,7 +1440,7 @@ class testFormHost extends CWebTest { 'Visible name' => 'testFormHost_Update Visible name', 'Host groups' => 'Zabbix servers', 'Description' => 'Created host via API to test update functionality in host form and interfaces', - 'Monitored by proxy' => 'Active proxy 2', + 'Monitored by proxy' => 'Proxy for Discovery rule', 'Enabled' => true ], 'interfaces' => [ diff --git a/ui/tests/selenium/common/testItemTest.php b/ui/tests/selenium/common/testItemTest.php index 22bd8142482..9d935da9e1b 100644 --- a/ui/tests/selenium/common/testItemTest.php +++ b/ui/tests/selenium/common/testItemTest.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once 'vendor/autoload.php'; require_once dirname(__FILE__).'/../../include/CWebTest.php'; @@ -29,7 +30,7 @@ require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php'; */ class testItemTest extends CWebTest { - const HOST_ID = 99136; // 'Test item host' monitored by 'Active proxy 1' + const HOST_ID = 99136; // 'Test item host' monitored by 'Proxy for Discovery rule' const TEMPLATE_ID = 99137; // 'Test Item Template' use PreprocessingTrait; diff --git a/ui/tests/selenium/data/data_test.sql b/ui/tests/selenium/data/data_test.sql index 63c84ad7fc0..914de15e32d 100644 --- a/ui/tests/selenium/data/data_test.sql +++ b/ui/tests/selenium/data/data_test.sql @@ -9,22 +9,6 @@ INSERT INTO media (mediaid, userid, mediatypeid, sendto, active, severity, perio -- More user scripts INSERT INTO scripts (scriptid, type, name, command, host_access, usrgrpid, groupid, description, confirmation) VALUES (4, 0,'Reboot','/sbin/shutdown -r',3,7,4,'This command reboots server.','Do you really want to reboot it?'); --- Add proxies -INSERT INTO hosts (hostid, host, status, description) VALUES (20000, 'Active proxy 1', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20001, 'Active proxy 2', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20002, 'Active proxy 3', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20003, 'Passive proxy 1', 6, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20004, 'Passive proxy 2', 6, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20005, 'Passive proxy 3', 6, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20010, 'Active proxy to delete', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (20011, 'Passive proxy to delete', 6, ''); - -INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10018,20003,1,0,1,'127.0.0.1','proxy1.zabbix.com','10051'); -INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10019,20004,1,0,1,'127.0.0.1','proxy2.zabbix.com','10333'); -INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10020,20005,1,0,0,'127.0.0.1','proxy3.zabbix.com','10051'); -INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10030,10084,1,4,1,'127.0.0.1','jmxagent.zabbix.com','10051'); -INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10040,20011,1,0,0,'127.0.0.1','proxy4.zabbix.com','10051'); - -- create an empty host "Template linkage test host" INSERT INTO hosts (hostid, host, name, status, description) VALUES (10053, 'Template linkage test host', 'Visible host for template linkage', 0, ''); INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10021,10053,1,1,1,'127.0.0.1','','10050'); @@ -33,6 +17,7 @@ INSERT INTO interface_snmp (interfaceid, version, bulk, community) values (10022 INSERT INTO interface (interfaceid,hostid,main,type,useip,ip,dns,port) values (10023,10053,1,3,1,'127.0.0.1','','623'); INSERT INTO interface (interfaceid,hostid,main,type,useip,ip,dns,port) values (10024,10053,1,4,1,'127.0.0.1','','12345'); INSERT INTO hosts_groups (hostgroupid, hostid, groupid) VALUES (90278, 10053, 4); +INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VALUES (10030,10084,1,4,1,'127.0.0.1','jmxagent.zabbix.com','10051'); -- Add regular expressions INSERT INTO regexps (regexpid, name, test_string) VALUES (20,'1_regexp_1','first test string'); @@ -69,6 +54,9 @@ INSERT INTO actions (actionid, name, eventsource, evaltype, status, esc_period) INSERT INTO actions (actionid, name, eventsource, evaltype, status, esc_period) VALUES (9,'Autoregistration action 1',2,0,0,'1h'); INSERT INTO actions (actionid, name, eventsource, evaltype, status, esc_period) VALUES (15,'Autoregistration action 2',2,0,1,'1h'); +INSERT INTO hosts (hostid, host, status, description) VALUES (20000, 'Proxy for Discovery rule', 5, ''); +INSERT INTO hosts (hostid, host, status, description) VALUES (20001, 'Proxy for Actions', 5, ''); + INSERT INTO conditions (conditionid, actionid, conditiontype, operator, value) VALUES (500, 9, 22, 3, 'DB2'); INSERT INTO conditions (conditionid, actionid, conditiontype, operator, value) VALUES (501, 9, 22, 2, 'MySQL'); INSERT INTO conditions (conditionid, actionid, conditiontype, operator, value) VALUES (502, 9, 20, 1, '20001'); @@ -345,256 +333,6 @@ INSERT INTO globalmacro (globalmacroid, macro, value, description, type) VALUES INSERT INTO globalmacro (globalmacroid, macro, value, description, type) VALUES (18,'{$Y_SECRET_MACRO_2_TEXT_REVERT}','Change value and type and revert','' , 1); INSERT INTO globalmacro (globalmacroid, macro, value, description, type) VALUES (19,'{$Z_GLOBAL_MACRO_2_RESOLVE}','Value 2 B resolved','' , 0); --- Adding records into Auditlog - --- add user --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid) VALUES (500, 1, 1411543800, 0, 0, 'User alias [Admin] name [Admin] surname [Admin]', '192.168.3.38', 0); --- -- update user --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid) VALUES (501, 1, 1411543800, 1, 0, 'User alias [Admin2] name [Admin2] surname [Admin2]', '192.168.3.38', 0); --- -- delete user --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid) VALUES (502, 1, 1411543800, 2, 0, 'User alias [Admin2] name [Admin2] surname [Admin2]', '192.168.3.38', 0); --- -- can check also block user (enable,disable) - --- -- add host --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (503, 1, 1411543800, 0, 4, '0', '192.168.3.32', 10054, 'H1'); --- --- -- update host --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (504, 1, 1411543800, 1, 4, '0', '192.168.3.32', 10054, 'H1 updated'); --- --- -- delete host --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (505, 1, 1411543800, 2, 4, '0', '192.168.3.32', 10054, 'H1 updated'); --- --- -- enable host, hosts.status: 1 => 0 --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (506, 1, 1411543800, 1, 4, '0', '192.168.3.32', 10054, 'H1 updated'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (500, 506, 'hosts', 'status', '1', '0'); --- --- -- disable host, hosts.status: 0 => 1 --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (507, 1, 1411543800, 1, 4, '0', '192.168.3.32', 10054, 'H1 updated'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (501, 507, 'hosts', 'status', '0', '1'); --- --- -- add hostgroup --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (508, 1, 1411543800, 0, 14, '0', '192.168.3.32', 6, 'HG1'); --- --- -- update hostgroup --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (509, 1, 1411543800, 1, 14, '0', '192.168.3.32', 6, 'HG1 updated'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (502, 509, 'groups', 'name', 'HG1', 'HG1 updated'); --- --- -- delete hostgroup --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (510, 1, 1411543800, 2, 14, '0', '192.168.3.32', 6, 'HG1 updated'); --- --- -- add item --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (511, 1, 1411543800, 0, 15, '0', '192.168.3.32', 22500, 'Item added'); --- --- -- update item --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (512, 1, 1411543800, 1, 15, '0', '192.168.3.32', 22500, 'Item updated'); --- --- -- disable item --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (513, 1, 1411543800, 1, 15, '0', '192.168.3.32', 22500, 'H1 updated:test_item'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (503, 513, 'items', 'status', '0', '1'); --- --- -- enable item --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (514, 1, 1411543800, 1, 15, '0', '192.168.3.32', 22500, 'H1 updated:test_item'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (504, 514, 'items', 'status', '1', '0'); --- --- -- delete item --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (515, 1, 1411543800, 2, 15, 'Item [agent.version] [22500] Host [H1]', '192.168.3.32', 22500, 'Item deleted'); --- --- -- add trigger --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (516, 1, 1411543800, 0, 13, '0', '192.168.3.32', 13000, 'Trigger1'); --- --- -- update trigger --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (517, 1, 1411543800, 0, 13, '0', '192.168.3.32', 13000, 'Trigger1'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (505, 517, '', 'description', 'Trigger1', 'Trigger1 updated'); --- --- -- disable trigger --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (518, 1, 1411543800, 1, 13, '0', '192.168.3.32', 13000, 'H1 updated:Trigger1'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (506, 518, 'triggers', 'status', '0', '1'); --- --- -- enable trigger --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (519, 1, 1411543800, 1, 13, '0', '192.168.3.32', 13000, 'H1 updated:Trigger1'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (507, 519, 'triggers', 'status', '1', '0'); - --- TODO: delete trigger - --- -- add action --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (520, 1, 1411543800, 0, 5, 'Name: Action1', '192.168.3.32', 0, ''); --- --- -- update action --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (521, 1, 1411543800, 1, 5, 'Name: Action1 updated', '192.168.3.32', 0, ''); --- --- -- disable action --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (522, 1, 1411543800, 1, 5, 'Actions [11] disabled', '192.168.3.32', 0, ''); --- --- -- enable action --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (523, 1, 1411543800, 1, 5, 'Actions [11] enabled', '192.168.3.32', 0, ''); --- --- -- delete action --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (524, 1, 1411543800, 2, 5, 'Actions [11] deleted', '192.168.3.32', 11, 'Action deleted'); --- --- -- add graph --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (530, 1, 1411543800, 0, 6, 'Graph [graph1]', '192.168.3.32', 0, ''); --- --- -- update graph --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (531, 1, 1411543800, 1, 6, 'Graph [graph1 updated]', '192.168.3.32', 0, ''); --- --- -- delete graph, no records in the DB for this operation --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (532, 1, 1411543800, 2, 6, 'Graph ID [386] Graph [graph1]', '192.168.3.32', 0, ''); --- --- -- add image --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (533, 1, 1411543800, 0, 16, 'Image [1image] added', '192.168.3.32', 0, ''); --- --- -- update image --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (534, 1, 1411543800, 1, 16, 'Image [1image] updated', '192.168.3.32', 0, ''); --- --- -- delete image --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (535, 1, 1411543800, 2, 16, 'Image [1image] updated', '192.168.3.32', 0, ''); --- --- -- add globalmacro --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (536, 1, 1411543800, 0, 29, '0', '192.168.3.32', 9, '{$B} ⇒ abcd'); --- --- -- update globalmacro --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (537, 1, 1411543800, 1, 29, '0', '192.168.3.32', 9, '{$B} ⇒ xyz'); --- --- -- delete globalmacro --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (538, 1, 1411543800, 2, 29, '0', '192.168.3.32', 9, 'Array ⇒ xyz'); --- --- -- add valuemap --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (539, 1, 1411543800, 0, 17, 'Value map [testvaluemap1]', '192.168.3.32', 0, ''); --- --- -- update valuemap --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (540, 1, 1411543800, 1, 17, '0', '192.168.3.32', 0, ''); --- --- -- delete valuemap --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (541, 1, 1411543800, 2, 17, '0', '192.168.3.32', 0, ''); --- --- -- add maint period --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (542, 1, 1411543800, 0, 27, 'Name: Maintenance1', '192.168.3.32', 0, ''); --- --- -- update maint period --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (543, 1, 1411543800, 1, 27, 'Name: Maintenance2', '192.168.3.32', 0, ''); --- --- -- delete maint period --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (544, 1, 1411543800, 2, 27, 'Id [3] Name [Maintenance2]', '192.168.3.32', 0, ''); --- --- -- add service --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (545, 1, 1411543800, 0, 18, 'Name [service1] id [1]', '192.168.3.32', 0, ''); --- --- -- update service --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (546, 1, 1411543800, 1, 18, 'Name [service1] id [1]', '192.168.3.32', 0, ''); --- --- -- delete service --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (547, 1, 1411543800, 2, 18, 'Name [service1] id [1]', '192.168.3.32', 0, ''); --- --- -- add DRule --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (548, 1, 1411543800, 0, 23, '[10] drule1', '192.168.3.32', 0, ''); --- --- -- update DRule --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (549, 1, 1411543800, 1, 23, '[10] drule1-new', '192.168.3.32', 0, ''); --- --- -- delete DRule --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (550, 1, 1411543800, 2, 23, 'Discovery rule [10] drule1-new deleted', '192.168.3.32', 0, ''); --- --- -- disable DRule --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (551, 1, 1411543800, 1, 23, 'Discovery rule [10] disabled', '192.168.3.32', 0, ''); --- --- -- enable DRule --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (552, 1, 1411543800, 1, 23, 'Discovery rule [10] enabled', '192.168.3.32', 0, ''); --- --- -- add map --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (553, 1, 1411543800, 0, 19, 'Test Map1', '192.168.3.32', 20, ''); --- --- -- update map --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (554, 1, 1411543800, 1, 19, 'Test Map2', '192.168.3.32', 20, ''); --- --- -- delete map --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (555, 1, 1411543800, 2, 19, '0', '192.168.3.32', 20, 'Test Map2'); --- --- -- add media type --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (556, 1, 1411543800, 0, 3, 'Media type [Media1]', '192.168.3.32', 0, ''); --- --- -- update media type --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (557, 1, 1411543800, 1, 3, 'Media type [Media2]', '192.168.3.32', 0, ''); --- --- -- disable media type --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (558, 1, 1411543800, 1, 3, 'Media type [Media2]', '192.168.3.32', 0, ''); --- --- -- enable media type --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (559, 1, 1411543800, 1, 3, 'Media type [Media2]', '192.168.3.32', 0, ''); --- --- -- delete media type --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (560, 1, 1411543800, 2, 3, 'Media type [Media2]', '192.168.3.32', 0, ''); --- --- -- add proxy --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (564, 1, 1411543800, 0, 26, '[test_proxy1] [10054]', '192.168.3.32', 0, ''); --- --- -- update proxy --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (565, 1, 1411543800, 1, 26, '[test_proxy2] [10054]', '192.168.3.32', 0, ''); --- --- -- disable proxy - this will disable all hosts that are monitored by this proxy --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (566, 1, 1411543800, 1, 4, '0', '192.168.3.32', 10053, 'Test host'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (510, 566, 'hosts', 'status', '0', '1'); --- --- -- enable proxy - this will enable all hosts that are monitored by this proxy --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (567, 1, 1411543800, 1, 4, '0', '192.168.3.32', 10053, 'Test host'); --- INSERT INTO auditlog_details (auditdetailid, auditid, table_name, field_name, oldvalue, newvalue) VALUES (511, 567, 'hosts', 'status', '1', '0'); --- --- -- delete proxy --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (568, 1, 1411543800, 1, 4, '0', '192.168.3.32', 10053, 'Test host'); --- --- -- add web scenario --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (569, 1, 1411543800, 0, 22, 'Web scenario [Scenario1] [1] Host [Test host]', '192.168.3.32', 0, ''); --- --- -- update web scenario --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (570, 1, 1411543800, 1, 22, 'Web scenario [Scenario1] [1] Host [Test host]', '192.168.3.32', 0, ''); --- --- -- disable scenario --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (571, 1, 1411543800, 6, 22, 'Web scenario [Scenario1] [1] Host [Test host] disabled', '192.168.3.32', 0, ''); --- --- -- enable scenario --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (572, 1, 1411543800, 5, 22, 'Web scenario [Scenario1] [1] Host [Test host] activated', '192.168.3.32', 0, ''); --- --- -- delete scenario --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (573, 1, 1411543800, 2, 22, 'Web scenario [Scenario1] [1] Host [Test host]', '192.168.3.32', 0, ''); --- --- -- add screen --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (574, 1, 1411543800, 0, 20, 'Name [screen1]', '192.168.3.32', 0, ''); --- --- -- update screen --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (575, 1, 1411543800, 1, 20, 'Name [screen1]', '192.168.3.32', 0, ''); --- --- -- delete screen --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (576, 1, 1411543800, 2, 20, '0', '192.168.3.32', 24, 'screen1'); --- --- -- add script --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (577, 1, 1411543800, 0, 25, 'Name [script1] id [4]', '192.168.3.32', 0, ''); --- --- -- update script --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (578, 1, 1411543800, 1, 25, 'Name [script1] id [4]', '192.168.3.32', 0, ''); --- --- -- delete script --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (579, 1, 1411543800, 2, 25, 'Script [4]', '192.168.3.32', 0, ''); --- --- -- add slideshow --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (580, 1, 1411543800, 0, 24, 'Name Slideshow_4', '192.168.3.32', 0, ''); --- --- -- update slideshow --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (581, 1, 1411543800, 1, 24, 'Name Slideshow_4', '192.168.3.32', 0, ''); --- --- -- delete slideshow --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (582, 1, 1411543800, 2, 24, 'Name Slideshow_4', '192.168.3.32', 0, ''); --- --- -- add template --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (583, 1, 1411543800, 0, 30, '', '192.168.3.32', 10055, 'Test_template1'); --- --- -- update template --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (584, 1, 1411543800, 1, 30, '', '192.168.3.32', 10055, 'Test_template1'); --- --- -- delete template --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (585, 1, 1411543800, 2, 30, '0', '192.168.3.32', 10055, 'Test_template1'); --- --- -- updating record "Configuration of Zabbix" in the auditlog --- INSERT INTO auditlog (auditid, userid, clock, action, resourcetype, note, ip, resourceid, resourcename) VALUES (700, 1, 1411543800, 1, 2, 'Default theme "originalblue".; Event acknowledges "1".; Dr...', '192.168.3.32', 0, ''); - -- adding test data to the 'alerts' table for testing Audit->Actions report INSERT INTO events (eventid, source, object, objectid, clock, value, acknowledged, ns) VALUES (1, 0, 0, 13545, 1329724790, 1, 0, 0); @@ -2016,16 +1754,6 @@ INSERT INTO task (taskid, type, status, clock, ttl, proxy_hostid) VALUES (2, 4, INSERT INTO task_acknowledge (taskid, acknowledgeid) VALUES (1, 1); INSERT INTO task_acknowledge (taskid, acknowledgeid) VALUES (2, 2); --- Hosts with proxies for Hosts filtering test -INSERT INTO hosts (hostid, host, status, description) VALUES (99051, 'Proxy_1 for filter', 5, ''); -INSERT INTO hosts (hostid, host, status, description) VALUES (99052, 'Proxy_2 for filter', 5, ''); -INSERT INTO hosts (hostid, proxy_hostid, host, name, status, description) VALUES (99053, 99051, 'Host_1 with proxy', 'Host_1 with proxy', 0, ''); -INSERT INTO hosts (hostid, proxy_hostid, host, name, status, description) VALUES (99054, 99052, 'Host_2 with proxy', 'Host_2 with proxy', 0, ''); -INSERT INTO interface (interfaceid, hostid, type, ip, useip, port, main) VALUES (55031, 99053, 1, '127.0.0.1', 1, '10050', 1); -INSERT INTO interface (interfaceid, hostid, type, ip, useip, port, main) VALUES (55032, 99054, 1, '127.0.0.1', 1, '10050', 1); -INSERT INTO hosts_groups (hostgroupid, hostid, groupid) VALUES (99911, 99053, 4); -INSERT INTO hosts_groups (hostgroupid, hostid, groupid) VALUES (99912, 99054, 4); - -- Dashboard for problem hosts widget INSERT INTO dashboard (dashboardid, name, userid, private) VALUES (1000, 'Dashboard for Problem hosts widget', 1, 1); INSERT INTO dashboard_page (dashboard_pageid, dashboardid) VALUES (12345, 1000); @@ -2235,7 +1963,7 @@ INSERT INTO widget_field (widgetid, widget_fieldid, type, name, value_int) VALUE INSERT INTO widget_field (widgetid, widget_fieldid, type, name, value_int) VALUES (10009, 80138, 0, 'layout', 1); -- testFormItemTest -INSERT INTO hosts (hostid, proxy_hostid, host, name, status, description) VALUES (99136, 20000, 'Test item host', 'Test item host', 0, 'Test item host for testing items'); +INSERT INTO hosts (hostid, host, name, status, description) VALUES (99136, 'Test item host', 'Test item host', 0, 'Test item host for testing items'); INSERT INTO hosts_groups (hostgroupid, hostid, groupid) VALUES (100999, 99136, 4); INSERT INTO interface (interfaceid, hostid, type, ip, dns, useip, port, main, available) VALUES (55070, 99136, 1, '127.0.0.1', 'Test1', '1', '10050', '1', 0); diff --git a/ui/tests/selenium/data/sources/Proxies.php b/ui/tests/selenium/data/sources/Proxies.php new file mode 100644 index 00000000000..42041bbd46e --- /dev/null +++ b/ui/tests/selenium/data/sources/Proxies.php @@ -0,0 +1,259 @@ +<?php +/* +** Zabbix +** Copyright (C) 2001-2022 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. +**/ + + +class Proxies { + + /** + * Names of enabled hosts, monitored by proxies. + * + * @var array + */ + private static $enabled_hosts = [ + 'enabled_host1', + 'enabled_host2', + 'enabled_host3', + 'enabled_host4', + 'enabled_host5', + 'enabled_host6', + 'enabled_host7', + 'enabled_host8' + ]; + + /** + * Names of disabled hosts, monitored by proxies. + * + * @var array + */ + private static $disabled_hosts = [ + 'disabled_host1', + 'disabled_host2', + 'disabled_host3', + 'disabled_host4', + 'disabled_host5', + 'disabled_host6', + 'disabled_host7', + 'disabled_host8' + ]; + + /** + * Names of active proxies for proxy tests. + * + * @var array + */ + private static $active_proxies = [ + 'active_proxy1', + 'active_proxy2', + 'active_proxy3', + 'active_proxy4', + 'active_proxy5', + 'active_proxy6', + 'active_proxy7', + 'active_current', + 'active_unknown', + 'Active proxy 1', + 'Active proxy 2', + 'Active proxy 3', + 'Active proxy to delete', + 'Proxy_1 for filter', + 'Proxy_2 for filter' + ]; + + /** + * Names of passive proxies for proxy tests. + * + * @var array + */ + private static $passive_proxies = [ + 'passive_proxy1', + 'passive_proxy2', + 'passive_proxy3', + 'passive_proxy4', + 'passive_proxy5', + 'passive_proxy6', + 'passive_proxy7', + 'passive_outdated', + 'passive_unsupported', + 'Passive proxy 1', + 'Passive proxy 2', + 'Passive proxy 3', + 'Passive proxy to delete' + ]; + + /** + * Preparing proxies and hosts. + */ + public static function load() { + // Create host group. + $hostgroups = CDataHelper::call('hostgroup.create', [['name' => 'HG_for_proxies']]); + $hostgroupid = $hostgroups['groupids'][0]; + + // Create enabled hosts. + $enabled_hosts_data = []; + foreach (self::$enabled_hosts as $host) { + $enabled_hosts_data[] = [ + 'host' => $host, + 'groups' => [['groupid' => $hostgroupid]], + 'status' => 0 + ]; + } + + $enabled_hosts = CDataHelper::call('host.create', $enabled_hosts_data); + $enabled_hostids = CDataHelper::getIds('host'); + + // Create hosts fo filtering scenario. + CDataHelper::call('host.create', [ + ['host' => 'Host_1 with proxy', 'groups' => [['groupid' => 4]]], + ['host' => 'Host_2 with proxy', 'groups' => [['groupid' => 4]]] + ]); + $filter_hostids = CDataHelper::getIds('host'); + + // Disabled hosts data. + $disabled_hosts_data = []; + foreach (self::$disabled_hosts as $host) { + $disabled_hosts_data[] = [ + 'host' => $host, + 'groups' => [['groupid' => $hostgroupid]], + 'status' => 1 + ]; + } + $disabled_hosts = CDataHelper::call('host.create', $disabled_hosts_data); + $disabled_hostids = CDataHelper::getIds('host'); + + // Create active proxies. + $active_proxy_data = []; + foreach (self::$active_proxies as $proxy) { + $active_proxy_data[] = [ + 'host' => $proxy, + 'status' => 5 + ]; + } + + $active_proxies = CDataHelper::call('proxy.create', $active_proxy_data); + $active_proxyids = CDataHelper::getIds('host'); + + // Create passive proxies. + $passive_proxy_data = []; + foreach (self::$passive_proxies as $proxy) { + $passive_proxy_data[] = [ + 'host' => $proxy, + 'status' => 6, + 'interface' => [ + 'ip'=> '127.0.0.1', + 'dns' => '', + 'useip' => '1', + 'port' => '10051' + ] + ]; + } + + $passive_proxies = CDataHelper::call('proxy.create', $passive_proxy_data); + $passive_proxyids = CDataHelper::getIds('host'); + + // Add hosts to proxies. + CDataHelper::call('proxy.update', [ + [ + 'proxyid' => $active_proxyids['active_proxy1'], + 'hosts' => [ + ['hostid' => $enabled_hostids['enabled_host1']] + ] + ], + [ + 'proxyid' => $passive_proxyids['passive_proxy1'], + 'hosts' => [ + ['hostid' => $disabled_hostids['disabled_host1']] + ] + ], + [ + 'proxyid' => $active_proxyids['active_proxy2'], + 'hosts' => [ + ['hostid' => $enabled_hostids['enabled_host2']], + ['hostid' => $enabled_hostids['enabled_host3']] + ] + ], + [ + 'proxyid' => $passive_proxyids['passive_proxy2'], + 'hosts' => [ + ['hostid' => $enabled_hostids['enabled_host4']], + ['hostid' => $enabled_hostids['enabled_host5']] + ] + ], + [ + 'proxyid' => $active_proxyids['active_proxy3'], + 'hosts' => [ + ['hostid' => $disabled_hostids['disabled_host2']], + ['hostid' => $disabled_hostids['disabled_host3']] + ] + ], + [ + 'proxyid' => $passive_proxyids['passive_proxy3'], + 'hosts' => [ + ['hostid' => $disabled_hostids['disabled_host4']], + ['hostid' => $disabled_hostids['disabled_host5']] + ] + ], + [ + 'proxyid' => $active_proxyids['active_proxy4'], + 'hosts' => [ + ['hostid' => $enabled_hostids['enabled_host6']], + ['hostid' => $disabled_hostids['disabled_host6']] + ] + ], + [ + 'proxyid' => $passive_proxyids['passive_proxy4'], + 'hosts' => [ + ['hostid' => $enabled_hostids['enabled_host7']], + ['hostid' => $enabled_hostids['enabled_host8']], + ['hostid' => $disabled_hostids['disabled_host7']], + ['hostid' => $disabled_hostids['disabled_host8']] + ] + ], + [ + 'proxyid' => $active_proxyids['Active proxy 1'], + 'hosts' => [ + ['hostid' => 99136] // Test item host. + ] + ], + [ + 'proxyid' => $active_proxyids['Proxy_1 for filter'], + 'hosts' => [ + ['hostid' => $filter_hostids['Host_1 with proxy']] + ] + ], + [ + 'proxyid' => $active_proxyids['Proxy_2 for filter'], + 'hosts' => [ + ['hostid' => $filter_hostids['Host_2 with proxy']] + ] + ] + ]); + + /** + * Add proxies versions. + * Supported version "60400" is hardcoded one time, so that no need to change it, + * even if newer versions of Zabbix are released. + */ + DBexecute('UPDATE host_rtdata SET version=60400, compatibility=1 WHERE hostid='.zbx_dbstr($active_proxyids['active_current'])); + DBexecute('UPDATE host_rtdata SET version=60200, compatibility=2 WHERE hostid='.zbx_dbstr($passive_proxyids['passive_outdated'])); + DBexecute('UPDATE host_rtdata SET version=0, compatibility=0 WHERE hostid='.zbx_dbstr($active_proxyids['active_unknown'])); + DBexecute('UPDATE host_rtdata SET version=50401, compatibility=3 WHERE hostid='.zbx_dbstr($passive_proxyids['passive_unsupported'])); + DBexecute('UPDATE config SET server_status='.zbx_dbstr('{"version": "6.4.0alpha1"}')); + } +} diff --git a/ui/tests/selenium/hosts/testFormHostConfiguration.php b/ui/tests/selenium/hosts/testFormHostConfiguration.php index d535cf43d30..72e00701d96 100644 --- a/ui/tests/selenium/hosts/testFormHostConfiguration.php +++ b/ui/tests/selenium/hosts/testFormHostConfiguration.php @@ -22,7 +22,7 @@ require_once dirname(__FILE__).'/../common/testFormHost.php'; /** - * @dataSource DiscoveredHosts + * @dataSource DiscoveredHosts, Proxies * * @backup hosts * diff --git a/ui/tests/selenium/hosts/testFormHostMonitoring.php b/ui/tests/selenium/hosts/testFormHostMonitoring.php index b06544c2c4f..793925ea1ca 100644 --- a/ui/tests/selenium/hosts/testFormHostMonitoring.php +++ b/ui/tests/selenium/hosts/testFormHostMonitoring.php @@ -18,10 +18,11 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../common/testFormHost.php'; /** - * @dataSource DiscoveredHosts + * @dataSource DiscoveredHosts, Proxies * * @backup hosts * diff --git a/ui/tests/selenium/hosts/testFormHostStandalone.php b/ui/tests/selenium/hosts/testFormHostStandalone.php index 02187fb42d1..c63c499d74b 100644 --- a/ui/tests/selenium/hosts/testFormHostStandalone.php +++ b/ui/tests/selenium/hosts/testFormHostStandalone.php @@ -18,10 +18,11 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../common/testFormHost.php'; /** - * @dataSource DiscoveredHosts + * @dataSource DiscoveredHosts, Proxies * * @backup hosts * diff --git a/ui/tests/selenium/items/testFormTestItem.php b/ui/tests/selenium/items/testFormTestItem.php index cf44e5eba12..dc663970428 100644 --- a/ui/tests/selenium/items/testFormTestItem.php +++ b/ui/tests/selenium/items/testFormTestItem.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../common/testItemTest.php'; /** diff --git a/ui/tests/selenium/items/testFormTestItemPrototype.php b/ui/tests/selenium/items/testFormTestItemPrototype.php index bad0fa80c71..cf15739313e 100644 --- a/ui/tests/selenium/items/testFormTestItemPrototype.php +++ b/ui/tests/selenium/items/testFormTestItemPrototype.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../common/testItemTest.php'; /** diff --git a/ui/tests/selenium/lld/testFormTestLowLevelDiscovery.php b/ui/tests/selenium/lld/testFormTestLowLevelDiscovery.php index 5720758061c..0cdc4098c73 100644 --- a/ui/tests/selenium/lld/testFormTestLowLevelDiscovery.php +++ b/ui/tests/selenium/lld/testFormTestLowLevelDiscovery.php @@ -18,11 +18,14 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../common/testItemTest.php'; /** * "Test item" function tests. * + * @dataSource Proxies + * * @backup items */ class testFormTestLowLevelDiscovery extends testItemTest{ diff --git a/ui/tests/selenium/proxies/testFormAdministrationGeneralProxies.php b/ui/tests/selenium/proxies/testFormAdministrationProxies.php index 091b393d006..42b9adb19b5 100644 --- a/ui/tests/selenium/proxies/testFormAdministrationGeneralProxies.php +++ b/ui/tests/selenium/proxies/testFormAdministrationProxies.php @@ -18,17 +18,20 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__) . '/../../include/CWebTest.php'; require_once dirname(__FILE__).'/../../include/helpers/CDataHelper.php'; /** * Test for checking Proxy host form. * + * @dataSource Proxies + * * @onBefore prepareProxyData * * @backup hosts */ -class testFormAdministrationGeneralProxies extends CWebTest { +class testFormAdministrationProxies extends CWebTest { private $sql = 'SELECT * FROM hosts ORDER BY hostid'; @@ -36,7 +39,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { private static $change_active_proxy = 'Active proxy for refresh cancel simple update'; private static $change_passive_proxy = 'Passive proxy for refresh cancel simple update'; private static $delete_proxy_with_hosts = 'Proxy_2 for filter'; - private static $delete_proxy_with_discovery_rule = 'Passive proxy 1'; + private static $delete_proxy_with_discovery_rule = 'Proxy for Discovery rule'; /** * Attach MessageBehavior to the test. @@ -477,7 +480,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getLayoutData */ - public function testFormAdministrationGeneralProxies_Layout($data) { + public function testFormAdministrationProxies_Layout($data) { $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); $this->query('button:Create proxy')->one()->waitUntilClickable()->click(); $dialog = COverlayDialogElement::find()->one()->waitUntilReady(); @@ -1026,14 +1029,14 @@ class testFormAdministrationGeneralProxies extends CWebTest { * * @backupOnce hosts */ - public function testFormAdministrationGeneralProxies_Create($data) { + public function testFormAdministrationProxies_Create($data) { $this->checkForm($data); } /** * @dataProvider getUpdateProxyData */ - public function testFormAdministrationGeneralProxies_Update($data) { + public function testFormAdministrationProxies_Update($data) { $this->checkForm($data, true); } @@ -1089,7 +1092,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { $this->page->waitUntilReady(); if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) { - $this->assertMessage(TEST_BAD, null, $data['error']); + $this->assertMessage(TEST_BAD, ($update ? 'Cannot update proxy' : 'Cannot add proxy'), $data['error']); // Check that DB hash is not changed. $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); @@ -1161,7 +1164,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getActivePassiveProxyData */ - public function testFormAdministrationGeneralProxies_RefreshConfiguration($data) { + public function testFormAdministrationProxies_RefreshConfiguration($data) { $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); $this->query('link', $data['proxy'])->one()->waitUntilClickable()->click(); @@ -1192,7 +1195,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getActivePassiveProxyData */ - public function testFormAdministrationGeneralProxies_Clone($data) { + public function testFormAdministrationProxies_Clone($data) { $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); $this->query('link', $data['proxy'])->one()->waitUntilClickable()->click(); @@ -1231,6 +1234,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { } /** + * Function for returning interface fields. * * @param COverlayDialogElement $dialog proxy form overlay dialog * @param array $fields passive proxy interface fields @@ -1249,7 +1253,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getActivePassiveProxyData */ - public function testFormAdministrationGeneralProxies_SimpleUpdate($data) { + public function testFormAdministrationProxies_SimpleUpdate($data) { $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); $this->query('link', $data['proxy'])->one()->waitUntilClickable()->click(); @@ -1302,7 +1306,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getCancelData */ - public function testFormAdministrationGeneralProxies_Cancel($data) { + public function testFormAdministrationProxies_Cancel($data) { $old_hash = CDBHelper::getHash($this->sql); $fields = [ @@ -1373,7 +1377,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { [ 'expected' => TEST_BAD, 'proxy' => self::$delete_proxy_with_discovery_rule, - 'error' => "Proxy \"Passive proxy 1\" is used by discovery rule \"Discovery rule for update\"." + 'error' => "Proxy \"Proxy for Discovery rule\" is used by discovery rule \"Discovery rule for update\"." ] ] ]); @@ -1382,7 +1386,7 @@ class testFormAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getProxyDeleteData */ - public function testFormAdministrationGeneralProxies_Delete($data) { + public function testFormAdministrationProxies_Delete($data) { if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) { $old_hash = CDBHelper::getHash($this->sql); } diff --git a/ui/tests/selenium/proxies/testPageAdministrationGeneralProxies.php b/ui/tests/selenium/proxies/testPageAdministrationProxies.php index 4fb2b82cace..a6a56373fcc 100644 --- a/ui/tests/selenium/proxies/testPageAdministrationGeneralProxies.php +++ b/ui/tests/selenium/proxies/testPageAdministrationProxies.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__) . '/../../include/CWebTest.php'; require_once dirname(__FILE__).'/../traits/TableTrait.php'; require_once dirname(__FILE__).'/../../include/helpers/CDataHelper.php'; @@ -25,54 +26,14 @@ require_once dirname(__FILE__).'/../../include/helpers/CDataHelper.php'; /** * Test for checking Proxies page. * + * @dataSource Proxies + * * @backup hosts */ -class testPageAdministrationGeneralProxies extends CWebTest { +class testPageAdministrationProxies extends CWebTest { private $sql = 'SELECT * FROM hosts ORDER BY hostid'; - private static $enabled_hosts = [ - 'enabled_host1', - 'enabled_host2', - 'enabled_host3', - 'enabled_host4', - 'enabled_host5', - 'enabled_host6', - 'enabled_host7', - 'enabled_host8' - ]; - - private static $disabled_hosts = [ - 'disabled_host1', - 'disabled_host2', - 'disabled_host3', - 'disabled_host4', - 'disabled_host5', - 'disabled_host6', - 'disabled_host7', - 'disabled_host8' - ]; - - private static $active_proxies = [ - 'active_proxy1', - 'active_proxy2', - 'active_proxy3', - 'active_proxy4', - 'active_proxy5', - 'active_proxy6', - 'active_proxy7' - ]; - - private static $passive_proxies = [ - 'passive_proxy1', - 'passive_proxy2', - 'passive_proxy3', - 'passive_proxy4', - 'passive_proxy5', - 'passive_proxy6', - 'passive_proxy7' - ]; - use TableTrait; /** @@ -84,159 +45,100 @@ class testPageAdministrationGeneralProxies extends CWebTest { return [CMessageBehavior::class]; } - /** - * Preparing proxies and hosts for test. - */ - public function prepareProxyHostsData() { - // Create enabled hosts. - $enabled_hosts_data = []; - foreach (self::$enabled_hosts as $host) { - $enabled_hosts_data[] = [ - 'host' => $host, - 'groups' => [['groupid' => 4]], - 'status' => 0 - ]; - } + public function testPageAdministrationProxies_Layout() { + $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); + $this->page->assertTitle('Configuration of proxies'); + $this->page->assertHeader('Proxies'); + $form = $this->query('name:zbx_filter')->waitUntilPresent()->asForm()->one(); - $enabled_hosts = CDataHelper::call('host.create', $enabled_hosts_data); - $this->assertArrayHasKey('hostids', $enabled_hosts); - $enabled_hostids = CDataHelper::getIds('host'); - - // Disabled hosts data. - $disabled_hosts_data = []; - foreach (self::$disabled_hosts as $host) { - $disabled_hosts_data[] = [ - 'host' => $host, - 'groups' => [['groupid' => 4]], - 'status' => 1 - ]; - } - $disabled_hosts = CDataHelper::call('host.create', $disabled_hosts_data); - $this->assertArrayHasKey('hostids', $disabled_hosts); - $disabled_hostids = CDataHelper::getIds('host'); - - // Create active proxies. - $active_proxy_data = []; - foreach (self::$active_proxies as $proxy) { - $active_proxy_data[] = [ - 'host' => $proxy, - 'status' => 5 - ]; - } + // Check default fields and values. + $fields = [ + 'Name' => [''], + 'Mode' => ['Any', 'Active', 'Passive'], + 'Version' => ['Any', 'Current', 'Outdated'] + ]; - $active_proxies = CDataHelper::call('proxy.create', $active_proxy_data); - $this->assertArrayHasKey('proxyids', $active_proxies); - $active_proxyids = CDataHelper::getIds('host'); - - // Create passive proxies. - $passive_proxy_data = []; - foreach (self::$passive_proxies as $proxy) { - $passive_proxy_data[] = [ - 'host' => $proxy, - 'status' => 6, - 'interface' => [ - 'ip'=> '127.0.0.1', - 'dns' => '', - 'useip' => '1', - 'port' => '10051' - ] - ]; + foreach ($fields as $field => $value) { + $this->assertEquals($value[0], $form->getField($field)->getValue()); } - $passive_proxies = CDataHelper::call('proxy.create', $passive_proxy_data); - $this->assertArrayHasKey('proxyids', $passive_proxies); - $passive_proxyids = CDataHelper::getIds('host'); - - // Add hosts to proxies. - CDataHelper::call('proxy.update', [ - [ - 'proxyid' => $active_proxyids['active_proxy1'], - 'hosts' => [ - ['hostid' => $enabled_hostids['enabled_host1']] - ] - ], - [ - 'proxyid' => $passive_proxyids['passive_proxy1'], - 'hosts' => [ - ['hostid' => $disabled_hostids['disabled_host1']] - ] - ], - [ - 'proxyid' => $active_proxyids['active_proxy2'], - 'hosts' => [ - ['hostid' => $enabled_hostids['enabled_host2']], - ['hostid' => $enabled_hostids['enabled_host3']] - ] - ], - [ - 'proxyid' => $passive_proxyids['passive_proxy2'], - 'hosts' => [ - ['hostid' => $enabled_hostids['enabled_host4']], - ['hostid' => $enabled_hostids['enabled_host5']] - ] - ], - [ - 'proxyid' => $active_proxyids['active_proxy3'], - 'hosts' => [ - ['hostid' => $disabled_hostids['disabled_host2']], - ['hostid' => $disabled_hostids['disabled_host3']] - ] - ], - [ - 'proxyid' => $passive_proxyids['passive_proxy3'], - 'hosts' => [ - ['hostid' => $disabled_hostids['disabled_host4']], - ['hostid' => $disabled_hostids['disabled_host5']] - ] - ], - [ - 'proxyid' => $active_proxyids['active_proxy4'], - 'hosts' => [ - ['hostid' => $enabled_hostids['enabled_host6']], - ['hostid' => $disabled_hostids['disabled_host6']] - ] - ], - [ - 'proxyid' => $passive_proxyids['passive_proxy4'], - 'hosts' => [ - ['hostid' => $enabled_hostids['enabled_host7']], - ['hostid' => $enabled_hostids['enabled_host8']], - ['hostid' => $disabled_hostids['disabled_host7']], - ['hostid' => $disabled_hostids['disabled_host8']] - ] - ] - ]); - } - - public function testPageAdministrationGeneralProxies_Layout() { - $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); - $this->page->assertTitle('Configuration of proxies'); - $this->page->assertHeader('Proxies'); + array_shift($fields); + foreach ($fields as $radio => $labels) { + $this->assertEquals($labels, $form->getField($radio)->asSegmentedRadio()->getLabels()->asText()); + } // Check filter collapse/expand. foreach ([true, false] as $status) { - $this->assertEquals($status, $this->query('xpath://div[contains(@class, "ui-tabs-panel")]') - ->one()->isVisible() - ); + $this->assertEquals($status, $this->query('xpath://div[contains(@class, "ui-tabs-panel")]')->one()->isVisible()); $this->query('xpath://a[contains(@class, "filter-trigger")]')->one()->click(); } $table = $this->query('class:list-table')->asTable()->one()->waitUntilPresent(); - $this->assertEquals(['', 'Name', 'Mode', 'Encryption', 'Compression', 'Last seen (age)', 'Host count', 'Item count', - 'Required performance (vps)', 'Hosts'], $table->getHeadersText() + $this->assertEquals(['', 'Name', 'Mode', 'Encryption', 'Version', 'Last seen (age)', 'Host count', 'Item count', + 'Required vps', 'Hosts'], $table->getHeadersText() ); - // Check that sortable header is clickable. + // Check that sortable headers are clickable. $this->assertTrue($table->query('link:Name')->one()->isClickable()); + $this->assertTrue($table->query('link:Mode')->one()->isClickable()); + $this->assertTrue($table->query('link:Encryption')->one()->isClickable()); + $this->assertTrue($table->query('link:Version')->one()->isClickable()); + $this->assertTrue($table->query('link:Last seen (age)')->one()->isClickable()); + + // Check versions and hints. + $versions = [ + 'active_current' => ['version' => '6.4.0'], + 'active_unknown' => ['version' => ''], + 'passive_outdated' => ['version' => '6.2.0 ', 'color' => 'red', 'icon_color' => 'yellow', 'hint_text' => + 'Proxy version is outdated, only data collection and remote execution is available with server version 6.4.0.' + ], + 'passive_unsupported' => ['version' => '5.4.1 ', 'color' => 'red', 'icon_color' => 'red', 'hint_text' => + 'Proxy version is not supported by server version 6.4.0.', 'hint_color' => 'red' + ] + ]; - // Check buttons are disabled by default. + foreach ($versions as $proxy => $parameters) { + $column = $table->findRow('Name', $proxy, true)->getColumn('Version'); + $this->assertEquals($parameters['version'], $column->getText()); + + if (array_key_exists('color', $parameters)) { + // Check version text color. + $this->assertTrue($column->query("xpath:.//span[@class=". + CXPathHelper::escapeQuotes($parameters['color'])."]")->exists() + ); + + // Check info-icon color. + $this->assertTrue($column->query("xpath:.//a[@class=". + CXPathHelper::escapeQuotes("icon-info status-".$parameters['icon_color'])."]")->exists() + ); + + // Check version hint. + $column->query('xpath:.//a[@data-hintbox="1"]')->one()->waitUntilClickable()->click(); + $hint = $this->query('xpath://div[@class="overlay-dialogue"]')->waitUntilVisible()->one(); + $this->assertEquals($parameters['hint_text'], $hint->getText()); + + if (array_key_exists('hint_color', $parameters)) { + $this->assertTrue($hint->query("xpath:.//div[@class=". + CXPathHelper::escapeQuotes("hintbox-wrap ".$parameters['hint_color'])."]")->exists() + ); + } + + $hint->asOverlayDialog()->close(); + } + else { + // Check that info-icon is absent. + $this->assertFalse($column->query('xpath:.//a[@class="rel-container"]')->exists()); + } + } + + // Check buttons disabled by default. foreach (['Refresh configuration', 'Enable hosts', 'Disable hosts', 'Delete'] as $button) { $this->assertTrue($this->query('button', $button)->one()->isVisible()); $this->assertFalse($this->query('button', $button)->one()->isClickable()); } } - public function testPageAdministrationGeneralProxies_CheckTableAndFilterReset() { + public function testPageAdministrationProxies_CheckTableAndFilterReset() { $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); $form = $this->query('name:zbx_filter')->waitUntilPresent()->asForm()->one(); @@ -247,43 +149,32 @@ class testPageAdministrationGeneralProxies extends CWebTest { $table_contents = $this->getTableColumnData('Name'); // Fill filter form with data. - $form->fill(['Name' => '1']); + $form->fill(['Name' => 'proxy1']); $form->submit(); $this->page->waitUntilReady(); $filter_result = [ [ - 'Name' => 'Active proxy 1', + 'Name' => 'active_proxy1', 'Mode' => 'Active', 'Encryption' => 'None', - 'Compression' => 'On', + 'Version' => '', 'Last seen (age)' => 'Never', 'Host count' => '', 'Item count' => '', - 'Required performance (vps)' => '', - 'Hosts' => 'Test item host' + 'Required vps' => '', + 'Hosts' => 'enabled_host1' ], [ - 'Name' => 'Passive proxy 1', + 'Name' => 'passive_proxy1', 'Mode' => 'Passive', 'Encryption' => 'None', - 'Compression' => 'On', - 'Last seen (age)' => 'Never', - 'Host count' => '', - 'Item count' => '', - 'Required performance (vps)' => '', - 'Hosts' => '' - ], - [ - 'Name' => 'Proxy_1 for filter', - 'Mode' => 'Active', - 'Encryption' => 'None', - 'Compression' => 'On', + 'Version' => '', 'Last seen (age)' => 'Never', 'Host count' => '', 'Item count' => '', - 'Required performance (vps)' => '', - 'Hosts' => 'Host_1 with proxy' + 'Required vps' => '', + 'Hosts' => 'disabled_host1' ] ]; @@ -312,15 +203,13 @@ class testPageAdministrationGeneralProxies extends CWebTest { [ [ 'filter' => [ - 'Mode' => 'Active' + 'Name' => 'Active proxy' ], 'result' => [ 'Active proxy 1', 'Active proxy 2', 'Active proxy 3', - 'Active proxy to delete', - 'Proxy_1 for filter', - 'Proxy_2 for filter' + 'Active proxy to delete' ], 'check_stats' => true ] @@ -328,7 +217,7 @@ class testPageAdministrationGeneralProxies extends CWebTest { [ [ 'filter' => [ - 'Mode' => 'Passive' + 'Name' => 'Passive proxy' ], 'result' => [ 'Passive proxy 1', @@ -358,6 +247,31 @@ class testPageAdministrationGeneralProxies extends CWebTest { ], 'result' => [] ] + ], + [ + [ + 'filter' => [ + 'Name' => 'Active', + 'Mode' => 'Active', + 'Version' => 'Current' + ], + 'result' => [ + 'active_current' + ] + ] + ], + [ + [ + 'filter' => [ + 'Name' => '', + 'Mode' => 'Passive', + 'Version' => 'Outdated' + ], + 'result' => [ + 'passive_outdated', + 'passive_unsupported' + ] + ] ] ]; } @@ -365,7 +279,7 @@ class testPageAdministrationGeneralProxies extends CWebTest { /** * @dataProvider getFilterProxyData */ - public function testPageAdministrationGeneralProxies_Filter($data) { + public function testPageAdministrationProxies_Filter($data) { $this->page->login()->open('zabbix.php?action=proxy.list')->waitUntilReady(); $form = $this->query('name:zbx_filter')->waitUntilPresent()->asForm()->one(); @@ -594,11 +508,11 @@ class testPageAdministrationGeneralProxies extends CWebTest { 'action' => 'Delete', 'proxies' => [ 'passive_proxy7', - 'Passive proxy 1' + 'Proxy for Discovery rule' ], 'alert' => 'Delete selected proxies?', 'title' => 'Cannot delete proxies', - 'error' => "Proxy \"Passive proxy 1\" is used by discovery rule \"Discovery rule for update\"." + 'error' => "Proxy \"Proxy for Discovery rule\" is used by discovery rule \"Discovery rule for update\"." ] ], // Delete one proxy with host. @@ -620,22 +534,20 @@ class testPageAdministrationGeneralProxies extends CWebTest { 'expected' => TEST_BAD, 'action' => 'Delete', 'proxies' => [ - 'Passive proxy 1' + 'Proxy for Discovery rule' ], 'alert' => 'Delete selected proxy?', 'title' => 'Cannot delete proxy', - 'error' => "Proxy \"Passive proxy 1\" is used by discovery rule \"Discovery rule for update\"." + 'error' => "Proxy \"Proxy for Discovery rule\" is used by discovery rule \"Discovery rule for update\"." ] ] ]; } /** - * @onBeforeOnce prepareProxyHostsData - * * @dataProvider getActionsProxyData */ - public function testPageAdministrationGeneralProxies_Actions($data) { + public function testPageAdministrationProxies_Actions($data) { if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) { $old_hash = CDBHelper::getHash($this->sql); } diff --git a/ui/tests/selenium/testDocumentationLinks.php b/ui/tests/selenium/testDocumentationLinks.php index ef9b83c0ad5..741b7e50228 100644 --- a/ui/tests/selenium/testDocumentationLinks.php +++ b/ui/tests/selenium/testDocumentationLinks.php @@ -18,11 +18,14 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../include/CWebTest.php'; use Facebook\WebDriver\WebDriverKeys; /** + * @dataSource Proxies + * * @backup profiles, module, services, token * * @onBefore prepareServiceData diff --git a/ui/tests/selenium/testFormNetworkDiscovery.php b/ui/tests/selenium/testFormNetworkDiscovery.php index bc08a005e49..1ceee6a17ec 100644 --- a/ui/tests/selenium/testFormNetworkDiscovery.php +++ b/ui/tests/selenium/testFormNetworkDiscovery.php @@ -18,12 +18,14 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -//require_once dirname(__FILE__).'/../include/class.cwebtest.php'; + require_once dirname(__FILE__).'/../include/CLegacyWebTest.php'; use Facebook\WebDriver\WebDriverBy; /** + * @dataSource Proxies + * * @backup drules */ class testFormNetworkDiscovery extends CLegacyWebTest { diff --git a/ui/tests/selenium/testPageDashboardWidgets.php b/ui/tests/selenium/testPageDashboardWidgets.php index 28b2358ec58..a9db76f8dc1 100644 --- a/ui/tests/selenium/testPageDashboardWidgets.php +++ b/ui/tests/selenium/testPageDashboardWidgets.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__) . '/../include/CWebTest.php'; /** diff --git a/ui/tests/selenium/testPageHosts.php b/ui/tests/selenium/testPageHosts.php index 5d6d642dc6d..e1776cccfee 100644 --- a/ui/tests/selenium/testPageHosts.php +++ b/ui/tests/selenium/testPageHosts.php @@ -18,12 +18,15 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__).'/../include/CLegacyWebTest.php'; require_once dirname(__FILE__).'/traits/TagTrait.php'; require_once dirname(__FILE__).'/traits/TableTrait.php'; /** - * @dataSource TagFilter + * @dataSource TagFilter, Proxies + * + * @backup hosts */ class testPageHosts extends CLegacyWebTest { public $HostName = 'ЗАББИКС Сервер'; @@ -254,6 +257,7 @@ class testPageHosts extends CLegacyWebTest { $this->zbxTestLogin(self::HOST_LIST_PAGE); $filter = $this->query('name:zbx_filter')->asForm()->one(); $filter->query('button:Reset')->one()->click(); + $filter->getField('Host groups')->fill('Zabbix servers'); $this->zbxTestClickXpathWait('//label[text()="Proxy"]'); $this->zbxTestClickButtonText('Apply'); diff --git a/ui/tests/selenium/testPageLatestData.php b/ui/tests/selenium/testPageLatestData.php index afda793cb3a..424ab6e1305 100644 --- a/ui/tests/selenium/testPageLatestData.php +++ b/ui/tests/selenium/testPageLatestData.php @@ -129,19 +129,19 @@ class testPageLatestData extends CWebTest { ); } - // With data/Without data subfilter shows only when some host is filtered. - foreach ([false, true] as $status) { - $this->assertEquals($status, $this->query('link:With data')->one(false)->isValid()); - $this->assertEquals($status, $this->query('link:Without data')->one(false)->isValid()); + // With data/Without data subfilter is always present. + $subfilter_queries = ['xpath:.//h3[text()="Data"]', 'link:With data', 'link:Without data']; - if (!$status) { - $form->fill(['Hosts' => self::HOSTNAME]); - $form->submit(); - $subfilter->waitUntilReloaded(); - } - else { - $this->assertTrue($subfilter->query('xpath:.//h3[text()="Data"]')->one()->isValid()); - } + foreach ($subfilter_queries as $query) { + $this->assertTrue($subfilter->query($query)->one()->isValid()); + } + + $form->fill(['Hosts' => self::HOSTNAME]); + $form->submit(); + $subfilter->waitUntilReloaded(); + + foreach ($subfilter_queries as $query) { + $this->assertTrue($subfilter->query($query)->one()->isValid()); } $this->query('button:Reset')->waitUntilClickable()->one()->click(); diff --git a/ui/tests/selenium/testPageMonitoringHosts.php b/ui/tests/selenium/testPageMonitoringHosts.php index 12634cbb97e..6ce8959c9c5 100644 --- a/ui/tests/selenium/testPageMonitoringHosts.php +++ b/ui/tests/selenium/testPageMonitoringHosts.php @@ -230,7 +230,8 @@ class testPageMonitoringHosts extends CWebTest { [ [ 'filter' => [ - 'Status' => 'Disabled' + 'Status' => 'Disabled', + 'Host groups' => ['Zabbix server'] ], 'expected' => [ 'No data found.' diff --git a/ui/tests/selenium/testSID.php b/ui/tests/selenium/testSID.php index 09cf98a3a2c..bc7f1c4a6ce 100644 --- a/ui/tests/selenium/testSID.php +++ b/ui/tests/selenium/testSID.php @@ -18,6 +18,7 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ + require_once dirname(__FILE__) . '/../include/CWebTest.php'; require_once dirname(__FILE__).'/behaviors/CMessageBehavior.php'; require_once dirname(__FILE__).'/../include/helpers/CDataHelper.php'; @@ -25,7 +26,7 @@ require_once dirname(__FILE__).'/../include/helpers/CDataHelper.php'; /** * @backup token * - * @dataSource ScheduledReports + * @dataSource ScheduledReports, Proxies * * @onBefore prepareTokenData */ |