diff --git a/library/Director/CustomVariable/CustomVariable.php b/library/Director/CustomVariable/CustomVariable.php index 4d8d70fb..e028475f 100644 --- a/library/Director/CustomVariable/CustomVariable.php +++ b/library/Director/CustomVariable/CustomVariable.php @@ -88,12 +88,12 @@ abstract class CustomVariable implements IcingaConfigRenderer return $this->modified; } - public function toConfigStringPrefetchable() + public function toConfigStringPrefetchable($renderExpressions = false) { if (PrefetchCache::shouldBeUsed()) { - return PrefetchCache::instance()->renderVar($this); + return PrefetchCache::instance()->renderVar($this, $renderExpressions); } else { - return $this->toConfigString(); + return $this->toConfigString($renderExpressions); } } diff --git a/library/Director/CustomVariable/CustomVariableString.php b/library/Director/CustomVariable/CustomVariableString.php index b67b3322..11942769 100644 --- a/library/Director/CustomVariable/CustomVariableString.php +++ b/library/Director/CustomVariable/CustomVariableString.php @@ -36,8 +36,12 @@ class CustomVariableString extends CustomVariable return $this; } - public function toConfigString() + public function toConfigString($renderExpressions = false) { - return c::renderString($this->getValue()); + if ($renderExpressions) { + return c::renderStringWithVariables($this->getValue()); + } else { + return c::renderString($this->getValue()); + } } } diff --git a/library/Director/CustomVariable/CustomVariables.php b/library/Director/CustomVariable/CustomVariables.php index 3ce0bb00..3bec8924 100644 --- a/library/Director/CustomVariable/CustomVariables.php +++ b/library/Director/CustomVariable/CustomVariables.php @@ -268,24 +268,24 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer return $this->storedVars; } - public function toConfigString() + public function toConfigString($renderExpressions = false) { $out = ''; ksort($this->vars); foreach ($this->vars as $key => $var) { // TODO: ctype_alnum + underscore? - $out .= $this->renderSingleVar($key, $var); + $out .= $this->renderSingleVar($key, $var, $renderExpressions); } return $out; } - protected function renderSingleVar($key, $var) + protected function renderSingleVar($key, $var, $renderExpressions = false) { return c::renderKeyValue( $this->renderKeyName($key), - $var->toConfigStringPrefetchable() + $var->toConfigStringPrefetchable($renderExpressions) ); } diff --git a/library/Director/Db/Cache/PrefetchCache.php b/library/Director/Db/Cache/PrefetchCache.php index ec5a910d..86fd922b 100644 --- a/library/Director/Db/Cache/PrefetchCache.php +++ b/library/Director/Db/Cache/PrefetchCache.php @@ -84,14 +84,14 @@ class PrefetchCache } */ - public function renderVar(CustomVariable $var) + public function renderVar(CustomVariable $var, $renderExpressions = false) { $checksum = $var->getChecksum(); if (null === $checksum) { - return $var->toConfigString(); + return $var->toConfigString($renderExpressions); } else { if (! array_key_exists($checksum, $this->renderedVars)) { - $this->renderedVars[$checksum] = $var->toConfigString(); + $this->renderedVars[$checksum] = $var->toConfigString($renderExpressions); } return $this->renderedVars[$checksum]; diff --git a/library/Director/IcingaConfig/IcingaConfigHelper.php b/library/Director/IcingaConfig/IcingaConfigHelper.php index 71e4a5bc..f76ad167 100644 --- a/library/Director/IcingaConfig/IcingaConfigHelper.php +++ b/library/Director/IcingaConfig/IcingaConfigHelper.php @@ -257,4 +257,22 @@ class IcingaConfigHelper return $seconds . 's'; } + + public static function renderStringWithVariables($string) + { + $string = preg_replace( + '/(?prioritizedProperties */); + $blacklist = array_merge($this->propertiesNotForRendering, + array() /* $this->prioritizedProperties */); foreach ($this->properties as $key => $value) { if (in_array($key, $blacklist)) { @@ -1706,7 +1703,12 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->renderRelationProperty($relKey, $value); } - return c::renderKeyValue($key, c::renderString($value)); + return c::renderKeyValue( + $key, + $this->isApplyRule() ? + c::renderStringWithVariables($value) : + c::renderString($value) + ); } protected function renderLegacyObjectProperty($key, $value) @@ -1783,7 +1785,7 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer protected function renderCustomVars() { if ($this->supportsCustomVars()) { - return $this->vars()->toConfigString(); + return $this->vars()->toConfigString($this->isApplyRule()); } else { return ''; } diff --git a/test/php/library/Director/CustomVariable/CustomVariablesTest.php b/test/php/library/Director/CustomVariable/CustomVariablesTest.php index f6d91873..ba1e25a6 100644 --- a/test/php/library/Director/CustomVariable/CustomVariablesTest.php +++ b/test/php/library/Director/CustomVariable/CustomVariablesTest.php @@ -44,6 +44,21 @@ class CustomVariablesTest extends BaseTestCase ); } + public function testVariablesToExpression() + { + $vars = $this->newVars(); + $vars->bla = 'da'; + $vars->abc = '$val$'; + $expected = $this->indentVarsList(array( + 'vars.abc = val', + 'vars.bla = "da"' + )); + $this->assertEquals( + $vars->toConfigString(true), + $expected + ); + } + protected function indentVarsList($vars) { return $this->indent . implode( diff --git a/test/php/library/Director/IcingaConfig/IcingaConfigHelperTest.php b/test/php/library/Director/IcingaConfig/IcingaConfigHelperTest.php index c73b5bb8..bb5955a0 100644 --- a/test/php/library/Director/IcingaConfig/IcingaConfigHelperTest.php +++ b/test/php/library/Director/IcingaConfig/IcingaConfigHelperTest.php @@ -69,4 +69,38 @@ class IcingaConfigHelperTest extends BaseTestCase { return file_get_contents(__DIR__ . '/rendered/' . $name . '.out'); } + + public function testRenderStringIsCorrectlyRendered() + { + $this->assertEquals(c::renderString('val1\\\val2'), '"val1\\\\\\\\val2"'); + $this->assertEquals(c::renderString('"val1"'), '"\"val1\""'); + $this->assertEquals(c::renderString('\$val\$'), '"\\\\$val\\\\$"'); + $this->assertEquals(c::renderString('\t'), '"\\\\t"'); + $this->assertEquals(c::renderString('\r'), '"\\\\r"'); + $this->assertEquals(c::renderString('\n'), '"\\\\n"'); + $this->assertEquals(c::renderString('\f'), '"\\\\f"'); + } + + public function testRenderStringWithVariables() + { + $this->assertEquals(c::renderStringWithVariables('Before $var$'), '"Before " + var'); + $this->assertEquals(c::renderStringWithVariables('$var$ After'), 'var + " After"'); + $this->assertEquals(c::renderStringWithVariables('$var$'), 'var'); + $this->assertEquals(c::renderStringWithVariables('$$var$$'), '"$$var$$"'); + $this->assertEquals(c::renderStringWithVariables('Before $$var$$ After'), '"Before $$var$$ After"'); + $this->assertEquals( + c::renderStringWithVariables('Before $name$ $name$ After'), + '"Before " + name + " " + name + " After"' + ); + $this->assertEquals( + c::renderStringWithVariables('Before $var1$ $var2$ After'), + '"Before " + var1 + " " + var2 + " After"' + ); + $this->assertEquals(c::renderStringWithVariables('$host.vars.custom$'), 'host.vars.custom'); + $this->assertEquals(c::renderStringWithVariables('$var"$'), '"$var\"$"'); + $this->assertEquals( + c::renderStringWithVariables('\tI am\rrendering\nproperly\fand I $support$ "multiple" $variables$\$'), + '"\\\\tI am\\\\rrendering\\\\nproperly\\\\fand I " + support + " \"multiple\" " + variables + "\\\\$"' + ); + } } diff --git a/test/php/library/Director/Objects/IcingaServiceTest.php b/test/php/library/Director/Objects/IcingaServiceTest.php index 590ad76d..07fea36c 100644 --- a/test/php/library/Director/Objects/IcingaServiceTest.php +++ b/test/php/library/Director/Objects/IcingaServiceTest.php @@ -13,6 +13,8 @@ class IcingaServiceTest extends BaseTestCase protected $testServiceName = '___TEST___service'; + protected $createdServices = array(); + public function testUnstoredHostCanBeLazySet() { $service = $this->service(); @@ -233,6 +235,51 @@ class IcingaServiceTest extends BaseTestCase ); } + public function testVariablesInPropertiesAndCustomVariables() + { + if ($this->skipForMissingDb()) { + return; + } + + $db = $this->getDb(); + + $service = $this->service('___TEST___service_$not_replaced$'); + $service->object_type = 'apply'; + $service->display_name = 'Service: $host.vars.replaced$'; + $service->assignments = array( + 'host.address="127.*"', + ); + $service->{'vars.custom_var'} = '$host.vars.replaced$'; + $service->store($db); + + $service = IcingaService::loadWithAutoIncId($service->id, $db); + $this->assertEquals( + $this->loadRendered('service3'), + (string) $service + ); + } + + public function testVariablesAreNotReplacedForNonApplyObjects() + { + if ($this->skipForMissingDb()) { + return; + } + + $db = $this->getDb(); + + $service = $this->service('___TEST___service_$not_replaced$'); + $service->object_type = 'object'; + $service->display_name = 'Service: $host.vars.not_replaced$'; + $service->{'vars.custom_var'} = '$host.vars.not_replaced$'; + $service->store($db); + + $service = IcingaService::loadWithAutoIncId($service->id, $db); + $this->assertEquals( + $this->loadRendered('service4'), + (string) $service + ); + } + protected function host() { return IcingaHost::create(array( @@ -242,10 +289,14 @@ class IcingaServiceTest extends BaseTestCase )); } - protected function service() + protected function service($objectName = null) { + if ($objectName === null) { + $objectName = $this->testServiceName; + } + $this->createdServices[] = $objectName; return IcingaService::create(array( - 'object_name' => $this->testServiceName, + 'object_name' => $objectName, 'object_type' => 'object', 'display_name' => 'Whatever service', 'vars' => array( @@ -279,7 +330,7 @@ class IcingaServiceTest extends BaseTestCase } } - $kill = array($this->testServiceName); + $kill = $this->createdServices; foreach ($kill as $name) { if (IcingaService::exists(array($name), $db)) { IcingaService::load($name, $db)->delete(); diff --git a/test/php/library/Director/Objects/rendered/service3.out b/test/php/library/Director/Objects/rendered/service3.out new file mode 100644 index 00000000..ad39128a --- /dev/null +++ b/test/php/library/Director/Objects/rendered/service3.out @@ -0,0 +1,16 @@ +apply Service "___TEST___service_$not_replaced$" { + display_name = "Service: " + host.vars.replaced + vars.custom_var = host.vars.replaced + vars.test1 = "string" + vars.test2 = 17 + vars.test3 = false + vars.test4 = { + a = [ "dict", "ionary" ] + @this = "is" + } + + assign where match("127.*", host.address) + + import DirectorOverrideTemplate +} + diff --git a/test/php/library/Director/Objects/rendered/service4.out b/test/php/library/Director/Objects/rendered/service4.out new file mode 100644 index 00000000..ef87fc83 --- /dev/null +++ b/test/php/library/Director/Objects/rendered/service4.out @@ -0,0 +1,12 @@ +object Service "___TEST___service_$not_replaced$" { + display_name = "Service: $host.vars.not_replaced$" + vars.custom_var = "$host.vars.not_replaced$" + vars.test1 = "string" + vars.test2 = 17 + vars.test3 = false + vars.test4 = { + a = [ "dict", "ionary" ] + @this = "is" + } +} +