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

2543 lines
80 KiB

1 year ago
<?php
/*
** Zabbix
** Copyright (C) 2001-2023 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
require_once dirname(__FILE__).'/../traits/MacrosTrait.php';
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
require_once dirname(__FILE__).'/../../include/CLegacyWebTest.php';
/**
* Base class for Macros tests.
*/
abstract class testFormMacros extends CLegacyWebTest {
use MacrosTrait;
const SQL_HOSTS = 'SELECT * FROM hosts ORDER BY hostid';
/**
* Attach Behaviors to the test.
*
* @return array
*/
public function getBehaviors() {
return ['class' => CMessageBehavior::class];
}
public static function getHash() {
return CDBHelper::getHash(self::SQL_HOSTS);
}
public static function getCreateMacrosData() {
return [
[
[
'expected' => TEST_GOOD,
'Name' => 'With MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$1234}',
'value' => '!@#$%^&*()_+/*',
'description' => '!@#$%^&*()_+/*'
],
[
'macro' => '{$M:regex:^[0-9a-z]}',
'value' => 'regex',
'description' => 'context macro with regex'
],
[
'macro' => '{$MACRO1}',
'value' => 'Value_1',
'description' => 'Test macro Description 1'
],
[
'macro' => '{$MACRO3}',
'value' => '',
'description' => ''
],
[
'macro' => '{$MACRO4}',
'value' => 'value',
'description' => ''
],
[
'macro' => '{$MACRO5}',
'value' => '',
'description' => 'DESCRIPTION'
],
[
'macro' => '{$MACRO6}',
'value' => 'Значение',
'description' => 'Описание'
],
[
'macro' => '{$MACRO:A}',
'value' => '{$MACRO:A}',
'description' => '{$MACRO:A}'
],
[
'macro' => '{$MACRO:regex:"^[0-9].*$"}',
'value' => '',
'description' => ''
]
]
]
],
[
[
'expected' => TEST_GOOD,
'Name' => 'With lowercase MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$lowercase}',
'value' => 'lowercase_value',
'description' => 'UPPERCASE DESCRIPTION'
]
]
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'Without dollar in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{MACRO}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "MACRO}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With two dollars in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$$MACRO}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "$MACRO}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With wrong symbols in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MAC%^}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "%^}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With LLD macro in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{#LLD_MACRO}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "#LLD_MACRO}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With empty MACRO',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '',
'value' => 'Macro_Value',
'description' => 'Macro Description'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": cannot be empty.'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With repeated MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MACRO}',
'value' => 'Macro_Value_1',
'description' => 'Macro Description_1'
],
[
'macro' => '{$MACRO}',
'value' => 'Macro_Value_2',
'description' => 'Macro Description_2'
]
],
'error' => 'Invalid parameter "/1/macros/2": value (macro)=({$MACRO}) already exists.'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With repeated regex in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MACRO:regex:"^[0-9].*$"}',
'value' => 'Macro_Value_1',
'description' => 'Macro Description_1'
],
[
'macro' => '{$MACRO:regex:"^[0-9].*$"}',
'value' => 'Macro_Value_2',
'description' => 'Macro Description_2'
]
],
'error' => 'Invalid parameter "/1/macros/2": value (macro)=({$MACRO:regex:"^[0-9].*$"}) already exists.'
]
]
];
}
public static function getUpdateMacrosNormalData() {
return [
[
[
'expected' => TEST_GOOD,
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$UPDATED_MACRO1}',
'value' => 'updated value1',
'description' => 'updated description 1'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$UPDATED_MACRO2}',
'value' => 'Updated value 2',
'description' => 'Updated description 2'
]
]
]
]
];
}
public static function getUpdateMacrosCommonData() {
return [
[
[
'expected' => TEST_GOOD,
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$UPDATED_MACRO1}',
'value' => '',
'description' => ''
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$UPDATED_MACRO2}',
'value' => 'Updated Value 2',
'description' => ''
],
[
'macro' => '{$UPDATED_MACRO3}',
'value' => '',
'description' => 'Updated Description 3'
]
]
]
],
[
[
'expected' => TEST_GOOD,
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MACRO:A}',
'value' => '{$MACRO:B}',
'description' => '{$MACRO:C}'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$UPDATED_MACRO_1}',
'value' => '',
'description' => 'DESCRIPTION'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 2,
'macro' => '{$UPDATED_MACRO_2}',
'value' => 'Значение',
'description' => 'Описание'
]
]
]
],
[
[
'expected' => TEST_GOOD,
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$lowercase}',
'value' => 'lowercase_value',
'description' => 'UPPERCASE DESCRIPTION'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$MACRO:regex:"^[a-z]"}',
'value' => 'regex',
'description' => ''
],
[
'action' => USER_ACTION_UPDATE,
'index' => 2,
'macro' => '{$MACRO:regex:^[0-9a-z]}',
'value' => '',
'description' => 'DESCRIPTION'
]
]
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'Without dollar in Macros',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{MACRO}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "MACRO}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With empty Macro',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '',
'value' => 'Macro_Value',
'description' => 'Macro Description'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": cannot be empty.'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With two dollars in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$$MACRO}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "$MACRO}'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With wrong symbols in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MAC%^}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "%^}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With LLD macro in MACROS',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{#LLD_MACRO}'
]
],
'error' => 'Invalid parameter "/1/macros/1/macro": incorrect syntax near "#LLD_MACRO}".'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With repeated Macros',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MACRO}',
'value' => 'Macro_Value_1',
'description' => 'Macro Description_1'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$MACRO}',
'value' => 'Macro_Value_2',
'description' => 'Macro Description_2'
]
],
'error' => 'Invalid parameter "/1/macros/2": value (macro)=({$MACRO}) already exists.'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With repeated regex Macros',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$M:regex:"[a-z]"}',
'value' => 'Macro_Value_1',
'description' => 'Macro Description_1'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$M:regex:"[a-z]"}',
'value' => 'Macro_Value_2',
'description' => 'Macro Description_2'
]
],
'error' => 'Invalid parameter "/1/macros/2": value (macro)=({$M:regex:"[a-z]"}) already exists.'
]
],
[
[
'expected' => TEST_BAD,
'Name' => 'With repeated regex Macros and quotes',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$MACRO:regex:"^[0-9].*$"}',
'value' => 'Macro_Value_1',
'description' => 'Macro Description_1'
],
[
'action' => USER_ACTION_UPDATE,
'index' => 1,
'macro' => '{$MACRO:regex:^[0-9].*$}',
'value' => 'Macro_Value_2',
'description' => 'Macro Description_2'
]
],
'error' => 'Invalid parameter "/1/macros/2": value (macro)=({$MACRO:regex:^[0-9].*$}) already exists.'
]
]
];
}
/**
* Check adding and saving macros in host, host prototype or template form.
*
* @param array $data given data provider
* @param string $host_type string defining is it host, template or host prototype
* @param string $name name of host where changes are made
* @param boolean $update true if update, false if create
* @param boolean $is_prototype defines is it prototype or not
* @param int $lld_id points to LLD rule id where host prototype belongs
*/
public function checkMacros($data, $host_type, $name = null, $update = false, $is_prototype = false, $lld_id = null) {
if ($data['expected'] === TEST_BAD) {
$old_hash = $this->getHash();
}
$form_type = ($host_type === 'host prototype') ? 'hostPrototype' : $host_type.'s';
if ($update) {
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view&filter_selected=0&filter_reset=1')->waitUntilReady();
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $name)->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else if ($host_type === 'template') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$id = CDBHelper::getValue('SELECT hostid FROM hosts WHERE host='.zbx_dbstr($name));
$this->page->login()->open(
$is_prototype
? 'host_prototypes.php?form=update&context=host&parent_discoveryid='.$lld_id.'&hostid='.$id
: 'host_prototypes.php?form=update&host_prototypeid='.$id.'&groupid=0'
);
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm()->one();
}
}
else {
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view&filter_selected=0&filter_reset=1')->waitUntilReady();
$this->query('button:Create host')->one()->waitUntilClickable()->click();
$form = COverlayDialogElement::find()->waitUntilReady()->asForm()->one();
}
else if ($host_type === 'template') {
$this->page->login()->open('zabbix.php?action=template.list')->waitUntilReady();
$this->query('button:Create template')->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$this->page->login()->open(
$is_prototype
? 'host_prototypes.php?form=create&context=host&parent_discoveryid='.$lld_id
: 'host_prototypes.php?form=create'
);
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm()->one();
}
$name = $is_prototype ? $data['Name'].' {#KEY}' : $data['Name'];
$group_name = ($host_type === 'template') ? 'Templates' : 'Zabbix servers';
$group_field = ($host_type === 'template') ? 'Template groups' : 'Host groups';
$general_data = [
(($host_type === 'template') ? 'Template name' : 'Host name') => $name,
$group_field => $group_name
];
if ($is_prototype) {
$form->asForm(['normalized' => true])->fill($general_data);
}
else {
$form->asGridForm(['normalized' => true])->fill($general_data);
}
}
$form->selectTab('Macros');
// Click "Change" button for every macros row in first case for discovered host form.
$macros_count = count($this->getMacros());
if (CTestArrayHelper::get($data, 'expected_macros')) {
for ($i = 0; $i < $macros_count; $i++) {
$form->query('id:macros_'.$i.'_change_state')->one()->waitUntilClickable()->click();
$this->assertFalse($form->query('id:macros_'.$i.'_macro')->one()->isEnabled());
}
}
$this->fillMacros($data['macros']);
$form->submit();
$object = $is_prototype ? 'host prototype' : $host_type;
switch ($data['expected']) {
case TEST_GOOD:
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD, $update ? ucfirst($object).' updated' : ucfirst($object).' added');
$this->assertEquals(1, CDBHelper::getCount('SELECT NULL FROM hosts WHERE host='.zbx_dbstr($name)));
// Check the results in form.
$this->checkMacrosFields($name, $is_prototype, $lld_id, $form_type, $host_type, $data);
break;
case TEST_BAD:
$this->assertMessage(TEST_BAD, ($update ? 'Cannot update '.$object : 'Cannot add '.$object), $data['error']);
// Check that DB hash is not changed.
$this->assertEquals($old_hash, CDBHelper::getHash(self::SQL_HOSTS));
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
break;
}
}
/**
* Test removing Macros from host, host prototype or template.
*
* @param string $name name of host where changes are made
* @param string $host_type string defining is it host, template or host prototype
* @param boolean $is_prototype defines is it prototype or not
* @param int $lld_id points to LLD rule id where host prototype belongs
*/
protected function checkRemoveAll($name, $host_type, $is_prototype = false, $lld_id = null) {
$form_type = ($host_type === 'host prototype') ? 'hostPrototype' : $host_type.'s';
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view')->waitUntilReady();
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $name)->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else if ($host_type === 'template') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$id = CDBHelper::getValue('SELECT hostid FROM hosts WHERE host='.zbx_dbstr($name));
$this->page->login()->open(
$is_prototype
? 'host_prototypes.php?form=update&context=host&parent_discoveryid='.$lld_id.'&hostid='.$id
: 'host_prototypes.php?form=update&host_prototypeid='.$id.'&groupid=0'
);
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm()->one();
}
$form->selectTab('Macros');
$this->removeAllMacros();
$form->submit();
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD, ($is_prototype ? 'Host prototype' : ucfirst($host_type)).' updated');
$this->assertEquals(1, CDBHelper::getCount('SELECT NULL FROM hosts WHERE host='.zbx_dbstr($name)));
// Check the results in form.
$this->checkMacrosFields($name, $is_prototype, $lld_id, $form_type, $host_type, null);
}
public static function getCheckInheritedMacrosData() {
return [
[
[
'case' => 'Add new macro',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$NEW_CHECK_MACRO1}',
'value' => 'new check macro 1',
'description' => 'new check macro description 1'
],
[
'macro' => '{$NEW_CHECK_MACRO2}',
'value' => 'new check macro 2',
'description' => 'new check macro description 2'
]
]
]
],
[
[
'case' => 'Redefine global macro on Host',
'macros' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$SNMP_COMMUNITY}',
'value' => 'new redefined value 1',
'description' => 'new redifined description 1'
],
[
'macro' => '{$_}',
'value' => 'new redifined value 2',
'description' => 'new redifined description 2'
]
]
]
],
[
[
'case' => 'Redefine global macro in Inherited',
'macros' => [
[
'macro' => '{$DEFAULT_DELAY}',
'value' => '100500',
'description' => 'new delay description'
],
[
'macro' => '{$LOCALIP}',
'value' => '100.200.3.4',
'description' => 'new local ip description'
]
]
]
]
];
}
/**
* Test changing and resetting global macro on host, prototype or template.
*
* @param array $data given data provider
* @param string $host_type string defining is it host, template or host prototype
* @param boolean $is_prototype defines is it prototype or not
* @param int $lld_id points to LLD rule id where host prototype belongs
*/
protected function checkChangeInheritedMacros($data, $host_type, $is_prototype = false, $lld_id = null) {
$form_type = ($host_type === 'host prototype') ? 'hostPrototype' : $host_type.'s';
if ($is_prototype) {
$this->page->login()->open('host_prototypes.php?form=create&context=host&parent_discoveryid='.$lld_id);
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm(['normalized' => true])->one();
$name = 'Host prototype with edited global {#MACRO} '.time();
$form->fill(['Host name' => $name]);
$form->fill(['Host groups' => 'Zabbix servers']);
}
else {
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view')->waitUntilReady();
$this->query('button:Create host')->one()->waitUntilClickable()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else if ($host_type === 'template') {
$this->page->login()->open('zabbix.php?action=template.list')->waitUntilReady();
$this->query('button:Create template')->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$this->page->login()->open('host_prototypes.php?form=create');
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm()->one();
}
$name = $host_type.' with edited global macro '.time();
if ($host_type === 'template') {
$form->asGridForm(['normalized' => true])->fill([
'Template name' => $name,
'Template groups' => 'Templates'
]);
}
else {
$form->asGridForm(['normalized' => true])->fill([
'Host name' => $name,
'Host groups' => 'Zabbix servers'
]);
}
}
$form->selectTab('Macros');
$radio_switcher = $this->query('id:show_inherited'.($host_type === 'template' ? '_template' : '').'_macros')
->asSegmentedRadio()->waitUntilPresent()->one();
switch ($data['case']) {
case 'Add new macro':
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
$global_macros = $this->getGlobalMacrosAndSwitch($radio_switcher, $host_type);
$this->fillMacros($data['macros']);
// Get all object's macros.
$hostmacros = $this->getMacros();
// By default macro type is Text, which refers to 0.
foreach ($hostmacros as &$macro) {
$macro['type'] = 0;
}
unset($macro);
// Go to global macros.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
// Check that host macro is editable.
foreach ($data['macros'] as $data_macro) {
$this->assertTrue($this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($data_macro['macro']).
']')->waitUntilPresent()->one()->isEnabled()
);
$this->assertTrue($this->getValueField($data_macro['macro'])->isEnabled());
// Fill macro description by new description using found macro index.
$this->assertTrue($this->query('id:macros_'.$this->getMacroIndex($data_macro['macro']).
'_description')->one()->isEnabled()
);
}
// Add newly added macros to global macros array.
$expected_global_macros = array_merge($global_macros, $hostmacros);
// Compare new macros table from global and inherited macros page with expected result.
$this->assertEquals($this->sortMacros($expected_global_macros), $this->getGlobalMacrosFrotendTable());
break;
case 'Redefine global macro on Host':
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
$global_macros = $this->getGlobalMacrosAndSwitch($radio_switcher, $host_type);
$this->fillMacros($data['macros']);
// Redefine macro values in expected Global macros.
foreach ($data['macros'] as $data_macro) {
foreach ($global_macros as &$global_macro) {
if ($global_macro['macro'] === $data_macro['macro']) {
$global_macro['value'] = $data_macro['value'];
$global_macro['description'] = $data_macro['description'];
}
}
unset($global_macro);
}
// Compare new macros table from global and inherited macros page with expected result.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
// Check enabled/disabled fields.
foreach ($data['macros'] as $data_macro) {
$this->assertFalse($this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($data_macro['macro']).']')
->waitUntilPresent()->one()->isEnabled()
);
$this->assertTrue($this->getValueField($data_macro['macro'])->isEnabled());
// Fill macro description by new description using found macro index.
$this->assertTrue($this->query('id:macros_'.$this->getMacroIndex($data_macro['macro']).
'_description')->one()->isEnabled()
);
$this->assertTrue($this->query('xpath://textarea[text()='.
CXPathHelper::escapeQuotes($data_macro['macro']).']/../..//button[text()="Remove"]')->exists()
);
}
$this->assertEquals($global_macros, $this->getGlobalMacrosFrotendTable());
break;
case 'Redefine global macro in Inherited':
// Get all object's macros.
$hostmacros = $this->getMacros();
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
foreach ($data['macros'] as $data_macro) {
// Find necessary row by macro name and click Change button.
$this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($data_macro['macro']).
']/../..//button[text()="Change"]')->waitUntilPresent()->one()->click();
// Fill macro value by new value.
$this->getValueField($data_macro['macro'])->fill($data_macro['value']);
// Fill macro description by new description using found macro index.
$this->query('id:macros_'.$this->getMacroIndex($data_macro['macro']).'_description')->one()
->fill($data_macro['description']
);
}
// Get new Global macro table.
$new_global_macros = $this->getGlobalMacrosFrotendTable();
if ($host_type === 'host') {
CElementQuery::getDriver()->executeScript('arguments[0].scrollTo(0, 0)',
[COverlayDialogElement::find()->one()->getContent()]
);
}
$radio_switcher->fill(ucfirst($host_type).' macros');
$this->page->waitUntilReady();
$expected_hostmacros = ($hostmacros[0]['macro'] !== '')
? array_merge($data['macros'], $hostmacros)
: $data['macros'];
// Compare host macros table with expected result.
$this->assertEquals($this->sortMacros($expected_hostmacros), $this->getMacros());
break;
}
$form->submit();
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD);
// Check saved edited macros in host/template form.
$id = CDBHelper::getValue('SELECT hostid FROM hosts WHERE host='.zbx_dbstr($name));
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view')->waitUntilReady();
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $name)
->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else if ($host_type === 'template') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$this->page->open(
$is_prototype
? 'host_prototypes.php?form=update&context=host&parent_discoveryid='.$lld_id.'&hostid='.$id
: 'host_prototypes.php?form=update&'.$host_type.'id='.$id.'&groupid=0'
);
$form->invalidate();
}
$form->selectTab('Macros');
// Check all macros after form saving in frontend and db.
switch ($data['case']) {
case 'Add new macro':
// Compare new macros table from host macros page with expected result.
$this->assertEquals($hostmacros, $this->getMacros(true));
// Compare new macros table from global and inherited macros page with expected result.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->assertEquals($this->sortMacros($expected_global_macros), $this->getGlobalMacrosFrotendTable());
// Check macros in FE with macros in DB.
$this->checkInheritedGlobalMacros($hostmacros);
break;
case 'Redefine global macro on Host':
foreach ($data['macros'] as &$data_macro) {
unset($data_macro['action']);
unset($data_macro['index']);
$data_macro['type'] = 0;
}
unset($data_macro);
// Compare new macros table from host macros page with expected result.
$this->assertEquals($data['macros'], $this->getMacros(true));
// Compare new macros table with db.
$this->assertEquals($this->getMacros(true),
$this->sortMacros(CDBHelper::getAll('SELECT macro, value, description, type'.
' FROM hostmacro'.
' WHERE hostid ='.$id)
)
);
// Compare new macros table from global and inherited macros page with expected result.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->assertEquals($global_macros, $this->getGlobalMacrosFrotendTable());
break;
case 'Redefine global macro in Inherited':
// Compare host macros table with expected result.
$this->assertEquals($this->sortMacros($expected_hostmacros), $this->getMacros());
// Compare new macros table with db.
$this->assertEquals($this->getMacros(true),
$this->sortMacros(CDBHelper::getAll('SELECT macro, value, description, type'.
' FROM hostmacro'.
' WHERE hostid ='.$id)
)
);
// Compare new macros table from global and inherited macros page with expected result.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->assertEquals($new_global_macros, $this->getGlobalMacrosFrotendTable());
break;
}
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
public static function getRemoveInheritedMacrosData() {
return [
[
[
'case' => 'Remove macro from Host',
'macros' => [
[
'macro' => '{$MACRO_FOR_DELETE_HOST1}'
],
[
'macro' => '{$MACRO_FOR_DELETE_HOST2}'
]
]
]
],
[
[
'case' => 'Remove macro from Inherited',
'macros' => [
[
'macro' => '{$MACRO_FOR_DELETE_GLOBAL1}'
],
[
'macro' => '{$MACRO_FOR_DELETE_GLOBAL2}'
]
]
]
],
[
[
'case' => 'Remove redefined macro in Inherited',
'macros' => [
[
'macro' => '{$SNMP_COMMUNITY}',
'value' => 'public',
'description' => ''
]
]
]
]
];
}
/**
* Test removing and resetting global macro on host, prototype or template.
*
* @param array $data given data provider
* @param string $host_type string defining is it host, template or host prototype
* @param int $id host's, prototype's or template's id
* @param boolean $is_prototype defines is it prototype or not
* @param int $lld_id points to LLD rule id where host prototype belongs
* @param string $name name of the host where macros are removed
*/
protected function checkRemoveInheritedMacros($data, $host_type, $id, $is_prototype = false,
$lld_id = null, $name = null) {
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view')->waitUntilReady();
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $name)
->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else if ($host_type === 'template') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$link = $is_prototype
? 'host_prototypes.php?form=update&context=host&parent_discoveryid='.$lld_id.'&hostid='.$id
: 'host_prototypes.php?form=update&'.$host_type.'id='.$id.'&groupid=0';
$this->page->login()->open($link);
$form_type = ($host_type === 'host prototype') ? 'hostPrototype' : $host_type.'s';
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm()->one();
}
$form->selectTab('Macros');
$radio_switcher = $this->query('id:show_inherited'.($host_type === 'template' ? '_template' : '').'_macros')
->asSegmentedRadio()->waitUntilPresent()->one();
switch ($data['case']) {
case 'Remove macro from Host':
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
$global_macros = $this->getGlobalMacrosAndSwitch($radio_switcher, $host_type);
$this->removeMacro($data['macros']);
$hostmacros = $this->getMacros(true);
$expected_hostmacros = ($hostmacros === [])
? [[ 'macro' => '', 'value' => '', 'description' => '']]
: $hostmacros;
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
foreach ($data['macros'] as $data_macro) {
foreach ($global_macros as $i => &$global_macro) {
if ($global_macro['macro'] === $data_macro['macro']) {
unset($global_macros[$i]);
}
}
unset($global_macro);
}
$this->assertEquals($this->sortMacros($global_macros), $this->getGlobalMacrosFrotendTable());
break;
case 'Remove macro from Inherited':
// Get all object's macros.
$hostmacros = $this->getMacros(true);
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
$this->removeMacro($data['macros']);
$global_macros = $this->getGlobalMacrosAndSwitch($radio_switcher, $host_type);
foreach ($data['macros'] as $data_macro) {
foreach ($hostmacros as $i => &$hostmacro) {
if ($hostmacro['macro'] === $data_macro['macro']) {
unset($hostmacros[$i]);
}
}
unset($hostmacro);
foreach ($global_macros as $i => &$global_macro) {
if ($global_macro['macro'] === $data_macro['macro']) {
unset($global_macros[$i]);
}
}
unset($global_macro);
}
$expected_hostmacros = ($hostmacros === [])
? [[ 'macro' => '', 'value' => '', 'description' => '']]
: $hostmacros;
// Compare host macros table with expected result.
$this->assertEquals($this->sortMacros($expected_hostmacros), $this->getMacros(true));
break;
case 'Remove redefined macro in Inherited':
// Get all object's macros before changes.
$hostmacros = $this->getMacros(true);
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
$this->removeMacro($data['macros']);
if ($host_type === 'host') {
CElementQuery::getDriver()->executeScript('arguments[0].scrollTo(0, 0)',
[COverlayDialogElement::find()->one()->getContent()]
);
}
$radio_switcher->fill(ucfirst($host_type).' macros');
$this->page->waitUntilReady();
// Delete reset macros from hostmacros array.
foreach ($data['macros'] as $data_macro) {
foreach ($hostmacros as $i => &$hostmacro) {
if ($hostmacro['macro'] === $data_macro['macro']) {
unset($hostmacros[$i]);
}
}
unset($hostmacro);
}
$expected_hostmacros = ($hostmacros === [])
? [[ 'macro' => '', 'value' => '', 'description' => '']]
: $hostmacros;
// Check that reset macros were deleted from hostmacros array.
$this->assertEquals($this->sortMacros($expected_hostmacros), $this->getMacros(true));
// Return to Global macros table and check fields and values there.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->page->waitUntilReady();
// Check enabled/disabled fields and values.
foreach ($data['macros'] as $data_macro) {
$this->assertTrue($this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($data_macro['macro']).
']/../..//button[text()="Change"]')->exists()
);
// Check macro field disabled.
$this->assertFalse($this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($data_macro['macro']).']')
->waitUntilPresent()->one()->isEnabled()
);
// Check macro value and disabled field.
$this->assertFalse($this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($data_macro['macro']).
']/../..//div[contains(@class, "macro-value")]/textarea')->waitUntilPresent()->one()->isEnabled()
);
$this->assertEquals($data_macro['value'], $this->getValueField($data_macro['macro'])->getValue());
// Check macro description and disabled field.
$this->assertFalse($this->query('id:macros_'.$this->getMacroIndex($data_macro['macro']).'_description')
->one()->isEnabled()
);
$this->assertEquals($data_macro['description'], $this->query('id:macros_'.$this
->getMacroIndex($data_macro['macro']).'_description')->one()->getValue()
);
}
break;
}
$form->submit();
if ($host_type === 'host') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD);
if ($host_type === 'host') {
$this->page->open('zabbix.php?action=host.view')->waitUntilReady();
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $name)
->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
}
else if ($host_type === 'template') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$this->page->open($link);
}
$form->invalidate();
$form->selectTab('Macros');
// Compare host macros table with expected result.
$this->assertEquals($this->sortMacros($expected_hostmacros), $this->getMacros(true));
// Compare new host macros table with db.
$this->assertEquals($this->getMacros(true),
$this->sortMacros(CDBHelper::getAll('SELECT macro, value, description, type'.
' FROM hostmacro'.
' WHERE hostid ='.$id)
)
);
// Check all macros after form save.
switch ($data['case']) {
case 'Remove macro from Host':
case 'Remove macro from Inherited':
// Compare new macros table from global and inherited macros page with expected result.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->assertEquals($this->sortMacros($global_macros), $this->getGlobalMacrosFrotendTable());
break;
case 'Remove redefined macro in Inherited':
// Check global macros.
$radio_switcher->fill('Inherited and '.$host_type.' macros');
$this->checkInheritedGlobalMacros($expected_hostmacros);
break;
}
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
/**
* Checking saved macros in host, host prototype or template form.
*
* @param string $name name of host where changes are made
* @param boolean $is_prototype defines is it prototype or not
* @param int $lld_id points to LLD rule id where host prototype belongs
* @param string $form_type string used in form selector
* @param string $host_type string defining is it host, template or host prototype
* @param array $data given data provider
*/
private function checkMacrosFields($name, $is_prototype, $lld_id, $form_type, $host_type, $data = null) {
$id = CDBHelper::getValue('SELECT hostid FROM hosts WHERE host='.zbx_dbstr($name));
if ($host_type === 'host') {
$this->page->login()->open('zabbix.php?action=host.view')->waitUntilReady();
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $name)
->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else if ($host_type === 'template') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
}
else {
$this->page->open(
$is_prototype
? 'host_prototypes.php?form=update&context=host&parent_discoveryid='.$lld_id.'&hostid='.$id
: 'host_prototypes.php?form=update&'.$host_type.'id='.$id.'&groupid=0'
);
$form = $this->query('name:'.$form_type.'Form')->waitUntilPresent()->asForm()->one();
}
$form->selectTab('Macros');
if ($data !== null) {
// Write expected macros to data for discovered host for first case in discovered host.
if (CTestArrayHelper::get($data, 'expected_macros')) {
foreach (array_keys($data['expected_macros']) as $i ) {
$data['macros'][$i]['macro'] = $data['expected_macros'][$i]['macro'];
}
}
foreach ($data['macros'] as &$macro) {
if ($macro['macro'] === '{$lowercase}') {
$macro['macro'] = '{$LOWERCASE}';
}
}
unset($macro);
}
$this->assertMacros(($data !== null) ? $data['macros'] : []);
$this->query('xpath://label[@for="show_inherited'.($host_type === 'template' ? '_template' : '').'_macros_1"]')
->waitUntilPresent()->one()->click();
// Get all macros defined for this host.
$hostmacros = CDBHelper::getAll('SELECT macro, value, description, type FROM hostmacro where hostid ='.$id);
$this->checkInheritedGlobalMacros($hostmacros);
if ($host_type === 'host' || $host_type === 'template') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
/**
* Check host/host prototype/template inherited macros in form matching with global macros in DB.
*
* @param array $hostmacros all macros defined particularly for this host
*/
public function checkInheritedGlobalMacros($hostmacros = []) {
// Create two macros arrays: from DB and from Frontend form.
$macros_db = array_merge(
CDBHelper::getAll('SELECT macro, value, description, type FROM globalmacro'),
$hostmacros
);
// If the macro is expected to have type "Secret text", replace the value from db with the secret macro pattern.
for ($i = 0; $i < count($macros_db); $i++) {
if (intval($macros_db[$i]['type']) === ZBX_MACRO_TYPE_SECRET) {
$macros_db[$i]['value'] = '******';
}
}
// Compare macros from DB with macros from Frontend.
$this->assertEquals($this->sortMacros($macros_db), $this->getGlobalMacrosFrotendTable());
}
/**
* Get values from global macros table.
*
* @return array
*/
public function getGlobalMacrosFrotendTable() {
// Write macros rows from Frontend to array.
$macros_frontend = [];
$table = $this->query('id:tbl_macros')->waitUntilVisible()->asTable()->one();
$count = $table->getRows()->count() - 1;
for ($i = 0; $i < $count; $i += 2) {
$macro = [];
$row = $table->getRow($i);
$macro['macro'] = $row->query('xpath:./td[1]/textarea')->one()->getValue();
$macro_value = $this->getValueField($macro['macro']);
$macro['value'] = $macro_value->getValue();
$macro['description'] = $table->getRow($i + 1)->query('tag:textarea')->one()->getValue();
$macro['type'] = ($macro_value->getInputType() === CInputGroupElement::TYPE_SECRET) ?
ZBX_MACRO_TYPE_SECRET : ZBX_MACRO_TYPE_TEXT;
$macros_frontend[] = $macro;
}
return $this->sortMacros($macros_frontend);
}
public function getSecretMacrosLayoutData() {
return [
[
[
'macro' => '{$SECRET_HOST_MACRO}',
'type' => 'Secret text'
]
],
[
[
'macro' => '{$SECRET_HOST_MACRO}',
'type' => 'Secret text',
'chenge_type' => true
]
],
[
[
'macro' => '{$TEXT_HOST_MACRO}',
'type' => 'Text'
]
],
[
[
'global' => true,
'macro' => '{$X_TEXT_2_SECRET}',
'type' => 'Text'
]
],
[
[
'global' => true,
'macro' => '{$X_SECRET_2_SECRET}',
'type' => 'Secret text'
]
]
];
}
/**
* Check content of macro value InputGroup element for macros.
*
* @param array $data given data provider
* @param string $url url of configuration form of the corresponding entity
* @param string $source type of entity that is being checked (hots, hostPrototype, template)
* @param string $name name of a host where macros to be checked
* @param string $discovered true if discovered host being checked, false if normal host or template
*/
public function checkSecretMacrosLayout($data, $url, $source, $name = null, $discovered = false) {
$this->openMacrosTab($url, $source, true, $name);
// Check that value field is disabled for global macros in "Inherited and host macros" tab.
if (CTestArrayHelper::get($data, 'global', false)) {
$this->query('xpath://label[@for="show_inherited_macros_1"]')->waitUntilPresent()->one()->click();
$value_field = $this->getValueField($data['macro']);
$change_button = $value_field->getNewValueButton();
$revert_button = $value_field->getRevertButton();
if ($data['type'] === CInputGroupElement::TYPE_TEXT) {
$this->assertTrue($value_field->query('xpath:./textarea')->one()->isAttributePresent('readonly'));
$this->assertEquals(2048, $value_field->query('xpath:./textarea')->one()->getAttribute('maxlength'));
$this->assertFalse($change_button->isValid());
$this->assertFalse($revert_button->isValid());
}
else {
$this->assertFalse($value_field->query('xpath:.//input')->one()->isEnabled());
$this->assertEquals(2048, $value_field->query('xpath:.//input')->one()->getAttribute('maxlength'));
$this->assertFalse($change_button->isEnabled());
$this->assertFalse($revert_button->isClickable());
}
$this->assertFalse($value_field->query('xpath:.//button[contains(@class, "btn-dropdown-toggle")]')->one()->isEnabled());
}
else {
$value_field = $this->getValueField($data['macro']);
$macros_count = count($this->getMacros());
if ($discovered) {
for ($i = 0; $i < $macros_count; $i++) {
$this->query('id:macros_'.$i.'_change_state')->one()->waitUntilClickable()->click();
}
}
$change_button = $value_field->getNewValueButton();
$revert_button = $value_field->getRevertButton();
$textarea_xpath = 'xpath:.//textarea[contains(@class, "textarea-flexible")]';
if ($data['type'] === CInputGroupElement::TYPE_SECRET) {
$this->assertFalse($value_field->query($textarea_xpath)->exists());
$this->assertEquals(2048, $value_field->query('xpath:.//input')->one()->getAttribute('maxlength'));
$this->assertTrue($change_button->isValid());
$this->assertFalse($revert_button->isClickable());
// Change value text or type and check that New value button is not displayed and Revert button appeared.
if (CTestArrayHelper::get($data, 'change_type', false)) {
$value_field->changeInputType(CInputGroupElement::TYPE_TEXT);
}
else {
$change_button->click();
}
$value_field->invalidate();
$this->assertFalse($change_button->isEnabled());
$this->assertTrue($revert_button->isClickable());
}
else {
$this->assertTrue($value_field->query($textarea_xpath)->exists());
$this->assertEquals(2048, $value_field->query('xpath:./textarea')->one()->getAttribute('maxlength'));
$this->assertFalse($change_button->isValid());
$this->assertFalse($revert_button->isValid());
// Change value type to "Secret text" and check that new value and revert buttons were not added.
$value_field->changeInputType(CInputGroupElement::TYPE_SECRET);
$value_field->invalidate();
$this->assertFalse($value_field->getNewValueButton()->isValid());
$this->assertFalse($value_field->getRevertButton()->isValid());
}
}
if ($source === 'hosts') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
public function getCreateSecretMacrosData() {
return [
[
[
'macro_fields' => [
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$SECRET_MACRO}',
'value' => [
'text' => 'host secret value',
'type' => 'Secret text'
],
'description' => 'secret description'
],
'check_default_type' => true
]
],
[
[
'macro_fields' => [
'macro' => '{$TEXT_MACRO}',
'value' => [
'text' => 'host plain text value',
'type' => 'Secret text'
],
'description' => 'plain text description'
],
'back_to_text' => true
]
],
[
[
'macro_fields' => [
'macro' => '{$SECRET_EMPTY_MACRO}',
'value' => [
'text' => '',
'type' => 'Secret text'
],
'description' => 'secret empty value'
]
]
]
];
}
/**
* Check adding and saving secret macros for host, host prototype and template entities.
*
* @param array $data given data provider
* @param string $url url of configuration form of the corresponding entity
* @param string $source type of entity that is being checked (hots, hostPrototype, template)
* @param string $name name of the host where macros are removed
*/
public function createSecretMacros($data, $url, $source, $name = null) {
$form = $this->openMacrosTab($url, $source, true, $name);
// Check that macro values have type plain text by default.
if (CTestArrayHelper::get($data, 'check_default_type', false)){
$this->assertEquals(CInputGroupElement::TYPE_TEXT, $this->query('xpath://div[contains(@class, "macro-value")]')
->one()->asInputGroup()->getInputType());
}
$this->fillMacros([$data['macro_fields']]);
$value_field = $this->query('xpath://div[contains(@class, "macro-value")]')->all()->last()->asInputGroup();
// Check that macro type is set correctly.
$this->assertEquals($data['macro_fields']['value']['type'], $value_field->getInputType());
// Check text from value field.
$this->assertEquals($data['macro_fields']['value']['text'], $value_field->getValue());
// Switch to tab with inherited and instance macros and verify that the value is secret but is still accessible.
$this->checkInheritedTab($data['macro_fields'], true, $source);
// Check that macro value is hidden but is still accessible after switching back to instance macros list.
$data_value_field = $this->getValueField($data['macro_fields']['macro']);
$this->assertEquals(CInputGroupElement::TYPE_SECRET, $data_value_field->getInputType());
// Change macro type back to text (is needed) before saving the changes.
if (CTestArrayHelper::get($data, 'back_to_text', false)) {
$data_value_field->changeInputType(CInputGroupElement::TYPE_TEXT);
}
$form->invalidate();
$form->submit();
if ($source === 'host') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD);
// Check value field for guest account.
$this->openMacrosTab($url, $source, false, $name);
$guest_value_field = $this->getValueField($data['macro_fields']['macro']);
if (CTestArrayHelper::get($data, 'back_to_text', false)) {
$this->assertEquals($data['macro_fields']['value']['text'], $guest_value_field->getValue());
// Switch to tab with inherited and instance macros and verify that the value is plain text.
$this->checkInheritedTab($data['macro_fields'], false, $source);
}
else {
$this->assertEquals('******', $guest_value_field->getValue());
// Switch to tab with inherited and instance macros and verify that the value is secret and is not accessible.
$this->checkInheritedTab($data['macro_fields'], true, $source, false);
}
// Check macro value, type and description in DB.
$sql = 'SELECT value, description, type FROM hostmacro WHERE macro='.zbx_dbstr($data['macro_fields']['macro']);
$type = (CTestArrayHelper::get($data, 'back_to_text', false)) ? ZBX_MACRO_TYPE_TEXT : ZBX_MACRO_TYPE_SECRET;
$this->assertEquals([$data['macro_fields']['value']['text'], $data['macro_fields']['description'], $type],
array_values(CDBHelper::getRow($sql))
);
if ($source === 'hosts' || $source == 'templates') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
/**
* Check update of secret macros for host, host prototype and template entities.
*
* @param array $data given data provider
* @param string $url url of configuration form of the corresponding entity
* @param string $source type of entity that is being checked (hots, hostPrototype, template)
* @param string $name name of the host where macros to be updated
* @param boolean $discovered true if object is discovered host, false - if normal
*/
public function updateSecretMacros($data, $url, $source, $name = null, $discovered = false) {
$form = $this->openMacrosTab($url, $source, true, $name);
if ($discovered) {
$expected = $data['expected'];
$data = $data['fields'];
// Click "Change" button for every macros row in first case for discovered host form.
$form->query('id:macros_'.$data['index'].'_change_state')->one()->waitUntilClickable()->click();
}
$this->fillMacros([$data]);
if ($discovered) {
$data = $expected;
}
// Check that new values are correct in Inherited and host prototype macros tab before saving the values.
$secret = (CTestArrayHelper::get($data['value'], 'type', CInputGroupElement::TYPE_SECRET) ===
CInputGroupElement::TYPE_SECRET) ? true : false;
$this->checkInheritedTab($data, $secret, $source);
$form->invalidate();
$form->submit();
if ($source === 'host') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD);
$this->openMacrosTab($url, $source, false, $name);
$value_field = $this->getValueField($data['macro']);
if (CTestArrayHelper::get($data['value'], 'type', CInputGroupElement::TYPE_SECRET) === CInputGroupElement::TYPE_SECRET) {
$this->assertEquals(CInputGroupElement::TYPE_SECRET, $value_field->getInputType());
$this->assertEquals('******', $value_field->getValue());
$this->checkInheritedTab($data, true, $source, false);
}
else {
$this->assertEquals(CInputGroupElement::TYPE_TEXT, $value_field->getInputType());
$this->assertEquals($data['value']['text'], $value_field->getValue());
$this->checkInheritedTab($data, false, $source);
}
// Check in DB that values of the updated macros are correct.
$sql = 'SELECT value FROM hostmacro WHERE macro='.zbx_dbstr($data['macro']).' ORDER BY hostmacroid DESC';
$this->assertEquals($data['value']['text'], CDBHelper::getValue($sql));
if ($source === 'hosts' || $source === 'templates') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
public function getRevertSecretMacrosData() {
return [
[
[
'macro_fields' => [
'macro' => $this->revert_macro_1,
'value' => 'Secret '.$this->revert_macro_object.' value'
]
]
],
[
[
'macro_fields' => [
'macro' => $this->revert_macro_2,
'value' => 'Secret '.$this->revert_macro_object.' value 2'
],
'set_to_text' => true
]
]
];
}
/**
* Check that it is possible to revert secret macro changes for host, host prototype and template entities.
*
* @param array $data given data provider
* @param string $url url of configuration form of the corresponding entity
* @param string $source type of entity that is being checked (hots, hostPrototype, template)
* @param string $name name of the host where macros to be updated
* @param boolean $discovered true if object is discovered host, false - if normal
*/
public function revertSecretMacroChanges($data, $url, $source, $name = null, $discovered = false) {
static $first_case = true;
$form = $this->openMacrosTab($url, $source, true, $name);
$sql = 'SELECT * FROM hostmacro WHERE macro='.CDBHelper::escape($data['macro_fields']['macro']);
$old_values = CDBHelper::getRow($sql);
$value_field = $this->getValueField($data['macro_fields']['macro']);
// Check that the existing macro value is hidden.
$this->assertEquals('******', $value_field->getValue());
// Click "Change" button for every macros row in first case for discovered host form.
$macros_count = count($this->getMacros());
if ($discovered && $first_case) {
$first_case = false;
for ($i = 0; $i < $macros_count; $i++) {
$form->query('id:macros_'.$i.'_change_state')->one()->waitUntilClickable()->click();
}
}
// Change the value of the secret macro
$value_field->getNewValueButton()->click();
$this->assertEquals('', $value_field->getValue());
$value_field->fill('New_macro_value');
if (CTestArrayHelper::get($data, 'set_to_text', false)) {
$value_field->changeInputType(CInputGroupElement::TYPE_TEXT);
$this->assertEquals('New_macro_value', $value_field->getValue());
}
// Press revert button and save the changes.
$value_field->getRevertButton()->click();
$form->invalidate();
$form->submit();
if ($source === 'host') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD);
// Check that no macro value changes took place.
$this->openMacrosTab($url, $source, false, $name);
$this->assertEquals('******', $this->getValueField($data['macro_fields']['macro'])->getValue());
$this->assertEquals($old_values, CDBHelper::getRow($sql));
if ($source === 'hosts' || $source === 'templates') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
/**
* Function opens Inherited and instance macros tab and checks the value, it the value has type Secret text and if
* the value is displayed.
*
* @param type $data given data provider
* @param type $secret flag that indicates if the value should have type "Secret text".
* @param string $source type of entity that is being checked (host, hostPrototype, template)
* @param type $available flag that indicates if the value should be available.
*/
public function checkInheritedTab($data, $secret, $source, $available = true) {
// Switch to the list of inherited and instance macros.
$this->query('xpath://label[@for="show_inherited'.($source === 'templates' ? '_template' : '').'_macros_1"]')
->waitUntilPresent()->one()->click();
$this->query('class:is-loading')->waitUntilNotPresent();
$value_field = $this->getValueField($data['macro']);
if ($secret) {
$this->assertEquals(CInputGroupElement::TYPE_SECRET, $value_field->getInputType());
$expected_value = ($available) ? $data['value']['text'] : '******';
$this->assertEquals($expected_value, $value_field->getValue());
}
else {
$this->assertEquals(CInputGroupElement::TYPE_TEXT, $value_field->getInputType());
$this->assertEquals($data['value']['text'], $value_field->getValue());
}
// Switch back to the list of instance macros.
$this->query('xpath://label[@for="show_inherited'.($source === 'templates' ? '_template' : '').'_macros_0"]')
->waitUntilPresent()->one()->click();
$this->query('class:is-loading')->waitUntilNotPresent();
}
/**
* Function opens Macros tab in corresponding instance configuration form.
*
* @param string $url URL that leads to the configuration form of corresponding entity
* @param string $source type of entity that is being checked (host, hostPrototype, template)
* @param type $login flag that indicates whether login should occur before opening the configuration form
* @param type $name name of a host where macros are updated
*/
public function openMacrosTab($url, $source, $login = false, $name = null) {
if ($login) {
$this->page->login();
}
$this->page->open($url)->waitUntilReady();
if ($source === 'hosts') {
$column = $this->query('xpath://table[@class="list-table"]')->asTable()->one()->waitUntilReady()
->findRow('Name', $name, true)->getColumn('Name');
$column->query('link', $name)->asPopupButton()->one()->select('Host');
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible()->selectTab('Macros');
}
else if ($source === 'templates') {
$this->page->login()
->open('zabbix.php?action=template.list&filter_name='.$name.'&filter_set=1')->waitUntilReady();
$this->query('link', $name)->one()->click();
$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible()->selectTab('Macros');
}
else {
$form = $this->query('id:'.$source.'-form')->asForm()->one()->selectTab('Macros');
}
return $form;
}
/**
* Sort all macros array by Macros.
*
* @param array $macros macros to be sorted
*
* @return array
*/
private function sortMacros($macros) {
usort($macros, function ($a, $b) {
return strcmp($a['macro'], $b['macro']);
});
return $macros;
}
/**
* Get macro index for the provided macro name.
*
* @param string $macro macro name for which index needs to be fetched
*
* @return int
*/
private function getMacroIndex($macro) {
$index = explode('_', $this->query('xpath://textarea[text()='.CXPathHelper::escapeQuotes($macro).']')
->one()->getAttribute('id'), 3
);
return $index[1];
}
/**
* Get macro index for the provided macro name.
*
* @param CElement $radio_switcher macro name for which index needs to be fetched
* @param string $host_type string defining is it host, template or host prototype
*
* @return array
*/
private function getGlobalMacrosAndSwitch($radio_switcher, $host_type) {
// Get all global macros before changes.
$global_macros = $this->getGlobalMacrosFrotendTable();
// Return to object's macros.
if ($host_type === 'host') {
CElementQuery::getDriver()->executeScript('arguments[0].scrollTo(0, 0)',
[COverlayDialogElement::find()->one()->getContent()]
);
}
$radio_switcher->fill(ucfirst($host_type).' macros');
$this->page->waitUntilReady();
return $global_macros;
}
public function getCreateVaultMacrosData() {
return [
[
[
'expected' => TEST_GOOD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO}',
'value' => [
'text' => 'secret/path:key',
'type' => 'Vault secret'
],
'description' => 'vault description'
],
'title' => ucfirst($this->vault_object).' updated',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_GOOD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO2}',
'value' => [
'text' => 'one/two/three/four/five/six:key',
'type' => 'Vault secret'
],
'description' => 'vault description1'
],
'title' => ucfirst($this->vault_object).' updated',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO3}',
'value' => [
'text' => 'secret/path:',
'type' => 'Vault secret'
],
'description' => 'vault description2'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": incorrect syntax near "path:".',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO4}',
'value' => [
'text' => '/path:key',
'type' => 'Vault secret'
],
'description' => 'vault description3'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": incorrect syntax near "/path:key".',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO5}',
'value' => [
'text' => 'path:key',
'type' => 'Vault secret'
],
'description' => 'vault description4'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": incorrect syntax near "path:key".',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO6}',
'value' => [
'text' => ':key',
'type' => 'Vault secret'
],
'description' => 'vault description5'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": incorrect syntax near ":key".',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO7}',
'value' => [
'text' => 'secret/path',
'type' => 'Vault secret'
],
'description' => 'vault description6'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": incorrect syntax near "path".',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO8}',
'value' => [
'text' => '/secret/path:key',
'type' => 'Vault secret'
],
'description' => 'vault description8'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": incorrect syntax near "/secret/path:key".',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO9}',
'value' => [
'text' => '',
'type' => 'Vault secret'
],
'description' => 'vault description9'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->hashi_error_field.'": cannot be empty.',
'vault' => 'Hashicorp'
]
],
[
[
'expected' => TEST_GOOD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO10}',
'value' => [
'text' => 'AppID=zabbix:key',
'type' => 'Vault secret'
],
'description' => 'cyberark description10'
],
'title' => ucfirst($this->vault_object).' updated',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_GOOD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO11}',
'value' => [
'text' => 'AppID=zabbix;SomethingElse=value;AndMoreValue=values:key',
'type' => 'Vault secret'
],
'description' => 'cyberark description11'
],
'title' => ucfirst($this->vault_object).' updated',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_GOOD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO12}',
'value' => [
'text' => 'AppID=:key',
'type' => 'Vault secret'
],
'description' => 'cyberark description12'
],
'title' => ucfirst($this->vault_object).' updated',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO13}',
'value' => [
'text' => '',
'type' => 'Vault secret'
],
'description' => 'vault description13'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->cyber_error_field.'": cannot be empty.',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO14}',
'value' => [
'text' => 'AppID=zabbix:',
'type' => 'Vault secret'
],
'description' => 'vault description14'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->cyber_error_field.'": mandatory key is missing.',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO15}',
'value' => [
'text' => 'AppID:key',
'type' => 'Vault secret'
],
'description' => 'vault description15'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->cyber_error_field.'": incorrect syntax near "AppID:key".',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO16}',
'value' => [
'text' => 'APPID=something:key',
'type' => 'Vault secret'
],
'description' => 'vault description16'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->cyber_error_field.'": mandatory parameter "AppID" is missing.',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO17}',
'value' => [
'text' => 'NotApp=something:key',
'type' => 'Vault secret'
],
'description' => 'vault description17'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->cyber_error_field.'": mandatory parameter "AppID" is missing.',
'vault' => 'Cyberark'
]
],
[
[
'expected' => TEST_BAD,
'macro_fields' => [
'macro' => '{$VAULT_MACRO18}',
'value' => [
'text' => 'NotApp=something:key',
'type' => 'Vault secret'
],
'description' => 'vault description18'
],
'title' => 'Cannot update '.$this->vault_object,
'message' => 'Invalid parameter "'.$this->cyber_error_field.'": mandatory parameter "AppID" is missing.',
'vault' => 'Cyberark'
]
]
];
}
/**
* Create Hashicorp or Cyberark vault macros.
*
* @param string $data data provider
* @param string $url link to page where source exists
* @param string $source source type - host/template/host prototype
* @param string $name source name
*/
public function createVaultMacros($data, $url, $source, $name = null) {
$this->selectVault($data['vault']);
$form = $this->openMacrosTab($url, $source, true, $name);
$this->fillMacros([$data['macro_fields']]);
$form->submit();
if ($data['expected'] == TEST_BAD) {
$this->assertMessage($data['expected'], $data['title'], $data['message']);
}
else {
if ($source === 'host') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage($data['expected'], $data['title']);
$sql = 'SELECT value, description, type FROM hostmacro WHERE macro='.zbx_dbstr($data['macro_fields']['macro']);
$this->assertEquals([$data['macro_fields']['value']['text'], $data['macro_fields']['description'], ZBX_MACRO_TYPE_VAULT],
array_values(CDBHelper::getRow($sql))
);
$this->openMacrosTab($url, $source, false, $name);
$value_field = $this->getValueField($data['macro_fields']['macro']);
$this->assertEquals($data['macro_fields']['value']['text'], $value_field->getValue());
}
if ($source === 'hosts' || $source === 'templates') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
public function getUpdateVaultMacrosNormalData() {
return [
[
[
'fields' => [
'action' => USER_ACTION_UPDATE,
'index' => $this->vault_macro_index,
'macro' => $this->update_vault_macro,
'value' => [
'text' => 'secret/path:key'
],
'description' => ''
],
'vault' => 'Hashicorp'
]
]
];
}
public function getUpdateVaultMacrosCommonData() {
return [
[
[
'fields' => [
'action' => USER_ACTION_UPDATE,
'index' => $this->vault_macro_index,
'macro' => $this->update_vault_macro,
'value' => [
'text' => 'new/path/to/secret:key'
],
'description' => ''
],
'vault' => 'Hashicorp'
]
],
[
[
'fields' => [
'action' => USER_ACTION_UPDATE,
'index' => $this->vault_macro_index,
'macro' => $this->update_vault_macro,
'value' => [
'text' => 'new/path/to/secret:key'
],
'description' => 'Changing description'
],
'vault' => 'Hashicorp'
]
],
[
[
'fields' => [
'action' => USER_ACTION_UPDATE,
'index' => $this->vault_macro_index,
'macro' => $this->update_vault_macro,
'value' => [
'text' => 'AppID=zabbix:key'
],
'description' => ''
],
'vault' => 'Cyberark'
]
],
[
[
'fields' => [
'action' => USER_ACTION_UPDATE,
'index' => $this->vault_macro_index,
'macro' => $this->update_vault_macro,
'value' => [
'text' => 'AppID=zabbix;Object=something:key'
],
'description' => ''
],
'vault' => 'Cyberark'
]
],
[
[
'fields' => [
'action' => USER_ACTION_UPDATE,
'index' => $this->vault_macro_index,
'macro' => $this->update_vault_macro,
'value' => [
'text' => 'AppID=zabbix;Object=something:key'
],
'description' => 'Changing description'
],
'vault' => 'Cyberark'
]
]
];
}
/**
* Update Hashicorp and Cyberark vault macros.
*
* @param string $data data provider
* @param string $url link to page where source exists
* @param string $source source type - host/template/host prototype
* @param string $name source name
*/
public function updateVaultMacros($data, $url, $source, $name = null) {
$this->selectVault($data['vault']);
$form = $this->openMacrosTab($url, $source, true, $name);
// Click "Change" button for every macros row in first case for discovered host form.
if (CTestArrayHelper::get($data, 'expected_macros')) {
$form->query('id:macros_'.$data['fields']['index'].'_change_state')->one()->waitUntilClickable()->click();
}
$this->fillMacros([$data['fields']]);
$form->submit();
if ($source === 'host') {
COverlayDialogElement::ensureNotPresent();
}
$this->assertMessage(TEST_GOOD);
$this->openMacrosTab($url, $source, false, $name);
$result = [];
foreach (['macro', 'value', 'description'] as $field) {
$result[] = $this->query('xpath://textarea[@id="macros_'.$data['fields']['index'].'_'.$field.'"]')->one()->getText();
}
$data = CTestArrayHelper::get($data, 'expected_macros', $data);
$this->assertEquals([$data['fields']['macro'], $data['fields']['value']['text'], $data['fields']['description']], $result);
array_push($result, ZBX_MACRO_TYPE_VAULT);
$sql = 'SELECT macro, value, description, type FROM hostmacro WHERE macro='.zbx_dbstr($data['fields']['macro']).' ORDER BY hostmacroid DESC';
$this->assertEquals($result, array_values(CDBHelper::getRow($sql)));
if ($source === 'hosts' || $source === 'templates') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
}
/**
* Select vault provider.
*
* @param string $vault vault provider Hashicorp or Cyberark
*/
public function selectVault($vault) {
$vaultid = ($vault === 'Hashicorp') ? 0 : 1;
if ($vaultid !== CDBHelper::getValue('SELECT vault_provider FROM config')) {
DBexecute('UPDATE config SET vault_provider='.zbx_dbstr($vaultid));
}
}
/**
* Check vault macros validation after changing vault type.
*
* @param string $url URL that leads to the configuration form of corresponding entity
* @param string $source type of entity that is being checked (host, hostPrototype, template)
* @param type $name name of a host where macros are updated
*/
public function checkVaultValidation($url, $source, $name = null, $discovered = false) {
$cyberark = [
'fields' =>
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$VAULT}',
'value' => [
'text' => 'AppID=zabbix:key',
'type' => 'Vault secret'
],
'description' => 'CyberArk vault description'
],
'error' => 'Invalid parameter "/1/macros/1/value": incorrect syntax near "AppID=zabbix:key".'
];
$hashicorp = [
'fields' =>
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'macro' => '{$VAULT}',
'value' => [
'text' => 'secret/path:key',
'type' => 'Vault secret'
],
'description' => 'HashiCorp vault description'
],
'error' => 'Invalid parameter "/1/macros/1/value": incorrect syntax near "secret/path:key".'
];
$this->page->login();
for ($i = 0; $i <= 1; $i++) {
$this->page->open('zabbix.php?action=miscconfig.edit')->waitUntilReady();
// Check in setting what Vault is enabled.
$setting_form = $this->query('name:otherForm')->asForm()->one();
$vault = $setting_form->getField('Vault provider')->getText();
// Try to create macros with Vault type different from settings.
$form = $this->openMacrosTab($url, $source, false, $name);
$vault_values = ($vault === 'CyberArk Vault') ? $hashicorp : $cyberark;
// Click "Change" button for discovered host form in the first case.
if ($discovered && $i === 0) {
$form->query('id:macros_0_change_state')->one()->waitUntilClickable()->click();
}
$this->fillMacros([$vault_values['fields']]);
$form->submit();
$this->assertMessage(TEST_BAD, 'Cannot update '.$this->vault_object, $vault_values['error']);
// Hosts in edit view opens in overlay and need to be closed manually.
if ($source === 'hosts' || $source === 'templates') {
COverlayDialogElement::find()->one()->close();
COverlayDialogElement::ensureNotPresent();
}
// Change Vault in settings to correct one.
$this->page->open('zabbix.php?action=miscconfig.edit')->waitUntilReady();
$vault_settings = ($vault === 'CyberArk Vault') ? 'HashiCorp Vault' : 'CyberArk Vault';
$setting_form->fill(['Vault provider' => $vault_settings])->submit();
// Check simple update.
$this->openMacrosTab($url, $source, false, $name);
if ($discovered && $i === 0) {
$form->query('id:macros_0_change_state')->one()->waitUntilClickable()->click();
}
$form->submit();
$this->assertMessage(TEST_BAD, 'Cannot update '.$this->vault_object);
// Create macros with correct value.
$this->fillMacros([$vault_values['fields']]);
// For discovered host macro becomes editable only after marco is redefined first.
if ($discovered && $i === 0) {
$form->submit();
$this->assertMessage(TEST_GOOD, ucfirst($this->vault_object).' updated');
$this->openMacrosTab($url, $source, false, $name);
$form->invalidate();
$this->fillMacros([$vault_values['fields']]);
}
$form->submit();
$this->assertMessage(TEST_GOOD, ucfirst($this->vault_object).' updated');
}
}
public function getResolveSecretMacroData() {
return [
// Latest data page. Macro is resolved only in key.
[
[
'url' => 'zabbix.php?action=latest.view&hostids%5B%5D='.$this->macro_resolve_hostid.'&show_details=1',
'name' => 'Macro value: '.$this->macro_resolve,
'key' => 'trap[Value 2 B resolved]',
'key_secret' => 'trap[******]'
]
],
// Hosts items page. Macro is not resolved in any field.
[
[
'url' => 'items.php?filter_set=1&filter_hostids%5B0%5D='.$this->macro_resolve_hostid.'&context=host',
'name' => 'Macro value: '.$this->macro_resolve,
'key' => 'trap['.$this->macro_resolve.']',
'key_secret' => 'trap['.$this->macro_resolve.']'
]
]
];
}
/**
* Function for testing resolving macros on host or global level.
*
* @param string $data data provider
* @param string $object macros level: global or host
*/
public function resolveSecretMacro($data, $object = 'global') {
$this->checkItemFields($data['url'], $data['name'], $data['key']);
if ($object === 'host') {
// Open host form in popup and change macro type to secret.
$form = $this->openMacrosTab('zabbix.php?action=host.view', 'hosts', false, 'Available host in maintenance');
$this->getValueField($this->macro_resolve)->changeInputType(CInputGroupElement::TYPE_SECRET);
$form->submit();
$this->page->waitUntilReady();
$this->assertMessage(TEST_GOOD, 'Host updated');
}
else {
// Change global macro type to secret.
$this->page->open('zabbix.php?action=macros.edit')->waitUntilReady();
$this->getValueField($this->macro_resolve)->changeInputType(CInputGroupElement::TYPE_SECRET);
$this->query('button:Update')->one()->click();
}
$this->checkItemFields($data['url'], $data['name'], $data['key_secret']);
}
/**
* Function for checking item field on Latest data or Items page.
*
* @param string $url Latest data or Items page URL
* @param string $name item name
* @param string $key item key
*/
private function checkItemFields($url, $name, $key) {
$this->page->login()->open($url)->waitUntilReady();
$table = $this->query('xpath://form[@name="items"]/table[@class="list-table"] | '.
'//table[contains(@class, "overflow-ellipsis")]')->asTable()->waitUntilPresent()->one();
$name_column = $table->findRow('Name', $name, true)->getColumn('Name');
$this->assertEquals($name, $name_column->query('tag:a')->one()->getText());
$this->assertEquals($key, (strpos($url, 'latest')
? $name_column->query('xpath://span[@class="green"]')->one()->getText()
: $table->findRow('Name', $name)->getColumn('Key')->getText()
));
}
}