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.
2114 lines
54 KiB
2114 lines
54 KiB
<?php
|
|
/*
|
|
** Zabbix
|
|
** Copyright (C) 2001-2023 Zabbix SIA
|
|
**
|
|
** This program is free software; you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation; either version 2 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program; if not, write to the Free Software
|
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
**/
|
|
|
|
require_once dirname(__FILE__).'/../../include/CWebTest.php';
|
|
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
|
|
|
|
/**
|
|
* @backup items, ids
|
|
*/
|
|
class testFormLowLevelDiscoveryOverrides extends CWebTest {
|
|
|
|
const HOST_ID = 40001;
|
|
const UPDATED_ID = 133800;
|
|
|
|
const INTERVAL_MAPPING = [
|
|
'Type' => [
|
|
'name' => 'type',
|
|
'class' => 'CSegmentedRadioElement',
|
|
'selector' => 'xpath:./ul[contains(@class, "radio-list-control")]'.
|
|
'|./ul/li/ul[contains(@class, "radio-list-control")]|./div/ul[contains(@class, "radio-list-control")]'
|
|
],
|
|
'Interval' => [
|
|
'name' => 'delay',
|
|
'class' => 'CElement',
|
|
'selector' => 'xpath:./input[@name][not(@type) or @type="text" or @type="password"][not(@style) or '.
|
|
'not(contains(@style,"display: none"))]|./textarea[@name]'
|
|
],
|
|
'Period' => [
|
|
'name' => 'period',
|
|
'class' => 'CElement',
|
|
'selector' => 'xpath:./input[@name][not(@type) or @type="text" or @type="password"][not(@style) or '.
|
|
'not(contains(@style,"display: none"))]|./textarea[@name]'
|
|
]
|
|
];
|
|
|
|
|
|
public static $created_id;
|
|
public static $old_hash;
|
|
|
|
/**
|
|
* Attach Behaviors to the test.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getBehaviors() {
|
|
return ['class' => CMessageBehavior::class];
|
|
}
|
|
|
|
/*
|
|
* Overrides data for LLD creation.
|
|
*/
|
|
public static function getCreateData() {
|
|
return [
|
|
// #0.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => ''
|
|
],
|
|
'error' => 'Incorrect value for field "Name": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #1.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override without actions'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #2.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override without actions'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #3.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override without actions'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Graph prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #4.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override without actions'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Host prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #5.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty tags in trigger prototype'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype',
|
|
'Tags' => []
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tags": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #6.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty tag name in trigger prototype'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype',
|
|
'Tags' => [
|
|
['tag' => '', 'value' => 'value1']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tag": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #7.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty template'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Link templates' => []
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Link templates": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #8.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty tag name in host prototype'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Tags' => [
|
|
['tag' => '', 'value' => 'value1']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tag": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #9.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty tags in host prototype'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Tags' => []
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tags": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #10.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty delay'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => ''
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Update interval": invalid delay.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #11.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with zero delay'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '0'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Item will not be refreshed. Specified update interval requires '.
|
|
'having at least one either flexible or scheduling interval.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #12.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with 2 days delay'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '2d'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Item will not be refreshed. Update interval should be between 1s and 1d. '.
|
|
'Also Scheduled/Flexible intervals can be used.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #13.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty interval'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '50m',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'type' => 'Flexible',
|
|
'delay' => '',
|
|
'period' => '1-5,01:01-13:05'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #14.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty period'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '50m',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'type' => 'Flexible',
|
|
'delay' => '20s',
|
|
'period' => ''
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #15.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with wrong period'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '50m',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'type' => 'Flexible',
|
|
'delay' => '20s',
|
|
'period' => '1-2'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "1-2".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #16.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with wrong scheduling interval'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '50m',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'type' => 'Scheduling',
|
|
'delay' => 'wd1-9'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "wd1-9".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #17.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty history'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype',
|
|
'History storage period' => [
|
|
'ophistory_history_mode' => 'Storage period',
|
|
'ophistory_history' => ''
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "History storage period": a time unit is expected.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #18.
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override with empty history'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype',
|
|
'Trend storage period' => [
|
|
'optrends_trends_mode' => 'Storage period',
|
|
'optrends_trends' => ''
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Trend storage period": a time unit is expected.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #19.
|
|
[
|
|
[
|
|
'expected' => TEST_GOOD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Minimal override'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
// #20.
|
|
[
|
|
[
|
|
'expected' => TEST_GOOD,
|
|
'overrides' => [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override_1',
|
|
'If filter matches' => 'Stop processing'
|
|
],
|
|
'Filters' => [
|
|
'Type of calculation' => 'Custom expression',
|
|
'formula' => '(A and B) or (C and D)',
|
|
'filter_conditions' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'macro' => '{#MACRO1}',
|
|
'operator' => 'does not match',
|
|
'value' => 'expression_1'
|
|
],
|
|
[
|
|
'macro' => '{#MACRO2}',
|
|
'operator' => 'matches',
|
|
'value' => 'expression_2'
|
|
],
|
|
[
|
|
'macro' => '{#MACRO3}',
|
|
'operator' => 'exists'
|
|
],
|
|
[
|
|
'macro' => '{#MACRO4}',
|
|
'operator' => 'does not exist'
|
|
]
|
|
]
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Item prototype',
|
|
'Condition' => ['operator' => 'does not match', 'value' => 'item_pattern'],
|
|
'Create enabled' => 'No',
|
|
'Discover' => 'No',
|
|
'History storage period' => [
|
|
'ophistory_history_mode' => 'Storage period',
|
|
'ophistory_history' => '500d'
|
|
],
|
|
'Trend storage period' => [
|
|
'optrends_trends_mode' => 'Storage period',
|
|
'optrends_trends' => '200d'
|
|
]
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '50m',
|
|
'Custom intervals' => [
|
|
['type' => 'Flexible', 'delay' => '60s', 'period' => '1-5,01:01-13:05'],
|
|
['type' => 'Scheduling', 'delay' => 'wd1-3h10-17']
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype',
|
|
'Condition' => ['operator' => 'contains', 'value' => 'trigger_Pattern'],
|
|
'Create enabled' => 'No',
|
|
'Discover' => 'No',
|
|
'Severity' => 'Warning',
|
|
'Tags' => [
|
|
['tag' => 'tag1', 'value' => 'value1'],
|
|
['tag' => 'tag2', 'value' => 'value2']
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Graph prototype',
|
|
'Condition' => ['operator' => 'matches', 'value' => 'Graph_Pattern'],
|
|
'Discover' => 'Yes'
|
|
]
|
|
],
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Condition' => ['operator' => 'does not match', 'value' => 'Host_Pattern'],
|
|
'Create enabled' => 'Yes',
|
|
'Discover' => 'Yes',
|
|
'Link templates' => 'Test Item Template',
|
|
'Host inventory' => 'Disabled'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override_2',
|
|
'If filter matches' => 'Continue overrides'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Graph prototype',
|
|
'Condition' => ['operator' => 'matches', 'value' => '2Graph_Pattern'],
|
|
'Discover' => 'No'
|
|
]
|
|
],
|
|
[
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Condition' => ['operator' => 'does not match', 'value' => '2Host_Pattern'],
|
|
'Create enabled' => 'Yes',
|
|
'Discover' => 'No',
|
|
'Link templates' => 'Test Item Template',
|
|
'Host inventory' => 'Automatic'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'screenshot' => true
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider getCreateData
|
|
*/
|
|
public function testFormLowLevelDiscoveryOverrides_Create($data) {
|
|
$this->overridesCreate($data);
|
|
}
|
|
|
|
private function overridesCreate($data) {
|
|
$this->page->login()->open('host_discovery.php?form=create&context=host&hostid='.self::HOST_ID);
|
|
$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
|
|
$key = 'lld_override'.time();
|
|
$form->fill([
|
|
'Name' => 'LLD with overrides',
|
|
'Key' => $key
|
|
]);
|
|
$form->selectTab('Overrides');
|
|
$form->invalidate();
|
|
$override_container = $form->getField('Overrides')->asTable();
|
|
|
|
// Add overrides from data to lld rule.
|
|
foreach($data['overrides'] as $i => $override){
|
|
$override_container->query('button:Add')->one()->click();
|
|
$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
|
|
// Fill Override name and what to do if Filter matches.
|
|
if (array_key_exists('fields', $override)) {
|
|
$override_overlay->fill($override['fields']);
|
|
}
|
|
$this->fillOverrideFilter($override);
|
|
$this->fillOverrideOperations($data, $override);
|
|
|
|
$this->checkSubmittedOverlay($data['expected'], $override_overlay, CTestArrayHelper::get($override, 'error'));
|
|
|
|
if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
|
|
// Check that Override with correct name was added to Overrides table.
|
|
$this->assertEquals(CTestArrayHelper::get($override, 'fields.Name'),
|
|
$override_container->getRow($i)->getColumn('Name')->getText()
|
|
);
|
|
// Check that Override in table has correct processing status.
|
|
$stop_processing = (CTestArrayHelper::get($override,
|
|
'fields.If filter matches') === 'Stop processing') ? 'Yes' : 'No';
|
|
$this->assertEquals($stop_processing,
|
|
$override_container->getRow($i)->getColumn('Stop processing')->getText()
|
|
);
|
|
}
|
|
}
|
|
|
|
// Take a screenshot to test draggable object position for overrides.
|
|
if (array_key_exists('screenshot', $data)) {
|
|
$this->page->removeFocus();
|
|
$this->assertScreenshot($this->query('class:lld-overrides-table')->one(), 'LLD override');
|
|
}
|
|
|
|
if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
|
|
// Submit LLD create.
|
|
$form->submit();
|
|
$this->assertMessage(TEST_GOOD, 'Discovery rule created');
|
|
self::$created_id = CDBHelper::getValue('SELECT itemid FROM items WHERE key_='.zbx_dbstr($key));
|
|
}
|
|
|
|
$this->checkSavedState($data);
|
|
}
|
|
|
|
/*
|
|
* Overrides data for LLD update.
|
|
*/
|
|
public static function getUpdateData() {
|
|
return [
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'fields' => [
|
|
'Name' => ''
|
|
],
|
|
'error' => 'Incorrect value for field "Name": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Name' => ''
|
|
],
|
|
'error' => 'Incorrect value for field "Name": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Name' => 'Override for update 1'
|
|
],
|
|
'error' => 'Override with name "Override for update 1" already exists.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Object' => 'Item prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Object' => 'Graph prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Object' => 'Host prototype'
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'fields' => [
|
|
'Object' => 'Item prototype',
|
|
'Create enabled' => null,
|
|
'Discover' => null,
|
|
'History storage period' => null,
|
|
'Trend storage period' => null
|
|
],
|
|
'Update interval' => null
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype',
|
|
'Create enabled' => null,
|
|
'Discover' => null,
|
|
'Severity' => null,
|
|
'Tags' => null
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'fields' => [
|
|
'Object' => 'Graph prototype',
|
|
'Discover' => null
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Create enabled' => null,
|
|
'Discover' => null,
|
|
'Link templates' => null,
|
|
'Tags' => null,
|
|
'Host inventory' => null
|
|
]
|
|
]
|
|
],
|
|
'error' => 'At least one action is mandatory.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype',
|
|
'Tags' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'tag' => '',
|
|
'value' => ''
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tags": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Trigger prototype',
|
|
'Tags' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'tag' => '',
|
|
'value' => 'value1'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tag": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Link templates' => []
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Link templates": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Tags' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'tag' => '',
|
|
'value' => ''
|
|
],
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 1
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tags": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Tags' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'tag' => '',
|
|
'value' => 'new_value'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tag": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Tags' => [
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 1
|
|
],
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 0
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Tags": cannot be empty.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Delay' => ''
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Update interval": invalid delay.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Delay' => '0',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 1
|
|
],
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 0
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Item will not be refreshed. Specified update interval requires '.
|
|
'having at least one either flexible or scheduling interval.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Delay' => '2d',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 1
|
|
],
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 0
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Item will not be refreshed. Update interval should be between 1s and 1d. '.
|
|
'Also Scheduled/Flexible intervals can be used.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'delay' => ''
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'period' => ''
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'period' => '1-2'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "1-2".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'Update interval' => [
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'delay' => 'wd1-9'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Invalid interval "wd1-9".'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'fields' => [
|
|
'History storage period' => [
|
|
'ophistory_history_mode' => 'Storage period',
|
|
'ophistory_history' => ''
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "History storage period": a time unit is expected.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_BAD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'fields' => [
|
|
'Trend storage period' => [
|
|
'optrends_trends_mode' => 'Storage period',
|
|
'optrends_trends' => ''
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'error' => 'Incorrect value for field "Trend storage period": a time unit is expected.'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_GOOD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'name' => 'Override for update 1'
|
|
],
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'name' => 'Override for update 2'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_GOOD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Filters' => [
|
|
'formula' => 'A and B and C and D and E',
|
|
'filter_conditions' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'macro' => '{#UPDATED_MACRO3}',
|
|
'operator' => 'does not match',
|
|
'value' => 'ADDED expression_3'
|
|
]
|
|
]
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_ADD,
|
|
'fields' => [
|
|
'Object' => 'Host prototype',
|
|
'Condition' => ['operator' => 'contains', 'value' => 'new host pattern'],
|
|
'Create enabled' => 'No',
|
|
'Discover' => 'Yes',
|
|
'Link templates' => 'Test Item Template',
|
|
'Tags' => [
|
|
['tag' => 'added_name1', 'value' => 'added_value1']
|
|
],
|
|
'Host inventory' => 'Disabled'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_GOOD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'fields' => [
|
|
'Name' => 'Updated Override for update 1',
|
|
'If filter matches' => 'Stop processing'
|
|
],
|
|
'Filters' => [
|
|
'Type of calculation' => 'Custom expression',
|
|
'formula' => 'A and B and C and D',
|
|
'filter_conditions' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'macro' => '{#UPDATED_MACRO1}',
|
|
'operator' => 'does not match',
|
|
'value' => 'UPDATED expression_1'
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'macro' => '{#UPDATED_MACRO2}',
|
|
'operator' => 'matches',
|
|
'value' => 'UPDATED expression_2'
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 2,
|
|
'macro' => '{#UPDATED_MACRO3}',
|
|
'operator' => 'does not exist'
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 3,
|
|
'macro' => '{#UPDATED_MACRO4}',
|
|
'operator' => 'exists'
|
|
]
|
|
]
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'fields' => [
|
|
'Create enabled' => 'No',
|
|
'Discover' => 'No',
|
|
'History storage period' => [
|
|
'ophistory_history_mode' => 'Storage period',
|
|
'ophistory_history' => '500d'
|
|
],
|
|
'Trend storage period' => [
|
|
'optrends_trends_mode' => 'Storage period',
|
|
'optrends_trends' => '200d'
|
|
]
|
|
],
|
|
'Update interval' => [
|
|
'Delay' => '50m',
|
|
'Custom intervals' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'type' => 'Scheduling',
|
|
'delay' => 'wd1-3h10-17'
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'type' => 'Flexible',
|
|
'delay' => '60s',
|
|
'period' => '1-5,01:01-13:05'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Create enabled' => 'No',
|
|
'Discover' => 'Yes',
|
|
'Severity' => null,
|
|
'Tags' => null
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 0,
|
|
'fields' => [
|
|
'Discover' => 'No'
|
|
]
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'index' => 1,
|
|
'fields' => [
|
|
'Create enabled' => 'No',
|
|
'Discover' =>'Yes',
|
|
'Link templates' => null,
|
|
'Tags' => null,
|
|
'Host inventory' => null
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
[
|
|
'expected' => TEST_GOOD,
|
|
'overrides' => [
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 1',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 1,
|
|
'fields' =>
|
|
[
|
|
'Object' => 'Trigger prototype',
|
|
'Condition' => ['operator' => 'does not equal', 'value' => 'test trigger pattern']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'action' => USER_ACTION_UPDATE,
|
|
'name' => 'Override for update 2',
|
|
'Operations' => [
|
|
[
|
|
'action' => USER_ACTION_REMOVE,
|
|
'index' => 1,
|
|
'fields' =>
|
|
[
|
|
'Object' => 'Host prototype',
|
|
'Condition' => ['operator' => 'does not match', 'value' => 'test host pattern']
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider getUpdateData
|
|
*
|
|
* @backup items
|
|
*/
|
|
public function testFormLowLevelDiscoveryOverrides_Update($data) {
|
|
$this->overridesUpdate($data);
|
|
}
|
|
|
|
private function overridesUpdate($data) {
|
|
self::$old_hash = CDBHelper::getHash('SELECT * FROM items WHERE flags=1 ORDER BY itemid');
|
|
$this->page->login()->open('host_discovery.php?form=update&context=host&itemid='.self::UPDATED_ID);
|
|
$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
|
|
$form->selectTab('Overrides');
|
|
$form->invalidate();
|
|
$override_container = $form->getField('Overrides')->asTable();
|
|
|
|
$sources = [
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override for update 1',
|
|
'If filter matches' => 'Continue overrides'
|
|
],
|
|
'Filters' => [
|
|
'Type of calculation' => 'And',
|
|
'formula' => 'A and B and C and D',
|
|
'filter_conditions' => [
|
|
[
|
|
'macro' => '{#MACRO1}',
|
|
'operator' => 'matches',
|
|
'value' => 'test expression_1'
|
|
],
|
|
[
|
|
'macro' => '{#MACRO2}',
|
|
'operator' => 'does not match',
|
|
'value' => 'test expression_2'
|
|
],
|
|
[
|
|
'macro' => '{#MACRO3}',
|
|
'operator' => 'exists'
|
|
],
|
|
[
|
|
'macro' => '{#MACRO4}',
|
|
'operator' => 'does not exist'
|
|
]
|
|
]
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'Object' => 'Item prototype',
|
|
'Condition' => ['operator' => 'equals', 'value' => 'test item pattern'],
|
|
'Create enabled' => 'Yes',
|
|
'Discover' => 'Yes',
|
|
// TODO: uncomment after fix DEV-1071 and it is possible to check this field.
|
|
// 'Update interval' => [
|
|
// 'Delay' => '1m',
|
|
// 'Custom intervals' => [
|
|
// ['type' => 'Flexible', 'delay' => '50s', 'period' => '1-7,00:00-24:00'],
|
|
// ['type' => 'Scheduling', 'delay' => 'wd1-5h9-18']
|
|
// ]
|
|
// ],
|
|
'History storage period' => ['ophistory_history_mode' => 'Do not keep history'],
|
|
'Trend storage period' => ['optrends_trends_mode' => 'Do not keep trends']
|
|
],
|
|
[
|
|
'Object' => 'Trigger prototype',
|
|
'Condition' => ['operator' => 'does not equal', 'value' => 'test trigger pattern'],
|
|
'Create enabled' => null,
|
|
'Discover' => null,
|
|
'Severity' => 'Warning',
|
|
'Tags' => [
|
|
['tag' => 'tag1', 'value' => 'value1']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
[
|
|
'fields' => [
|
|
'Name' => 'Override for update 2',
|
|
'If filter matches' => 'Continue overrides'
|
|
],
|
|
'Operations' => [
|
|
[
|
|
'Object' => 'Graph prototype',
|
|
'Condition' => ['operator' => 'matches', 'value' => 'test graph pattern'],
|
|
'Discover' => 'Yes'
|
|
],
|
|
[
|
|
'Object' => 'Host prototype',
|
|
'Condition' => ['operator' => 'does not match', 'value' => 'test host pattern'],
|
|
'Create enabled' => null,
|
|
'Discover' => null,
|
|
'Link templates' => 'Test Item Template',
|
|
'Tags' => [
|
|
['tag' => 'name1', 'value' => 'value1'],
|
|
['tag' => 'name2', 'value' => 'value2']
|
|
],
|
|
'Host inventory' => 'Automatic'
|
|
]
|
|
]
|
|
]
|
|
];
|
|
|
|
foreach ($data['overrides'] as $i => $override) {
|
|
$override_action = CTestArrayHelper::get($override, 'action', USER_ACTION_ADD);
|
|
|
|
// Preparing reference data for overrides.
|
|
switch ($override_action) {
|
|
case USER_ACTION_ADD:
|
|
$sources[] = $override;
|
|
break;
|
|
|
|
case USER_ACTION_REMOVE:
|
|
foreach ($sources as $id => $source) {
|
|
if ($source['fields']['Name'] === $override['name']) {
|
|
unset($sources[$id]);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case USER_ACTION_UPDATE:
|
|
// Find overrides by name.
|
|
foreach ($sources as $id => $source) {
|
|
if ($source['fields']['Name'] === $override['name']) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->assertNotNull($id, 'Cannot find reference data by override name '.$override['name']);
|
|
|
|
// Check if source has fields from data to update them.
|
|
foreach (CTestArrayHelper::get($override, 'fields', []) as $key => $value) {
|
|
$this->assertArrayHasKey($key, $sources[$id]['fields'], 'Cannot find field '.$key.' in source');
|
|
$sources[$id]['fields'][$key] = $value;
|
|
}
|
|
|
|
// Preparing reference data for Filter conditions.
|
|
$conditions = [];
|
|
foreach (CTestArrayHelper::get($override, 'Filters', []) as $key => $value) {
|
|
if ($key === 'filter_conditions') {
|
|
$conditions = $value;
|
|
continue;
|
|
}
|
|
|
|
$sources[$id]['Filters'][$key] = $value;
|
|
}
|
|
|
|
foreach ($conditions as $condition) {
|
|
switch($condition['action']) {
|
|
case USER_ACTION_ADD:
|
|
$sources[$id]['Filters']['filter_conditions'][] = $condition;
|
|
break;
|
|
|
|
case USER_ACTION_UPDATE:
|
|
foreach ($condition as $key => $value) {
|
|
// Skipping 'action' and 'index' fields from reference data.
|
|
if (in_array($key, ['action', 'index'])) {
|
|
continue;
|
|
}
|
|
|
|
$sources[$id]['Filters']['filter_conditions'][$condition['index']][$key] = $value;
|
|
}
|
|
break;
|
|
|
|
case USER_ACTION_REMOVE:
|
|
unset($sources[$id]['Filters']['filter_conditions'][$condition['index']]);
|
|
break;
|
|
}
|
|
}
|
|
// Open Override overlay.
|
|
$override_container->query('link', $override['name'])->one()->click();
|
|
$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
|
|
// Get Operations Table.
|
|
$operations_container = $override_overlay->getField('Operations')->asTable();
|
|
|
|
foreach (CTestArrayHelper::get($override, 'Operations', []) as $j => $operation) {
|
|
$operation_action = CTestArrayHelper::get($operation, 'action', USER_ACTION_ADD);
|
|
// Preparing reference data for Operations.
|
|
switch ($operation_action) {
|
|
case USER_ACTION_ADD:
|
|
$temp = $operation['fields'];
|
|
if (array_key_exists('Update interval', $operation)) {
|
|
$temp['Update interval'] = $operation['Update interval'];
|
|
}
|
|
$sources[$id]['Operations'][] = $temp;
|
|
break;
|
|
case USER_ACTION_UPDATE:
|
|
// Check if source has Operations from data to update them.
|
|
foreach (CTestArrayHelper::get($operation, 'fields', []) as $key => $value) {
|
|
// Skipping 'action' and 'index' fields from reference data.
|
|
if (in_array($key, ['action', 'index'])) {
|
|
continue;
|
|
}
|
|
|
|
$this->assertArrayHasKey($key, $sources[$id]['Operations'][$operation['index']],
|
|
'Cannot find field '.$key.' in source');
|
|
$sources[$id]['Operations'][$operation['index']][$key] = $value;
|
|
}
|
|
|
|
break;
|
|
case USER_ACTION_REMOVE:
|
|
unset($sources[$id]['Operations'][$operation['index']]);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch ($override_action) {
|
|
// Perform adding or updating Override.
|
|
case USER_ACTION_ADD:
|
|
$override_container->query('button:Add')->one()->click();
|
|
$id = null;
|
|
case USER_ACTION_UPDATE:
|
|
// Fill Override name and what to do if Filter matches.
|
|
if (array_key_exists('fields', $override)) {
|
|
$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
$override_overlay->fill($override['fields']);
|
|
}
|
|
$this->fillOverrideFilter($override);
|
|
$this->fillOverrideOperations($data, $override, $sources, $id);
|
|
$this->checkSubmittedOverlay($data['expected'], $override_overlay,
|
|
CTestArrayHelper::get($override, 'error'));
|
|
|
|
if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
|
|
// Check that Override with correct name was added to Overrides table.
|
|
$fields = (CTestArrayHelper::get($override, 'fields'))
|
|
? $override['fields']['Name']
|
|
: $sources[$i]['fields']['Name'];
|
|
$this->assertEquals($fields, $override_container->getRow($i)->getColumn('Name')->getText());
|
|
// Check that Override in table has correct processing status.
|
|
$stop_processing = (CTestArrayHelper::get($override,
|
|
'fields.If filter matches') === 'Stop processing') ? 'Yes' : 'No';
|
|
$this->assertEquals($stop_processing, $override_container->getRow($i)->getColumn('Stop processing')
|
|
->getText());
|
|
}
|
|
break;
|
|
|
|
case USER_ACTION_REMOVE:
|
|
$override_container->findRow('Name', $override['name'])->query('button:Remove')->one()->click();
|
|
break;
|
|
|
|
default:
|
|
throw new Exception('Cannot perform action "'.$override_action.'".');
|
|
}
|
|
}
|
|
|
|
if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
|
|
// Submit LLD update.
|
|
$form->submit();
|
|
$this->assertMessage(TEST_GOOD, 'Discovery rule updated');
|
|
$this->assertEquals(1, CDBHelper::getCount('SELECT NULL FROM items WHERE itemid ='.self::UPDATED_ID));
|
|
|
|
self::$created_id = self::UPDATED_ID;
|
|
$this->checkSavedState(['overrides' => $sources]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array $override override fields from data
|
|
*
|
|
* @return CFormElement $override_overlay override or condition form in overlay
|
|
*/
|
|
private function fillOverrideFilter($override) {
|
|
$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
|
|
// Add Filters to override.
|
|
if (array_key_exists('Filters', $override)) {
|
|
$filters_table = $override_overlay->query('id:overrides_filters')->asMultifieldTable()->one();
|
|
$mapping = $this->setFiltersTableMapping($filters_table);
|
|
$filters_table->setFieldMapping($mapping)->fill($override['Filters']['filter_conditions']);
|
|
|
|
// Add Type of calculation if there are more then 2 filters.
|
|
if (array_key_exists('Type of calculation', $override['Filters'])) {
|
|
$override_overlay->query('name:overrides_evaltype')->waitUntilPresent()->one()
|
|
->asDropdown()->fill($override['Filters']['Type of calculation']);
|
|
|
|
// Add formula if Type of calculation is Custom.
|
|
if (array_key_exists('formula', $override['Filters'])) {
|
|
$override_overlay->query('id:overrides_formula')->waitUntilPresent()->one()
|
|
->fill($override['Filters']['formula']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array $data data provider
|
|
* @param array $override override fields from data
|
|
*
|
|
* @return CFormElement $override_overlay override or condition form in overlay
|
|
*/
|
|
private function fillOverrideOperations($data, $override, $sources = null, $id = null) {
|
|
$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
$operation_container = $override_overlay->getField('Operations')->asTable();
|
|
|
|
// Add Operations to override.
|
|
foreach(CTestArrayHelper::get($override, 'Operations', []) as $i => $operation){
|
|
|
|
$operation_action = CTestArrayHelper::get($operation, 'action', USER_ACTION_ADD);
|
|
unset($operation['action']);
|
|
|
|
$row = null;
|
|
switch ($operation_action) {
|
|
case USER_ACTION_ADD:
|
|
$row = $operation_container->getRows()->count() - 1;
|
|
$operation_container->query('button:Add')->one()->click();
|
|
break;
|
|
|
|
case USER_ACTION_UPDATE:
|
|
$row = $operation['index'];
|
|
$operation_container->getRow($row)->query('button:Edit')->one()->click();
|
|
unset($operation['index']);
|
|
break;
|
|
}
|
|
|
|
switch ($operation_action) {
|
|
case USER_ACTION_ADD:
|
|
case USER_ACTION_UPDATE:
|
|
$operation_overlay = $this->query('id:lldoperation_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
if (array_key_exists('fields', $operation)) {
|
|
$operation_overlay->fill($operation['fields']);
|
|
}
|
|
|
|
// Fill Delay and Intervals.
|
|
if (array_key_exists('Update interval', $operation)) {
|
|
if ($operation['Update interval'] !== null) {
|
|
$intervals = $operation_overlay->getField('Update interval');
|
|
$operation_overlay->query('id:visible_opperiod')->one()->fill(true);
|
|
if (array_key_exists('Delay', $operation['Update interval'])) {
|
|
$intervals->query('id:opperiod_delay')->waitUntilVisible()->one()
|
|
->fill($operation['Update interval']['Delay']);
|
|
}
|
|
if (array_key_exists('Custom intervals', $operation['Update interval'])) {
|
|
$this->query('xpath:.//table[@id="lld_overrides_custom_intervals"]')
|
|
->asMultifieldTable(['mapping' => self::INTERVAL_MAPPING])->one()
|
|
->fill($operation['Update interval']['Custom intervals']);
|
|
}
|
|
}
|
|
else {
|
|
$operation_overlay->query('id:visible_opperiod')->one()->asCheckbox()->fill(false);
|
|
}
|
|
}
|
|
|
|
$operation_overlay->submit();
|
|
$this->checkSubmittedOverlay($data['expected'], $operation_overlay,
|
|
CTestArrayHelper::get($override, 'error')
|
|
);
|
|
|
|
if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
|
|
// Check that Operation was added to Operations table.
|
|
$object = CTestArrayHelper::get($operation, 'fields.Object');
|
|
if ($object === null) {
|
|
$object = $sources[$id]['Operations'][$i]['Object'];
|
|
}
|
|
|
|
$operator = CTestArrayHelper::get($operation, 'fields.Condition.operator');
|
|
if ($operator === null) {
|
|
$operator = $sources[$id]['Operations'][$i]['Condition']['operator'];
|
|
}
|
|
|
|
$value = CTestArrayHelper::get($operation, 'fields.Condition.value');
|
|
if ($value === null) {
|
|
$value = $sources[$id]['Operations'][$i]['Condition']['value'];
|
|
}
|
|
|
|
$condition_text = $object.' '.$operator.' '.$value;
|
|
$this->assertEquals($condition_text,
|
|
$operation_container->getRow($row)->getColumn('Condition')->getText()
|
|
);
|
|
}
|
|
break;
|
|
|
|
case USER_ACTION_REMOVE:
|
|
$condition_text = $operation['fields']['Object'].' '.
|
|
$operation['fields']['Condition']['operator'].' '.
|
|
$operation['fields']['Condition']['value'];
|
|
$row = $operation_container->findRow('Condition', $condition_text)->query('button:Remove')->one()->click();
|
|
$row->waitUntilNotPresent();
|
|
break;
|
|
}
|
|
}
|
|
// Submit Override.
|
|
$override_overlay->submit();
|
|
}
|
|
|
|
/**
|
|
* Function for checking successful/failed overlay submitting.
|
|
*
|
|
* @param string $expected case GOOD or BAD
|
|
* @param CFormElement $overlay override or condition form in overlay
|
|
* @param string $error error message text
|
|
*/
|
|
private function checkSubmittedOverlay($expected, $overlay, $error) {
|
|
switch ($expected) {
|
|
case TEST_GOOD:
|
|
$overlay->waitUntilNotPresent();
|
|
break;
|
|
case TEST_BAD:
|
|
$this->assertMessage(TEST_BAD, null, $error);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private function checkSavedState($data) {
|
|
// Skip Bad cases.
|
|
if (CTestArrayHelper::get($data, 'expected') === TEST_BAD) {
|
|
return;
|
|
}
|
|
|
|
// Open saved LLD.
|
|
$this->page->login()->open('host_discovery.php?form=update&context=host&itemid='.self::$created_id);
|
|
$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
|
|
$form->selectTab('Overrides');
|
|
$override_container = $form->getField('Overrides')->asTable();
|
|
// Get Overrides count.
|
|
$overrides_count = $override_container->getRows()->count();
|
|
|
|
// Write Override names from data to array.
|
|
foreach ($data['overrides'] as $override) {
|
|
$override_names[] = $override['fields']['Name'];
|
|
$stop_processing[] = (CTestArrayHelper::get($override['fields'],
|
|
'If filter matches') === 'Stop processing') ? 'Yes' : 'No';
|
|
}
|
|
|
|
// Compare Override names from table with data.
|
|
for ($k = 0; $k < $overrides_count - 1; $k++) {
|
|
$this->assertEquals($override_names[$k],
|
|
$override_container->getRow($k)->getColumn('Name')->getText()
|
|
);
|
|
// Check that Override in table has correct processing status.
|
|
$this->assertEquals($stop_processing[$k],
|
|
$override_container->getRow($k)->getColumn('Stop processing')->getText()
|
|
);
|
|
}
|
|
|
|
foreach ($data['overrides'] as $override) {
|
|
// Open each override dialog.
|
|
$row = $override_container->findRow('Name', $override['fields']['Name']);
|
|
$row->query('link', $override['fields']['Name'])->one()->click();
|
|
$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
|
|
// Check that Override fields filled with correct data.
|
|
foreach ($override['fields'] as $field => $value) {
|
|
$override_overlay->getField($field)->checkValue($value);
|
|
}
|
|
|
|
if (array_key_exists('Filters', $override)) {
|
|
foreach ($override['Filters']['filter_conditions'] as &$condition) {
|
|
unset($condition['index']);
|
|
unset($condition['action']);
|
|
}
|
|
unset($condition);
|
|
|
|
// Check that Filters are filled correctly.
|
|
$filters_table = $override_overlay->query('id:overrides_filters')->asMultifieldTable()->one();
|
|
$mapping = $this->setFiltersTableMapping($filters_table);
|
|
$filters_table->setFieldMapping($mapping)->checkValue($override['Filters']['filter_conditions']);
|
|
|
|
// Check that Evaluation type is filled correctly.
|
|
if (array_key_exists('Type of calculation', $override['Filters'])) {
|
|
$evaluation_type = $override_overlay->query('name:overrides_evaltype')->one()->asDropdown()->getValue();
|
|
$this->assertEquals($override['Filters']['Type of calculation'], $evaluation_type);
|
|
|
|
// Check that Formula is filled correctly.
|
|
if (array_key_exists('formula', $override['Filters'])) {
|
|
$formula = CTestArrayHelper::get($override['Filters'], 'Type of calculation') !== 'Custom expression'
|
|
? $override_overlay->query('id:overrides_expression')->one()->getText()
|
|
: $override_overlay->query('id:overrides_formula')->one()->getValue();
|
|
$this->assertEquals($override['Filters']['formula'], $formula);
|
|
}
|
|
}
|
|
}
|
|
|
|
$operation_container = $override_overlay->getField('Operations')->asTable();
|
|
// Get Operations count.
|
|
$operation_count = $operation_container->getRows()->count();
|
|
|
|
if (array_key_exists('Operations', $override)) {
|
|
// Write Conditions from data to array.
|
|
$condition_text = [];
|
|
foreach ($override['Operations'] as $operation) {
|
|
$fields = array_key_exists('fields', $operation) ? $operation['fields'] : $operation;
|
|
|
|
$condition_text[] = $fields['Object'].' '.
|
|
$fields['Condition']['operator'].' '.
|
|
$fields['Condition']['value'];
|
|
}
|
|
|
|
// Compare Conditions from table with data.
|
|
$actual_conditions = [];
|
|
for ($n = 0; $n < $operation_count - 1; $n++) {
|
|
$actual_conditions[] = $operation_container->getRow($n)->getColumn('Condition')->getText();
|
|
}
|
|
$this->assertEquals($condition_text, $actual_conditions);
|
|
|
|
foreach ($override['Operations'] as $i => $operation) {
|
|
$operation_container->getRow($i)->query('button:Edit')->one()->click();
|
|
$operation_overlay = $this->query('id:lldoperation_form')->waitUntilPresent()->asCheckboxForm()->one();
|
|
$operation_overlay->checkValue(
|
|
array_key_exists('fields', $operation) ? $operation['fields'] : $operation
|
|
);
|
|
|
|
// Close Operation dialog.
|
|
$operation_overlay->submit()->waitUntilNotPresent();
|
|
}
|
|
}
|
|
|
|
// Close Override dialog.
|
|
COverlayDialogElement::find()->one()->close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function for updating the mapping of the specified Filters multi-field table.
|
|
*
|
|
* @param CMultifieldTableElement $filters_table table which mapping needs to be updated
|
|
*
|
|
* @return array
|
|
*/
|
|
private function setFiltersTableMapping($filters_table) {
|
|
$mapping = $filters_table->detectFieldMapping();
|
|
$mapping['Regular expression']['name'] = 'value';
|
|
$mapping['Regular expression']['selector'] = 'xpath:./div/input';
|
|
|
|
return $mapping;
|
|
}
|
|
}
|