void ConfigType::ValidateItem(const ConfigItem::Ptr& item) { /* Don't validate abstract items. */ if (item->IsAbstract()) return; Dictionary::Ptr attrs; DebugInfo debugInfo; String type, name; { ObjectLock olock(item); attrs = item->GetProperties(); debugInfo = item->GetDebugInfo(); type = item->GetType(); name = item->GetName(); } std::vector<String> locations; locations.push_back("Object '" + name + "' (Type: '" + type + "') at " + debugInfo.Path + ":" + Convert::ToString(debugInfo.FirstLine)); std::vector<TypeRuleList::Ptr> ruleLists; AddParentRules(ruleLists, GetSelf()); ruleLists.push_back(m_RuleList); ValidateDictionary(attrs, ruleLists, locations); }
void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); Log(LogDebug, "ScheduledDowntime") << "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); builder->SetType("ScheduledDowntime"); builder->SetName(name); builder->SetScope(locals); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di)); if (service) builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di)); String zone = checkable->GetZone(); if (!zone.IsEmpty()) { builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di)); } builder->AddExpression(new OwnedExpression(rule.GetExpression())); ConfigItem::Ptr downtimeItem = builder->Compile(); DynamicObject::Ptr dobj = downtimeItem->Commit(); dobj->OnConfigLoaded(); }
bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule) { if (!rule.EvaluateFilter(frame)) return false; DebugInfo di = rule.GetDebugInfo(); Log(LogDebug, "Service") << "Applying service '" << name << "' to host '" << host->GetName() << "' for rule " << di; ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); builder->SetType("Service"); builder->SetName(name); builder->SetScope(frame.Locals->ShallowClone()); builder->SetIgnoreOnError(rule.GetIgnoreOnError()); builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di)); builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "name"), OpSetLiteral, MakeLiteral(name), di)); String zone = host->GetZoneName(); if (!zone.IsEmpty()) builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "package"), OpSetLiteral, MakeLiteral(rule.GetPackage()), di)); builder->AddExpression(new OwnedExpression(rule.GetExpression())); ConfigItem::Ptr serviceItem = builder->Compile(); serviceItem->Register(); return true; }
bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigItem::Ptr& group) { String group_name = group->GetName(); CONTEXT("Evaluating rule for group '" + group_name + "'"); Host::Ptr host = service->GetHost(); ScriptFrame frame; if (group->GetScope()) group->GetScope()->CopyTo(frame.Locals); frame.Locals->Set("host", host); frame.Locals->Set("service", service); if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool()) return false; Log(LogDebug, "ServiceGroup") << "Assigning membership for group '" << group_name << "' to service '" << service->GetName() << "'"; Array::Ptr groups = service->GetGroups(); groups->Add(group_name); return true; }
ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const { if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo)); String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo); ExpressionResult nameres = m_Name->Evaluate(frame); CHECK_RESULT(nameres); Value name = nameres.GetValue(); if (!name.IsString()) BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo)); ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(Type::GetByName(type), name); if (!item) BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo)); Dictionary::Ptr scope = item->GetScope(); if (scope) scope->CopyTo(frame.Locals); ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint); CHECK_RESULT(result); return Empty; }
static Dictionary::Ptr GetTargetForTemplate(const ConfigItem::Ptr& item) { Dictionary::Ptr target = new Dictionary(); target->Set("name", item->GetName()); target->Set("type", item->GetType()); return target; }
virtual bool ValidateName(const String& type, const String& name) const override { ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, name); if (!item || (item && item->IsAbstract())) return false; return true; }
bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors) { std::vector<Object::Ptr> parents = DependencyGraph::GetParents(object); Type::Ptr type = object->GetReflectionType(); if (!parents.empty() && !cascade) { if (errors) errors->Add("Object '" + object->GetName() + "' of type '" + type->GetName() + "' cannot be deleted because other objects depend on it. " "Use cascading delete to delete it anyway."); return false; } for (const Object::Ptr& pobj : parents) { ConfigObject::Ptr parentObj = dynamic_pointer_cast<ConfigObject>(pobj); if (!parentObj) continue; DeleteObjectHelper(parentObj, cascade, errors); } ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, object->GetName()); try { /* mark this object for cluster delete event */ object->SetExtension("ConfigObjectDeleted", true); /* triggers signal for DB IDO and other interfaces */ object->Deactivate(true); if (item) item->Unregister(); else object->Unregister(); } catch (const std::exception& ex) { if (errors) errors->Add(DiagnosticInformation(ex)); return false; } String path = GetObjectConfigPath(object->GetReflectionType(), object->GetName()); if (Utility::PathExists(path)) { if (unlink(path.CStr()) < 0 && errno != ENOENT) { BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("unlink") << boost::errinfo_errno(errno) << boost::errinfo_file_name(path)); } } return true; }
virtual Value GetTargetByName(const String& type, const String& name) const override { ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, name); if (!item || !item->IsAbstract()) BOOST_THROW_EXCEPTION(std::invalid_argument("Template does not exist.")); return GetTargetForTemplate(item); }
bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); std::ostringstream msgbuf; msgbuf << "Evaluating 'apply' rule (" << di << ")"; CONTEXT(msgbuf.str()); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); Dictionary::Ptr locals = make_shared<Dictionary>(); locals->Set("host", host); if (service) locals->Set("service", service); if (!rule.EvaluateFilter(locals)) return false; std::ostringstream msgbuf2; msgbuf2 << "Applying notification '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; Log(LogDebug, "icinga", msgbuf2.str()); ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di); builder->SetType("Notification"); builder->SetName(rule.GetName()); builder->SetScope(rule.GetScope()); builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, make_shared<AExpression>(&AExpression::OpLiteral, "host_name", di), make_shared<AExpression>(&AExpression::OpLiteral, host->GetName(), di), di)); if (service) { builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, make_shared<AExpression>(&AExpression::OpLiteral, "service_name", di), make_shared<AExpression>(&AExpression::OpLiteral, service->GetShortName(), di), di)); } builder->AddExpression(rule.GetExpression()); ConfigItem::Ptr notificationItem = builder->Compile(); notificationItem->Register(); DynamicObject::Ptr dobj = notificationItem->Commit(); dobj->OnConfigLoaded(); return true; }
bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule) { if (!rule.EvaluateFilter(frame)) return false; DebugInfo di = rule.GetDebugInfo(); #ifdef _DEBUG Log(LogDebug, "Dependency") << "Applying dependency '" << name << "' to object '" << checkable->GetName() << "' for rule " << di; #endif /* _DEBUG */ ConfigItemBuilder builder{di}; builder.SetType(Dependency::TypeInstance); builder.SetName(name); builder.SetScope(frame.Locals->ShallowClone()); builder.SetIgnoreOnError(rule.GetIgnoreOnError()); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "parent_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di)); builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "child_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di)); if (service) builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di)); String zone = checkable->GetZoneName(); if (!zone.IsEmpty()) builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "package"), OpSetLiteral, MakeLiteral(rule.GetPackage()), di)); builder.AddExpression(new ImportDefaultTemplatesExpression()); builder.AddExpression(new OwnedExpression(rule.GetExpression())); ConfigItem::Ptr dependencyItem = builder.Compile(); dependencyItem->Register(); return true; }
bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule) { if (!rule.EvaluateFilter(frame)) return false; DebugInfo di = rule.GetDebugInfo(); Log(LogDebug, "Dependency") << "Applying dependency '" << name << "' to object '" << checkable->GetName() << "' for rule " << di; ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); builder->SetType("Dependency"); builder->SetName(name); builder->SetScope(frame.Locals->ShallowClone()); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "parent_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di)); builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "child_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di)); if (service) builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di)); String zone = checkable->GetZoneName(); if (!zone.IsEmpty()) builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "module"), OpSetLiteral, MakeLiteral(rule.GetModule()), di)); builder->AddExpression(new OwnedExpression(rule.GetExpression())); ConfigItem::Ptr dependencyItem = builder->Compile(); dependencyItem->Register(); return true; }
bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr& group) { String group_name = group->GetName(); CONTEXT("Evaluating rule for group '" + group_name + "'"); ScriptFrame frame; if (group->GetScope()) group->GetScope()->CopyTo(frame.Locals); frame.Locals->Set("user", user); if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool()) return false; Log(LogDebug, "UserGroup") << "Assigning membership for group '" << group_name << "' to user '" << user->GetName() << "'"; Array::Ptr groups = user->GetGroups(); groups->Add(group_name); return true; }
bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr& group) { String groupName = group->GetName(); CONTEXT("Evaluating rule for group '" + groupName + "'"); ScriptFrame frame(true); if (group->GetScope()) group->GetScope()->CopyTo(frame.Locals); frame.Locals->Set("host", host); if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool()) return false; Log(LogDebug, "HostGroup") << "Assigning membership for group '" << groupName << "' to host '" << host->GetName() << "'"; Array::Ptr groups = host->GetGroups(); if (groups && !groups->Contains(groupName)) groups->Add(groupName); return true; }
static inline Value NewObject(ScriptFrame& frame, bool abstract, const String& type, const String& name, const boost::shared_ptr<Expression>& filter, const String& zone, std::map<String, Expression *> *closedVars, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo()) { ConfigItemBuilder::Ptr item = new ConfigItemBuilder(debugInfo); String checkName = name; if (!abstract) { Type::Ptr ptype = Type::GetByName(type); NameComposer *nc = dynamic_cast<NameComposer *>(ptype.get()); if (nc) checkName = nc->MakeName(name, Dictionary::Ptr()); } if (!checkName.IsEmpty()) { ConfigItem::Ptr oldItem = ConfigItem::GetObject(type, checkName); if (oldItem) { std::ostringstream msgbuf; msgbuf << "Object '" << name << "' of type '" << type << "' re-defined: " << debugInfo << "; previous definition: " << oldItem->GetDebugInfo(); BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), debugInfo)); } } item->SetType(type); if (name.FindFirstOf("!") != String::NPos) { std::ostringstream msgbuf; msgbuf << "Name for object '" << name << "' of type '" << type << "' is invalid: Object names may not contain '!'"; BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), debugInfo)); } item->SetName(name); item->AddExpression(new OwnedExpression(expression)); item->SetAbstract(abstract); item->SetScope(EvaluateClosedVars(frame, closedVars)); item->SetZone(zone); item->SetFilter(filter); item->Compile()->Register(); return Empty; }
bool DaemonUtility::ValidateConfigFiles(const std::vector<std::string>& configs, const String& objectsFile) { bool success; if (!objectsFile.IsEmpty()) ConfigCompilerContext::GetInstance()->OpenObjectsFile(objectsFile); if (!configs.empty()) { for (const String& configPath : configs) { try { std::unique_ptr<Expression> expression = ConfigCompiler::CompileFile(configPath, String(), "_etc"); success = ExecuteExpression(&*expression); if (!success) return false; } catch (const std::exception& ex) { Log(LogCritical, "cli", "Could not compile config files: " + DiagnosticInformation(ex, false)); Application::Exit(1); } } } /* Load cluster config files from /etc/icinga2/zones.d. * This should probably be in libremote but * unfortunately moving it there is somewhat non-trivial. */ success = true; String zonesEtcDir = Configuration::ZonesDir; if (!zonesEtcDir.IsEmpty() && Utility::PathExists(zonesEtcDir)) Utility::Glob(zonesEtcDir + "/*", std::bind(&IncludeZoneDirRecursive, _1, "_etc", std::ref(success)), GlobDirectory); if (!success) return false; /* Load package config files - they may contain additional zones which * are authoritative on this node and are checked in HasZoneConfigAuthority(). */ String packagesVarDir = Configuration::DataDir + "/api/packages"; if (Utility::PathExists(packagesVarDir)) Utility::Glob(packagesVarDir + "/*", std::bind(&IncludePackage, _1, std::ref(success)), GlobDirectory); if (!success) return false; /* Load cluster synchronized configuration files */ String zonesVarDir = Configuration::DataDir + "/api/zones"; if (Utility::PathExists(zonesVarDir)) Utility::Glob(zonesVarDir + "/*", std::bind(&IncludeNonLocalZone, _1, "_cluster", std::ref(success)), GlobDirectory); if (!success) return false; Namespace::Ptr systemNS = ScriptGlobal::Get("System"); VERIFY(systemNS); /* This is initialized inside the IcingaApplication class. */ Value vAppType; VERIFY(systemNS->Get("ApplicationType", &vAppType)); Type::Ptr appType = Type::GetByName(vAppType); if (ConfigItem::GetItems(appType).empty()) { ConfigItemBuilder builder; builder.SetType(appType); builder.SetName("app"); builder.AddExpression(new ImportDefaultTemplatesExpression()); ConfigItem::Ptr item = builder.Compile(); item->Register(); } return true; }