diff --git a/lib/cli/CMakeLists.txt b/lib/cli/CMakeLists.txt index bf706e2eb..101577530 100644 --- a/lib/cli/CMakeLists.txt +++ b/lib/cli/CMakeLists.txt @@ -18,15 +18,13 @@ set(cli_SOURCES apisetupcommand.cpp apisetuputility.cpp calistcommand.cpp casigncommand.cpp - nodeaddcommand.cpp nodeblackandwhitelistcommand.cpp nodelistcommand.cpp noderemovecommand.cpp - nodesetcommand.cpp nodesetupcommand.cpp nodeupdateconfigcommand.cpp nodewizardcommand.cpp nodeutility.cpp + nodesetupcommand.cpp nodewizardcommand.cpp nodeutility.cpp clicommand.cpp consolecommand.cpp daemoncommand.cpp daemonutility.cpp featureenablecommand.cpp featuredisablecommand.cpp featurelistcommand.cpp featureutility.cpp objectlistcommand.cpp objectlistutility.cpp pkinewcacommand.cpp pkinewcertcommand.cpp pkisigncsrcommand.cpp pkirequestcommand.cpp pkisavecertcommand.cpp pkiticketcommand.cpp - repositoryclearchangescommand.cpp repositorycommitcommand.cpp repositoryobjectcommand.cpp repositoryutility.cpp variablegetcommand.cpp variablelistcommand.cpp variableutility.cpp troubleshootcommand.cpp ) diff --git a/lib/cli/nodeaddcommand.cpp b/lib/cli/nodeaddcommand.cpp deleted file mode 100644 index f2e38e71a..000000000 --- a/lib/cli/nodeaddcommand.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/nodeaddcommand.hpp" -#include "cli/nodeutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include -#include -#include -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("node/add", NodeAddCommand); - -String NodeAddCommand::GetDescription(void) const -{ - return "Add Icinga 2 node."; -} - -String NodeAddCommand::GetShortDescription(void) const -{ - return "add node"; -} - -int NodeAddCommand::GetMinArguments(void) const -{ - return 1; -} - -bool NodeAddCommand::IsDeprecated(void) const -{ - return true; -} - -/** - * The entry point for the "node add" CLI command. - * - * @returns An exit status. - */ -int NodeAddCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - NodeUtility::AddNode(ap[0]); - - return 0; -} diff --git a/lib/cli/nodeaddcommand.hpp b/lib/cli/nodeaddcommand.hpp deleted file mode 100644 index 19347b4ba..000000000 --- a/lib/cli/nodeaddcommand.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef NODEADDCOMMAND_H -#define NODEADDCOMMAND_H - -#include "cli/clicommand.hpp" - -namespace icinga -{ - -/** - * The "node add" command. - * - * @ingroup cli - */ -class NodeAddCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(NodeAddCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual int GetMinArguments(void) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; -}; - -} - -#endif /* NODEADDCOMMAND_H */ diff --git a/lib/cli/nodeblackandwhitelistcommand.cpp b/lib/cli/nodeblackandwhitelistcommand.cpp deleted file mode 100644 index ccc4ddb8c..000000000 --- a/lib/cli/nodeblackandwhitelistcommand.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/nodeblackandwhitelistcommand.hpp" -#include "cli/nodeutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include "base/objectlock.hpp" -#include "base/json.hpp" -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_BLACKANDWHITELIST_CLICOMMAND(whitelist); -REGISTER_BLACKANDWHITELIST_CLICOMMAND(blacklist); - -BlackAndWhitelistCommand::BlackAndWhitelistCommand(const String& type, BlackAndWhitelistCommandType command) - : m_Type(type), m_Command(command) -{ } - -String BlackAndWhitelistCommand::GetDescription(void) const -{ - String description; - - switch (m_Command) { - case BlackAndWhitelistCommandAdd: - description = "Adds a new"; - break; - case BlackAndWhitelistCommandRemove: - description = "Removes a"; - break; - case BlackAndWhitelistCommandList: - description = "Lists all"; - break; - } - - description += " " + m_Type + " filter"; - - if (m_Command == BlackAndWhitelistCommandList) - description += "s"; - - return description; -} - -String BlackAndWhitelistCommand::GetShortDescription(void) const -{ - String description; - - switch (m_Command) { - case BlackAndWhitelistCommandAdd: - description = "adds a new"; - break; - case BlackAndWhitelistCommandRemove: - description = "removes a"; - break; - case BlackAndWhitelistCommandList: - description = "lists all"; - break; - } - - description += " " + m_Type + " filter"; - - if (m_Command == BlackAndWhitelistCommandList) - description += "s"; - - return description; -} - -bool BlackAndWhitelistCommand::IsDeprecated(void) const -{ - return true; -} - -void BlackAndWhitelistCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const -{ - if (m_Command == BlackAndWhitelistCommandAdd || m_Command == BlackAndWhitelistCommandRemove) { - visibleDesc.add_options() - ("zone", po::value(), "The name of the zone") - ("host", po::value(), "The name of the host") - ("service", po::value(), "The name of the service"); - } -} - -/** - * The entry point for the "node " CLI command. - * - * @returns An exit status. - */ -int BlackAndWhitelistCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - if (m_Command == BlackAndWhitelistCommandAdd) { - if (!vm.count("zone")) { - Log(LogCritical, "cli", "At least the zone name filter is required!"); - return 1; - } - - if (!vm.count("host")) { - Log(LogCritical, "cli", "At least the host name filter is required!"); - return 1; - } - - String service_filter; - - if (vm.count("service")) - service_filter = vm["service"].as(); - - return NodeUtility::UpdateBlackAndWhiteList(m_Type, vm["zone"].as(), vm["host"].as(), service_filter); - } else if (m_Command == BlackAndWhitelistCommandList) { - return NodeUtility::PrintBlackAndWhiteList(std::cout, m_Type); - } else if (m_Command == BlackAndWhitelistCommandRemove) { - if (!vm.count("zone")) { - Log(LogCritical, "cli", "The zone name filter is required!"); - return 1; - } - - if (!vm.count("host")) { - Log(LogCritical, "cli", "The host name filter is required!"); - return 1; - } - - String zone_filter = vm["zone"].as(); - String host_filter = vm["host"].as(); - String service_filter; - - if (vm.count("service")) { - service_filter = vm["service"].as(); - } - - return NodeUtility::RemoveBlackAndWhiteList(m_Type, vm["zone"].as(), vm["host"].as(), service_filter); - } - - - return 0; -} diff --git a/lib/cli/nodeblackandwhitelistcommand.hpp b/lib/cli/nodeblackandwhitelistcommand.hpp deleted file mode 100644 index 6039c2cc0..000000000 --- a/lib/cli/nodeblackandwhitelistcommand.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef BLACKANDWHITELISTCOMMAND_H -#define BLACKANDWHITELISTCOMMAND_H - -#include "cli/clicommand.hpp" -#include - -namespace icinga -{ - -enum BlackAndWhitelistCommandType -{ - BlackAndWhitelistCommandAdd, - BlackAndWhitelistCommandRemove, - BlackAndWhitelistCommandList -}; - -/** - * The "repository " command. - * - * @ingroup cli - */ -class I2_CLI_API BlackAndWhitelistCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(BlackAndWhitelistCommand); - - BlackAndWhitelistCommand(const String& type, BlackAndWhitelistCommandType command); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; - -private: - String m_Type; - BlackAndWhitelistCommandType m_Command; -}; - -#define REGISTER_BLACKANDWHITELIST_CLICOMMAND(type) \ - INITIALIZE_ONCE([]() { \ - String ltype = #type; \ - boost::algorithm::to_lower(ltype); \ -\ - std::vector name; \ - name.push_back("node"); \ - name.push_back(ltype); \ - name.push_back("add"); \ - CLICommand::Register(name, new BlackAndWhitelistCommand(#type, BlackAndWhitelistCommandAdd)); \ -\ - name[2] = "remove"; \ - CLICommand::Register(name, new BlackAndWhitelistCommand(#type, BlackAndWhitelistCommandRemove)); \ -\ - name[2] = "list"; \ - CLICommand::Register(name, new BlackAndWhitelistCommand(#type, BlackAndWhitelistCommandList)); \ - }) - -} - -#endif /* BLACKANDWHITELISTCOMMAND_H */ diff --git a/lib/cli/nodelistcommand.cpp b/lib/cli/nodelistcommand.cpp deleted file mode 100644 index 63548231e..000000000 --- a/lib/cli/nodelistcommand.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/nodelistcommand.hpp" -#include "cli/nodeutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include "base/console.hpp" -#include -#include -#include -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("node/list", NodeListCommand); - -String NodeListCommand::GetDescription(void) const -{ - return "Lists all Icinga 2 nodes."; -} - -String NodeListCommand::GetShortDescription(void) const -{ - return "lists all nodes"; -} - -bool NodeListCommand::IsDeprecated(void) const -{ - return true; -} - -void NodeListCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const -{ - visibleDesc.add_options() - ("batch", "list nodes in json"); -} - -/** - * The entry point for the "node list" CLI command. - * - * @returns An exit status. - */ -int NodeListCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - if (!ap.empty()) { - Log(LogWarning, "cli") - << "Ignoring parameters: " << boost::algorithm::join(ap, " "); - } - - if (vm.count("batch")) - NodeUtility::PrintNodesJson(std::cout); - else - NodeUtility::PrintNodes(std::cout); - - return 0; -} diff --git a/lib/cli/nodelistcommand.hpp b/lib/cli/nodelistcommand.hpp deleted file mode 100644 index 21fbd5591..000000000 --- a/lib/cli/nodelistcommand.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef NODELISTCOMMAND_H -#define NODELISTCOMMAND_H - -#include "cli/clicommand.hpp" - -namespace icinga -{ - -/** - * The "node list" command. - * - * @ingroup cli - */ -class NodeListCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(NodeListCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; -}; - -} - -#endif /* NODELISTCOMMAND_H */ diff --git a/lib/cli/noderemovecommand.cpp b/lib/cli/noderemovecommand.cpp deleted file mode 100644 index d1a6dac4f..000000000 --- a/lib/cli/noderemovecommand.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/noderemovecommand.hpp" -#include "cli/nodeutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include -#include -#include -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("node/remove", NodeRemoveCommand); - -String NodeRemoveCommand::GetDescription(void) const -{ - return "Removes Icinga 2 node."; -} - -String NodeRemoveCommand::GetShortDescription(void) const -{ - return "removes node"; -} - -std::vector NodeRemoveCommand::GetPositionalSuggestions(const String& word) const -{ - return NodeUtility::GetNodeCompletionSuggestions(word); -} - -int NodeRemoveCommand::GetMinArguments(void) const -{ - return 1; -} - -int NodeRemoveCommand::GetMaxArguments(void) const -{ - return -1; -} - -bool NodeRemoveCommand::IsDeprecated(void) const -{ - return true; -} - -/** - * The entry point for the "node remove" CLI command. - * - * @returns An exit status. - */ -int NodeRemoveCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - for (const String& node : ap) { - NodeUtility::RemoveNode(node); - } - - return 0; -} diff --git a/lib/cli/noderemovecommand.hpp b/lib/cli/noderemovecommand.hpp deleted file mode 100644 index d267e5407..000000000 --- a/lib/cli/noderemovecommand.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef NODEREMOVECOMMAND_H -#define NODEREMOVECOMMAND_H - -#include "cli/clicommand.hpp" - -namespace icinga -{ - -/** - * The "node remove" command. - * - * @ingroup cli - */ -class NodeRemoveCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(NodeRemoveCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual int GetMinArguments(void) const override; - virtual int GetMaxArguments(void) const override; - virtual std::vector GetPositionalSuggestions(const String& word) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; -}; - -} - -#endif /* NODEREMOVECOMMAND_H */ diff --git a/lib/cli/nodesetcommand.cpp b/lib/cli/nodesetcommand.cpp deleted file mode 100644 index 017c58196..000000000 --- a/lib/cli/nodesetcommand.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/nodesetcommand.hpp" -#include "cli/nodeutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include -#include -#include -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("node/set", NodeSetCommand); - -String NodeSetCommand::GetDescription(void) const -{ - return "Set node attribute(s)."; -} - -String NodeSetCommand::GetShortDescription(void) const -{ - return "set node attributes"; -} - -void NodeSetCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const -{ - visibleDesc.add_options() - ("host", po::value(), "Icinga 2 host") - ("port", po::value(), "Icinga 2 port") - ("log_duration", po::value(), "Log duration (in seconds)"); -} - -int NodeSetCommand::GetMinArguments(void) const -{ - return 1; -} - -bool NodeSetCommand::IsDeprecated(void) const -{ - return true; -} - -/** - * The entry point for the "node set" CLI command. - * - * @returns An exit status. - */ -int NodeSetCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - String repoFile = NodeUtility::GetNodeRepositoryFile(ap[0]); - - if (!Utility::PathExists(repoFile)) { - Log(LogCritical, "cli") - << "Node '" << ap[0] << "' does not exist."; - return 1; - } - - String host, port = "5665"; - double log_duration = 24 * 60 * 60; - - if (vm.count("host")) - host = vm["host"].as(); - - if (vm.count("port")) - port = vm["port"].as(); - - if (vm.count("log_duration")) - log_duration = vm["log_duration"].as(); - - NodeUtility::AddNodeSettings(ap[0], host, port, log_duration); - - return 0; -} diff --git a/lib/cli/nodesetcommand.hpp b/lib/cli/nodesetcommand.hpp deleted file mode 100644 index 72c5aa94a..000000000 --- a/lib/cli/nodesetcommand.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef NODESETCOMMAND_H -#define NODESETCOMMAND_H - -#include "cli/clicommand.hpp" - -namespace icinga -{ - -/** - * The "node set" command. - * - * @ingroup cli - */ -class NodeSetCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(NodeSetCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual int GetMinArguments(void) const override; - virtual bool IsDeprecated(void) const override; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; -}; - -} - -#endif /* NODESETCOMMAND_H */ diff --git a/lib/cli/nodeupdateconfigcommand.cpp b/lib/cli/nodeupdateconfigcommand.cpp deleted file mode 100644 index edb317d11..000000000 --- a/lib/cli/nodeupdateconfigcommand.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/nodeupdateconfigcommand.hpp" -#include "cli/nodeutility.hpp" -#include "cli/repositoryutility.hpp" -#include "cli/variableutility.hpp" -#include "base/logger.hpp" -#include "base/console.hpp" -#include "base/application.hpp" -#include "base/tlsutility.hpp" -#include "base/json.hpp" -#include "base/objectlock.hpp" -#include -#include -#include -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("node/update-config", NodeUpdateConfigCommand); - -String NodeUpdateConfigCommand::GetDescription(void) const -{ - return "Update Icinga 2 node config."; -} - -String NodeUpdateConfigCommand::GetShortDescription(void) const -{ - return "update node config"; -} - -ImpersonationLevel NodeUpdateConfigCommand::GetImpersonationLevel(void) const -{ - return ImpersonateRoot; -} - -bool NodeUpdateConfigCommand::IsDeprecated(void) const -{ - return true; -} - -/** - * The entry point for the "node update-config" CLI command. - * - * @returns An exit status. - */ -int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - //If there are changes pending, abort the current operation - if (RepositoryUtility::ChangeLogHasPendingChanges()) { - Log(LogWarning, "cli") - << "There are pending changes for commit.\n" - << "Please review and commit them using 'icinga2 repository commit [--simulate]'\n" - << "or drop them using 'icinga2 repository clear-changes' before proceeding."; - return 1; - } - - String inventory_path = NodeUtility::GetRepositoryPath() + "/inventory.index"; - - Dictionary::Ptr old_inventory = new Dictionary(); - if (Utility::PathExists(inventory_path)) { - old_inventory = Utility::LoadJsonFile(inventory_path); - } - - Dictionary::Ptr inventory = new Dictionary(); - - Log(LogInformation, "cli") - << "Updating node configuration for "; - - NodeUtility::PrintNodes(std::cout); - - /* cache all existing object configs only once and pass it to AddObject() */ - std::vector object_paths = RepositoryUtility::GetObjects(); - /* cache all existing changes only once and pass it to AddObject() */ - Array::Ptr changes = new Array(); - RepositoryUtility::GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changes)); - - std::vector nodes = NodeUtility::GetNodes(); - - /* first make sure that all nodes are valid and should not be removed */ - for (const Dictionary::Ptr& node : nodes) { - Dictionary::Ptr repository = node->Get("repository"); - String zone = node->Get("zone"); - String endpoint = node->Get("endpoint"); - String node_name = endpoint; - - /* store existing structure in index */ - inventory->Set(endpoint, node); - } - - if (old_inventory) { - /* check if there are objects inside the old_inventory which do not exist anymore */ - ObjectLock ulock(old_inventory); - for (const Dictionary::Pair& old_node_objs : old_inventory) { - - String old_node_name = old_node_objs.first; - - /* check if the node was dropped */ - if (!inventory->Contains(old_node_name)) { - Log(LogInformation, "cli") - << "Node update found old node '" << old_node_name << "'. Removing it and all of its hosts/services."; - - //TODO Remove an node and all of his hosts - Dictionary::Ptr old_node = old_node_objs.second; - Dictionary::Ptr old_node_repository = old_node->Get("repository"); - - if (old_node_repository) { - ObjectLock olock(old_node_repository); - for (const Dictionary::Pair& kv : old_node_repository) { - String host = kv.first; - - Dictionary::Ptr host_attrs = new Dictionary(); - host_attrs->Set("name", host); - RepositoryUtility::RemoveObject(host, "Host", host_attrs, changes); //this removes all services for this host as well - } - } - - String zone = old_node->Get("zone"); - String endpoint = old_node->Get("endpoint"); - - Dictionary::Ptr zone_attrs = new Dictionary(); - zone_attrs->Set("name", zone); - RepositoryUtility::RemoveObject(zone, "Zone", zone_attrs, changes); - - Dictionary::Ptr endpoint_attrs = new Dictionary(); - endpoint_attrs->Set("name", endpoint); - RepositoryUtility::RemoveObject(endpoint, "Endpoint", endpoint_attrs, changes); - } else { - /* get the current node */ - Dictionary::Ptr new_node = inventory->Get(old_node_name); - Dictionary::Ptr new_node_repository = new_node->Get("repository"); - - Dictionary::Ptr old_node = old_node_objs.second; - Dictionary::Ptr old_node_repository = old_node->Get("repository"); - - if (old_node_repository) { - ObjectLock xlock(old_node_repository); - for (const Dictionary::Pair& kv : old_node_repository) { - String old_host = kv.first; - - if (old_host == "localhost") { - Log(LogWarning, "cli") - << "Ignoring host '" << old_host << "'. Please make sure to configure a unique name on your node '" << old_node_name << "'."; - continue; - } - - /* check against black/whitelist before trying to remove host */ - if (NodeUtility::CheckAgainstBlackAndWhiteList("blacklist", old_node_name, old_host, Empty) && - !NodeUtility::CheckAgainstBlackAndWhiteList("whitelist", old_node_name, old_host, Empty)) { - Log(LogWarning, "cli") - << "Host '" << old_node_name << "' on node '" << old_node_name << "' is blacklisted, but not whitelisted. Skipping."; - continue; - } - - if (!new_node_repository->Contains(old_host)) { - Log(LogInformation, "cli") - << "Node update found old host '" << old_host << "' on node '" << old_node_name << "'. Removing it."; - - Dictionary::Ptr host_attrs = new Dictionary(); - host_attrs->Set("name", old_host); - RepositoryUtility::RemoveObject(old_host, "Host", host_attrs, changes); //this will remove all services for this host too - } else { - /* host exists, now check all services for this host */ - Array::Ptr old_services = kv.second; - Array::Ptr new_services = new_node_repository->Get(old_host); - - ObjectLock ylock(old_services); - for (const String& old_service : old_services) { - /* check against black/whitelist before trying to remove service */ - if (NodeUtility::CheckAgainstBlackAndWhiteList("blacklist", old_node_name, old_host, old_service) && - !NodeUtility::CheckAgainstBlackAndWhiteList("whitelist", old_node_name, old_host, old_service)) { - Log(LogWarning, "cli") - << "Service '" << old_service << "' on host '" << old_host << "' on node '" - << old_node_name << "' is blacklisted, but not whitelisted. Skipping."; - continue; - } - - if (!new_services->Contains(old_service)) { - Log(LogInformation, "cli") - << "Node update found old service '" << old_service << "' on host '" << old_host - << "' on node '" << old_node_name << "'. Removing it."; - - Dictionary::Ptr service_attrs = new Dictionary(); - service_attrs->Set("name", old_service); - service_attrs->Set("host_name", old_host); - RepositoryUtility::RemoveObject(old_service, "Service", service_attrs, changes); - } - } - } - } - } - } - } - } - - /* next iterate over all nodes and add hosts/services */ - for (const Dictionary::Ptr& node : nodes) { - Dictionary::Ptr repository = node->Get("repository"); - String zone = node->Get("zone"); - String endpoint = node->Get("endpoint"); - String node_name = endpoint; - - Dictionary::Ptr host_services = new Dictionary(); - - if (NodeUtility::CheckAgainstBlackAndWhiteList("blacklist", node_name, "*", Empty) && - !NodeUtility::CheckAgainstBlackAndWhiteList("whitelist", node_name, "*", Empty)) { - Log(LogWarning, "cli") - << "Skipping node '" << node_name << "' on blacklist."; - continue; - } - - Log(LogInformation, "cli") - << "Adding host '" << zone << "' to the repository."; - - Dictionary::Ptr host_attrs = new Dictionary(); - host_attrs->Set("__name", zone); - host_attrs->Set("name", zone); - host_attrs->Set("check_command", "cluster-zone"); - Array::Ptr host_imports = new Array(); - host_imports->Add("satellite-host"); //default host node template - host_attrs->Set("import", host_imports); - - if (!RepositoryUtility::AddObject(object_paths, zone, "Host", host_attrs, changes, false)) { - Log(LogWarning, "cli") - << "Cannot add node host '" << zone << "' to the config repository!\n"; - } - - if (repository) { - ObjectLock olock(repository); - for (const Dictionary::Pair& kv : repository) { - String host = kv.first; - String host_pattern = host + ".conf"; - bool skip_host = false; - - if (host == "localhost") { - Log(LogWarning, "cli") - << "Ignoring host '" << host << "'. Please make sure to configure a unique name on your node '" << endpoint << "'."; - continue; - } - - for (const String& object_path : object_paths) { - if (object_path.Contains(host_pattern)) { - Log(LogNotice, "cli") - << "Host '" << host << "' already exists."; - skip_host = true; - break; - } - } - - /* host has already been created above */ - if (host == zone) - skip_host = true; - - bool host_was_blacklisted = false; - - /* check against black/whitelist before trying to add host */ - if (NodeUtility::CheckAgainstBlackAndWhiteList("blacklist", node_name, host, Empty) && - !NodeUtility::CheckAgainstBlackAndWhiteList("whitelist", node_name, host, Empty)) { - Log(LogWarning, "cli") - << "Host '" << host << "' on node '" << node_name << "' is blacklisted, but not whitelisted. Not creating host object."; - skip_host = true; - host_was_blacklisted = true; //check this for services on this blacklisted host - } - - if (!skip_host) { - /* add a new host to the config repository */ - Dictionary::Ptr host_attrs = new Dictionary(); - host_attrs->Set("__name", host); - host_attrs->Set("name", host); - - if (host == zone) - host_attrs->Set("check_command", "cluster-zone"); - else { - host_attrs->Set("check_command", "dummy"); - host_attrs->Set("zone", zone); - } - - Array::Ptr host_imports = new Array(); - host_imports->Add("satellite-host"); //default host node template - host_attrs->Set("import", host_imports); - - RepositoryUtility::AddObject(object_paths, host, "Host", host_attrs, changes, false); - } - - /* special condition: what if the host was blacklisted before, but the services should be generated? */ - if (host_was_blacklisted) { - Log(LogNotice, "cli") - << "Host '" << host << "' was blacklisted. Won't generate any services."; - continue; - } - - Array::Ptr services = kv.second; - - if (services->GetLength() == 0) { - Log(LogNotice, "cli") - << "Host '" << host << "' without services."; - continue; - } - - ObjectLock xlock(services); - for (const String& service : services) { - bool skip_service = false; - - String service_pattern = host + "/" + service + ".conf"; - - for (const String& object_path : object_paths) { - if (object_path.Contains(service_pattern)) { - Log(LogNotice, "cli") - << "Service '" << service << "' on Host '" << host << "' already exists."; - skip_service = true; - break; - } - } - - /* check against black/whitelist before trying to add service */ - if (NodeUtility::CheckAgainstBlackAndWhiteList("blacklist", endpoint, host, service) && - !NodeUtility::CheckAgainstBlackAndWhiteList("whitelist", endpoint, host, service)) { - Log(LogWarning, "cli") - << "Service '" << service << "' on host '" << host << "' on node '" - << node_name << "' is blacklisted, but not whitelisted. Not creating service object."; - skip_service = true; - } - - if (skip_service) - continue; - - /* add a new service for this host to the config repository */ - Dictionary::Ptr service_attrs = new Dictionary(); - String long_name = host + "!" + service; //use NameComposer? - service_attrs->Set("__name", long_name); - service_attrs->Set("name", service); - service_attrs->Set("host_name", host); //Required for host-service relation - service_attrs->Set("check_command", "dummy"); - service_attrs->Set("zone", zone); - - Array::Ptr service_imports = new Array(); - service_imports->Add("satellite-service"); //default service node template - service_attrs->Set("import", service_imports); - - if (!RepositoryUtility::AddObject(object_paths, service, "Service", service_attrs, changes, false)) - continue; - } - } - } - - /* write a new zone and endpoint for the node */ - Dictionary::Ptr endpoint_attrs = new Dictionary(); - endpoint_attrs->Set("__name", endpoint); - endpoint_attrs->Set("name", endpoint); - - Dictionary::Ptr settings = node->Get("settings"); - - if (settings) { - if (settings->Contains("host")) - endpoint_attrs->Set("host", settings->Get("host")); - if (settings->Contains("port")) - endpoint_attrs->Set("port", settings->Get("port")); - } - - Log(LogInformation, "cli") - << "Adding endpoint '" << endpoint << "' to the repository."; - - if (!RepositoryUtility::AddObject(object_paths, endpoint, "Endpoint", endpoint_attrs, changes, false)) { - Log(LogWarning, "cli") - << "Cannot add node endpoint '" << endpoint << "' to the config repository!\n"; - } - - Dictionary::Ptr zone_attrs = new Dictionary(); - Array::Ptr zone_members = new Array(); - - zone_members->Add(endpoint); - zone_attrs->Set("__name", zone); - zone_attrs->Set("name", zone); - zone_attrs->Set("endpoints", zone_members); - - String parent_zone = VariableUtility::GetVariable("ZoneName"); - - if (parent_zone.IsEmpty()) { - Log(LogWarning, "cli") - << "Variable 'ZoneName' is not set. Falling back to using 'master' as default. Please verify the generated configuration."; - parent_zone = "master"; - } - - zone_attrs->Set("parent", parent_zone); - - Log(LogInformation, "cli") - << "Adding zone '" << zone << "' to the repository."; - - if (!RepositoryUtility::AddObject(object_paths, zone, "Zone", zone_attrs, changes, false)) { - Log(LogWarning, "cli") - << "Cannot add node zone '" << zone << "' to the config repository!\n"; - } - } - - Log(LogInformation, "cli", "Committing node configuration."); - - RepositoryUtility::PrintChangeLog(std::cout); - std::cout << "\n"; - RepositoryUtility::CommitChangeLog(); - - /* store the new inventory for next run */ - NodeUtility::CreateRepositoryPath(); - Utility::SaveJsonFile(inventory_path, 0600, inventory); - - std::cout << "Make sure to reload Icinga 2 for these changes to take effect." << std::endl; - - return 0; -} diff --git a/lib/cli/nodeupdateconfigcommand.hpp b/lib/cli/nodeupdateconfigcommand.hpp deleted file mode 100644 index 1801f403e..000000000 --- a/lib/cli/nodeupdateconfigcommand.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef NODEUPDATECONFIGCOMMAND_H -#define NODEUPDATECONFIGCOMMAND_H - -#include "cli/clicommand.hpp" - -namespace icinga -{ - -/** - * The "agent update-config" command. - * - * @ingroup cli - */ -class NodeUpdateConfigCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(NodeUpdateConfigCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; - virtual ImpersonationLevel GetImpersonationLevel(void) const override; -}; - -} - -#endif /* NODEUPDATECONFIGCOMMAND_H */ diff --git a/lib/cli/repositoryclearchangescommand.cpp b/lib/cli/repositoryclearchangescommand.cpp deleted file mode 100644 index 653640de5..000000000 --- a/lib/cli/repositoryclearchangescommand.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/repositoryclearchangescommand.hpp" -#include "cli/repositoryutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include "base/utility.hpp" -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("repository/clear-changes", RepositoryClearChangesCommand); - -String RepositoryClearChangesCommand::GetDescription(void) const -{ - return "Clear uncommitted Icinga 2 repository changes"; -} - -String RepositoryClearChangesCommand::GetShortDescription(void) const -{ - return "clear uncommitted repository changes"; -} - -ImpersonationLevel RepositoryClearChangesCommand::GetImpersonationLevel(void) const -{ - return ImpersonateRoot; -} - -bool RepositoryClearChangesCommand::IsDeprecated(void) const -{ - return true; -} - -/** - * The entry point for the "repository clear-changes" CLI command. - * - * @returns An exit status. - */ -int RepositoryClearChangesCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - if (!Utility::PathExists(RepositoryUtility::GetRepositoryChangeLogPath())) { - std::cout << "Repository Changelog path '" << RepositoryUtility::GetRepositoryChangeLogPath() << "' does not exist. Add objects first!\n"; - return 1; - } - - std::cout << "Clearing all remaining changes\n"; - RepositoryUtility::ClearChangeLog(); - - return 0; -} diff --git a/lib/cli/repositoryclearchangescommand.hpp b/lib/cli/repositoryclearchangescommand.hpp deleted file mode 100644 index 951c6fd36..000000000 --- a/lib/cli/repositoryclearchangescommand.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef REPOSITORYCLEARCHANGESCOMMAND_H -#define REPOSITORYCLEARCHANGESCOMMAND_H - -#include "base/dictionary.hpp" -#include "base/array.hpp" -#include "cli/clicommand.hpp" -#include - -namespace icinga -{ - -/** - * The "repository clear-changes" command. - * - * @ingroup cli - */ -class RepositoryClearChangesCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(RepositoryClearChangesCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual ImpersonationLevel GetImpersonationLevel(void) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; -}; - -} - -#endif /* REPOSITORYCLEARCHANGESCOMMAND_H */ diff --git a/lib/cli/repositorycommitcommand.cpp b/lib/cli/repositorycommitcommand.cpp deleted file mode 100644 index da4c898b1..000000000 --- a/lib/cli/repositorycommitcommand.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/repositorycommitcommand.hpp" -#include "cli/repositoryutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include "base/utility.hpp" -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_CLICOMMAND("repository/commit", RepositoryCommitCommand); - -String RepositoryCommitCommand::GetDescription(void) const -{ - return "Commit Icinga 2 repository changes"; -} - -String RepositoryCommitCommand::GetShortDescription(void) const -{ - return "commit repository changes"; -} - -void RepositoryCommitCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const -{ - visibleDesc.add_options() - ("simulate", "Simulate to-be-committed changes"); -} - -ImpersonationLevel RepositoryCommitCommand::GetImpersonationLevel(void) const -{ - return ImpersonateRoot; -} - -bool RepositoryCommitCommand::IsDeprecated(void) const -{ - return true; -} - -/** - * The entry point for the "repository commit" CLI command. - * - * @returns An exit status. - */ -int RepositoryCommitCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - if (!Utility::PathExists(RepositoryUtility::GetRepositoryChangeLogPath())) { - std::cout << "Repository Changelog path '" << RepositoryUtility::GetRepositoryChangeLogPath() << "' does not exist. Add objects first!\n"; - return 1; - } - - if (vm.count("simulate")) { - RepositoryUtility::PrintChangeLog(std::cout); - std::cout << "\n"; - std::cout << "Simulation not yet implemented.\n"; - //TODO - return 1; - } else { - RepositoryUtility::PrintChangeLog(std::cout); - std::cout << "\n"; - RepositoryUtility::CommitChangeLog(); - } - - return 0; -} diff --git a/lib/cli/repositorycommitcommand.hpp b/lib/cli/repositorycommitcommand.hpp deleted file mode 100644 index e7e2f1d08..000000000 --- a/lib/cli/repositorycommitcommand.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef REPOSITORYCOMMITCOMMAND_H -#define REPOSITORYCOMMITCOMMAND_H - -#include "base/dictionary.hpp" -#include "base/array.hpp" -#include "cli/clicommand.hpp" -#include - -namespace icinga -{ - -/** - * The "repository commit" command. - * - * @ingroup cli - */ -class RepositoryCommitCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(RepositoryCommitCommand); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual bool IsDeprecated(void) const override; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const override; - virtual ImpersonationLevel GetImpersonationLevel(void) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; -}; - -} - -#endif /* REPOSITORYCOMMITCOMMAND_H */ diff --git a/lib/cli/repositoryobjectcommand.cpp b/lib/cli/repositoryobjectcommand.cpp deleted file mode 100644 index 835fb0100..000000000 --- a/lib/cli/repositoryobjectcommand.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/repositoryobjectcommand.hpp" -#include "cli/repositoryutility.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include "base/utility.hpp" -#include -#include - -using namespace icinga; -namespace po = boost::program_options; - -REGISTER_REPOSITORY_CLICOMMAND(Host); -REGISTER_REPOSITORY_CLICOMMAND(Service); -REGISTER_REPOSITORY_CLICOMMAND(Zone); -REGISTER_REPOSITORY_CLICOMMAND(Endpoint); - -RepositoryObjectCommand::RepositoryObjectCommand(const String& type, RepositoryCommandType command) - : m_Type(type), m_Command(command) -{ } - -String RepositoryObjectCommand::GetDescription(void) const -{ - String description; - - switch (m_Command) { - case RepositoryCommandAdd: - description = "Adds a new"; - break; - case RepositoryCommandRemove: - description = "Removes a"; - break; - case RepositoryCommandList: - description = "Lists all"; - break; - case RepositoryCommandSet: - description = "Set attributes for a"; - break; - default: - break; - } - - description += " " + m_Type + " object"; - - if (m_Command == RepositoryCommandList) - description += "s"; - - return description; -} - -String RepositoryObjectCommand::GetShortDescription(void) const -{ - String description; - - switch (m_Command) { - case RepositoryCommandAdd: - description = "adds a new"; - break; - case RepositoryCommandRemove: - description = "removes a"; - break; - case RepositoryCommandList: - description = "lists all"; - break; - case RepositoryCommandSet: - description = "set attributes for a"; - break; - default: - break; - } - - description += " " + m_Type + " object"; - - if (m_Command == RepositoryCommandList) - description += "s"; - - return description; -} - -bool RepositoryObjectCommand::IsDeprecated(void) const -{ - return true; -} - -void RepositoryObjectCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const -{ - if (m_Command == RepositoryCommandAdd) { - visibleDesc.add_options() - ("import", po::value >(), "Import the defined template into the object. Must be defined and included separately in Icinga 2"); - } -} - -std::vector RepositoryObjectCommand::GetPositionalSuggestions(const String& word) const -{ - if (m_Command == RepositoryCommandAdd) { - Type::Ptr ptype = Type::GetByName(m_Type); - ASSERT(ptype); - return GetFieldCompletionSuggestions(ptype, word); - } else if (m_Command == RepositoryCommandRemove) { - std::vector suggestions; - - String argName = "name="; - if (argName.Find(word) == 0) - suggestions.push_back(argName); - - if (m_Type == "Service") { - String argHostName = "host_name="; - if (argHostName.Find(word) == 0) - suggestions.push_back(argHostName); - } - - return suggestions; - } else - return CLICommand::GetPositionalSuggestions(word); -} - -ImpersonationLevel RepositoryObjectCommand::GetImpersonationLevel(void) const -{ - return ImpersonateRoot; -} - -int RepositoryObjectCommand::GetMaxArguments(void) const -{ - return -1; -} - -/** - * The entry point for the "repository " CLI command. - * - * @returns An exit status. - */ -int RepositoryObjectCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const -{ - Dictionary::Ptr attrs = RepositoryUtility::GetArgumentAttributes(ap); - - /* shortcut for list command */ - if (m_Command == RepositoryCommandList) { - RepositoryUtility::PrintObjects(std::cout, m_Type); - return 0; - } - - if (!attrs->Contains("name")) { - Log(LogCritical, "cli", "Object requires a name (Hint: 'name=')!"); - return 1; - } - - String name = attrs->Get("name"); - - if (vm.count("import")) { - Array::Ptr imports = new Array(); - - for (const String& import : vm["import"].as >()) { - imports->Add(import); - } - - //Update object attributes - if (imports->GetLength() > 0) - attrs->Set("import", imports); - } - - if (m_Command == RepositoryCommandAdd) { - std::vector object_paths = RepositoryUtility::GetObjects(); - - Array::Ptr changes = new Array(); - RepositoryUtility::GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changes)); - - RepositoryUtility::AddObject(object_paths, name, m_Type, attrs, changes); - } else if (m_Command == RepositoryCommandRemove) { - Array::Ptr changes = new Array(); - RepositoryUtility::GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changes)); - - /* pass attrs for service->host_name requirement */ - RepositoryUtility::RemoveObject(name, m_Type, attrs, changes); - } else if (m_Command == RepositoryCommandSet) { - Log(LogWarning, "cli") - << "Not supported yet. Please check the roadmap at https://github.com/Icinga/icinga2\n"; - return 1; - } else { - Log(LogCritical, "cli") - << "Invalid command '" << m_Command << "'specified.\n"; - return 1; - } - - return 0; -} diff --git a/lib/cli/repositoryobjectcommand.hpp b/lib/cli/repositoryobjectcommand.hpp deleted file mode 100644 index 960d5456e..000000000 --- a/lib/cli/repositoryobjectcommand.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef REPOSITORYOBJECTCOMMAND_H -#define REPOSITORYOBJECTCOMMAND_H - -#include "cli/clicommand.hpp" -#include - -namespace icinga -{ - -enum RepositoryCommandType -{ - RepositoryCommandAdd, - RepositoryCommandRemove, - RepositoryCommandList, - RepositoryCommandSet -}; - -/** - * The "repository " command. - * - * @ingroup cli - */ -class I2_CLI_API RepositoryObjectCommand : public CLICommand -{ -public: - DECLARE_PTR_TYPEDEFS(RepositoryObjectCommand); - - RepositoryObjectCommand(const String& type, RepositoryCommandType command); - - virtual String GetDescription(void) const override; - virtual String GetShortDescription(void) const override; - virtual int GetMaxArguments(void) const override; - virtual bool IsDeprecated(void) const override; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc) const override; - virtual ImpersonationLevel GetImpersonationLevel(void) const override; - virtual std::vector GetPositionalSuggestions(const String& word) const override; - virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override; - -private: - String m_Type; - RepositoryCommandType m_Command; -}; - -#define REGISTER_REPOSITORY_CLICOMMAND(type) \ - INITIALIZE_ONCE([]() { \ - String ltype = #type; \ - boost::algorithm::to_lower(ltype); \ -\ - std::vector name; \ - name.push_back("repository"); \ - name.push_back(ltype); \ - name.push_back("add"); \ - CLICommand::Register(name, new RepositoryObjectCommand(#type, RepositoryCommandAdd)); \ -\ - name[2] = "remove"; \ - CLICommand::Register(name, new RepositoryObjectCommand(#type, RepositoryCommandRemove)); \ -\ - name[2] = "list"; \ - CLICommand::Register(name, new RepositoryObjectCommand(#type, RepositoryCommandList)); \ - }) - -} - -#endif /* REPOSITORYOBJECTCOMMAND_H */ diff --git a/lib/cli/repositoryutility.cpp b/lib/cli/repositoryutility.cpp deleted file mode 100644 index d7b9fd02f..000000000 --- a/lib/cli/repositoryutility.cpp +++ /dev/null @@ -1,716 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "cli/repositoryutility.hpp" -#include "cli/clicommand.hpp" -#include "base/logger.hpp" -#include "base/application.hpp" -#include "base/convert.hpp" -#include "base/configwriter.hpp" -#include "base/scriptglobal.hpp" -#include "base/json.hpp" -#include "base/netstring.hpp" -#include "base/tlsutility.hpp" -#include "base/stdiostream.hpp" -#include "base/debug.hpp" -#include "base/objectlock.hpp" -#include "base/console.hpp" -#include "base/serializer.hpp" -#include "base/exception.hpp" -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace icinga; - -Dictionary::Ptr RepositoryUtility::GetArgumentAttributes(const std::vector& arguments) -{ - Dictionary::Ptr attrs = new Dictionary(); - - for (const String& kv : arguments) { - std::vector tokens; - boost::algorithm::split(tokens, kv, boost::is_any_of("=")); - - if (tokens.size() != 2) { - Log(LogWarning, "cli") - << "Cannot parse passed attributes: " << boost::algorithm::join(tokens, "="); - continue; - } - - Value value; - - try { - value = Convert::ToDouble(tokens[1]); - } catch (...) { - value = tokens[1]; - } - - attrs->Set(tokens[0], value); - } - - return attrs; -} - -String RepositoryUtility::GetRepositoryConfigPath(void) -{ - return Application::GetSysconfDir() + "/icinga2/repository.d"; -} - -String RepositoryUtility::GetRepositoryObjectConfigPath(const String& type, const Dictionary::Ptr& object) -{ - String path = GetRepositoryConfigPath() + "/"; - - if (type == "Host") - path += "hosts"; - else if (type == "Service") - path += "hosts/" + EscapeName(object->Get("host_name")); - else if (type == "Zone") - path += "zones"; - else if (type == "Endpoint") - path += "endpoints"; - - return path; -} - -bool RepositoryUtility::FilterRepositoryObjects(const String& type, const String& path) -{ - if (type == "Host") { - boost::regex expr("hosts/[^/]*.conf", boost::regex::icase); - boost::smatch what; - return boost::regex_search(path.GetData(), what, expr); - } - else if (type == "Service") - return Utility::Match("*hosts/*/*.conf", path); - else if (type == "Zone") - return Utility::Match("*zones/*.conf", path); - else if (type == "Endpoints") - return Utility::Match("*endpoints/*.conf", path); - - return false; -} - -String RepositoryUtility::GetRepositoryObjectConfigFilePath(const String& type, const Dictionary::Ptr& object) -{ - String path = GetRepositoryObjectConfigPath(type, object); - - path += "/" + EscapeName(object->Get("name")) + ".conf"; - - return path; -} - -String RepositoryUtility::GetRepositoryChangeLogPath(void) -{ - return Application::GetLocalStateDir() + "/lib/icinga2/repository/changes"; -} - -void RepositoryUtility::CreateRepositoryPath(const String& path) -{ - if (!Utility::PathExists(path)) - Utility::MkDirP(path, 0750); - - String user = ScriptGlobal::Get("RunAsUser"); - String group = ScriptGlobal::Get("RunAsGroup"); - - if (!Utility::SetFileOwnership(path, user, group)) { - Log(LogWarning, "cli") - << "Cannot set ownership for user '" << user << "' group '" << group << "' on path '" << path << "'. Verify it yourself!"; - } -} - -/* printers */ -void RepositoryUtility::PrintObjects(std::ostream& fp, const String& type) -{ - std::vector objects = GetObjects(); //full path - - for (const String& object : objects) { - if (!FilterRepositoryObjects(type, object)) { - Log(LogDebug, "cli") - << "Ignoring object '" << object << "'. Type '" << type << "' does not match."; - continue; - } - - String file = Utility::BaseName(object); - boost::algorithm::replace_all(file, ".conf", ""); - file = UnescapeName(file); - - fp << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << type << ConsoleColorTag(Console_Normal) - << " '" << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << file << ConsoleColorTag(Console_Normal) << "'"; - - String prefix = Utility::DirName(object); - - if (type == "Service") { - std::vector tokens; - boost::algorithm::split(tokens, prefix, boost::is_any_of("/")); - - String host_name = UnescapeName(tokens[tokens.size()-1]); - fp << " (on " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << "Host" << ConsoleColorTag(Console_Normal) - << " '" << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << host_name << ConsoleColorTag(Console_Normal) << "')"; - - } - - fp << "\n"; - } -} - -void RepositoryUtility::PrintChangeLog(std::ostream& fp) -{ - Array::Ptr changelog = new Array(); - - GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changelog)); - - ObjectLock olock(changelog); - - std::cout << "Changes to be committed:\n\n"; - - for (const Value& entry : changelog) { - FormatChangelogEntry(std::cout, entry); - } -} - -class RepositoryValidationUtils : public ValidationUtils -{ -public: - virtual bool ValidateName(const String& type, const String& name) const - { - return true; - } -}; - -/* modify objects and write changelog */ -bool RepositoryUtility::AddObject(const std::vector& object_paths, const String& name, const String& type, - const Dictionary::Ptr& attrs, const Array::Ptr& changes, bool check_config) -{ - String pattern; - - if (type == "Service") - pattern = EscapeName(attrs->Get("host_name")) + "/" + EscapeName(name) + ".conf"; - else - pattern = EscapeName(name) + ".conf"; - - for (const String& object_path : object_paths) { - if (object_path.Contains(pattern)) { - Log(LogWarning, "cli") - << type << " '" << name << "' already exists. Skipping creation."; - return false; - } - } - - /* add a new changelog entry by timestamp */ - String path = GetRepositoryChangeLogPath() + "/" + Convert::ToString(Utility::GetTime()) + "-" + type + "-" + SHA256(name) + ".change"; - - Dictionary::Ptr change = new Dictionary(); - - change->Set("timestamp", Utility::GetTime()); - change->Set("name", name); - change->Set("type", type); - change->Set("command", "add"); - change->Set("attrs", attrs); - - Type::Ptr utype = Type::GetByName(type); - ASSERT(utype); - - if (check_config) { - try { - ConfigObject::Ptr object = static_pointer_cast(utype->Instantiate(std::vector())); - /* temporarly set the object type for validation */ - attrs->Set("type", utype->GetName()); - Deserialize(object, attrs, false, FAConfig); - object->SetName(name); - - RepositoryValidationUtils utils; - static_pointer_cast(object)->Validate(FAConfig, utils); - - attrs->Remove("type"); - } catch (const ValidationError& ex) { - Log(LogCritical, "config", DiagnosticInformation(ex)); - return false; - } - } - - if (CheckChangeExists(change, changes)) { - Log(LogWarning, "cli") - << "Change '" << change->Get("command") << "' for type '" - << change->Get("type") << "' and name '" << change->Get("name") - << "' already exists."; - - return false; - } - - /* store the cached change */ - changes->Add(change); - - return WriteObjectToRepositoryChangeLog(path, change); -} - -bool RepositoryUtility::RemoveObject(const String& name, const String& type, const Dictionary::Ptr& attrs, const Array::Ptr& changes) -{ - /* add a new changelog entry by timestamp */ - String path = GetRepositoryChangeLogPath() + "/" + Convert::ToString(Utility::GetTime()) + "-" + type + "-" + SHA256(name) + ".change"; - - Dictionary::Ptr change = new Dictionary(); - - change->Set("timestamp", Utility::GetTime()); - change->Set("name", name); - change->Set("type", type); - change->Set("command", "remove"); - change->Set("attrs", attrs); //required for service->host_name - - if (CheckChangeExists(change, changes)) { - Log(LogWarning, "cli") - << "Change '" << change->Get("command") << "' for type '" - << change->Get("type") << "' and name '" << change->Get("name") - << "' already exists."; - - return false; - } - - /* store the cached change */ - changes->Add(change); - - return WriteObjectToRepositoryChangeLog(path, change); -} - -bool RepositoryUtility::SetObjectAttribute(const String& name, const String& type, const String& attr, const Value& val) -{ - //TODO: Implement modification commands - return true; -} - -bool RepositoryUtility::CheckChangeExists(const Dictionary::Ptr& change, const Array::Ptr& changes) -{ - Dictionary::Ptr attrs = change->Get("attrs"); - - ObjectLock olock(changes); - for (const Dictionary::Ptr& entry : changes) { - if (entry->Get("type") != change->Get("type")) - continue; - - if (entry->Get("name") != change->Get("name")) - continue; - - Dictionary::Ptr their_attrs = entry->Get("attrs"); - - if (entry->Get("type") == "Service" && attrs->Get("host_name") != their_attrs->Get("host_name")) - continue; - - if (entry->Get("command") != change->Get("command")) - continue; - - /* only works for add/remove commands (no set) */ - if (change->Get("command") == "add" || change->Get("command") == "remove") - return true; - } - - return false; -} - -bool RepositoryUtility::ClearChangeLog(void) -{ - GetChangeLog(boost::bind(RepositoryUtility::ClearChange, _1, _2)); - - return true; -} - -bool RepositoryUtility::ChangeLogHasPendingChanges(void) -{ - Array::Ptr changelog = new Array(); - GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changelog)); - - return changelog->GetLength() > 0; -} - -/* commit changelog */ -bool RepositoryUtility::CommitChangeLog(void) -{ - GetChangeLog(boost::bind(RepositoryUtility::CommitChange, _1, _2)); - - return true; -} - -/* write/read from changelog repository */ -bool RepositoryUtility::WriteObjectToRepositoryChangeLog(const String& path, const Dictionary::Ptr& item) -{ - Log(LogInformation, "cli", "Dumping changelog items to file '" + path + "'"); - - CreateRepositoryPath(Utility::DirName(path)); - - std::fstream fp; - String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", 0600, fp); - - fp << JsonEncode(item); - fp.close(); - -#ifdef _WIN32 - _unlink(path.CStr()); -#endif /* _WIN32 */ - - if (rename(tempFilename.CStr(), path.CStr()) < 0) { - BOOST_THROW_EXCEPTION(posix_error() - << boost::errinfo_api_function("rename") - << boost::errinfo_errno(errno) - << boost::errinfo_file_name(tempFilename)); - } - - return true; -} - -Dictionary::Ptr RepositoryUtility::GetObjectFromRepositoryChangeLog(const String& filename) -{ - std::fstream fp; - fp.open(filename.CStr(), std::ifstream::in); - - if (!fp) - return Dictionary::Ptr(); - - String content((std::istreambuf_iterator(fp)), std::istreambuf_iterator()); - - fp.close(); - - return JsonDecode(content); -} - -/* internal implementation when changes are committed */ -bool RepositoryUtility::AddObjectInternal(const String& name, const String& type, const Dictionary::Ptr& attrs) -{ - String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + EscapeName(name) + ".conf"; - - return WriteObjectToRepository(path, name, type, attrs); -} - -bool RepositoryUtility::RemoveObjectInternal(const String& name, const String& type, const Dictionary::Ptr& attrs) -{ - String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + EscapeName(name) + ".conf"; - - if (!Utility::PathExists(path)) { - Log(LogWarning, "cli") - << type << " '" << name << "' does not exist."; - return true; - } - - bool success = RemoveObjectFileInternal(path); - - if (success) - Log(LogInformation, "cli") - << "Removing config object '" << name << "' in file '" << path << "'"; - - /* special treatment for hosts -> remove the services too */ - if (type == "Host") { - path = GetRepositoryObjectConfigPath(type, attrs) + "/" + name; - - /* if path does not exist, this host does not have any services */ - if (!Utility::PathExists(path)) { - Log(LogNotice, "cli") - << type << " '" << name << "' does not have any services configured."; - return success; - } - - std::vector files; - - Utility::GlobRecursive(path, "*.conf", - boost::bind(&RepositoryUtility::CollectObjects, _1, boost::ref(files)), GlobFile); - - - for (const String& file : files) { - RemoveObjectFileInternal(file); - } -#ifndef _WIN32 - rmdir(path.CStr()); -#else - _rmdir(path.CStr()); -#endif /* _WIN32 */ - - } - - return success; -} - -bool RepositoryUtility::RemoveObjectFileInternal(const String& path) -{ - if (!Utility::PathExists(path) ) { - Log(LogCritical, "cli", "Cannot remove '" + path + "'. Does not exist."); - return false; - } - - if (unlink(path.CStr()) < 0) { - Log(LogCritical, "cli", "Cannot remove path '" + path + - "'. Failed with error code " + Convert::ToString(errno) + ", \"" + Utility::FormatErrorNumber(errno) + "\"."); - return false; - } - - return true; -} - -bool RepositoryUtility::SetObjectAttributeInternal(const String& name, const String& type, const String& key, const Value& val, const Dictionary::Ptr& attrs) -{ - //TODO - String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + EscapeName(name) + ".conf"; - - Dictionary::Ptr obj = GetObjectFromRepository(path); //TODO - - if (!obj) { - Log(LogCritical, "cli") - << "Can't get object " << name << " from repository.\n"; - return false; - } - - obj->Set(key, val); - - std::cout << "Writing object '" << name << "' to path '" << path << "'.\n"; - - //TODO: Create a patch file - if (!WriteObjectToRepository(path, name, type, obj)) { - Log(LogCritical, "cli") - << "Can't write object " << name << " to repository.\n"; - return false; - } - - return true; -} - -bool RepositoryUtility::WriteObjectToRepository(const String& path, const String& name, const String& type, const Dictionary::Ptr& item) -{ - Log(LogInformation, "cli") - << "Writing config object '" << name << "' to file '" << path << "'"; - - CreateRepositoryPath(Utility::DirName(path)); - - std::fstream fp; - String tempFilename = Utility::CreateTempFile(path + ".XXXXXX", 0644, fp); - - SerializeObject(fp, name, type, item); - fp << std::endl; - fp.close(); - -#ifdef _WIN32 - _unlink(path.CStr()); -#endif /* _WIN32 */ - - if (rename(tempFilename.CStr(), path.CStr()) < 0) { - BOOST_THROW_EXCEPTION(posix_error() - << boost::errinfo_api_function("rename") - << boost::errinfo_errno(errno) - << boost::errinfo_file_name(tempFilename)); - } - - return true; -} - -Dictionary::Ptr RepositoryUtility::GetObjectFromRepository(const String& filename) -{ - //TODO: Parse existing configuration objects - return Dictionary::Ptr(); -} - -String RepositoryUtility::EscapeName(const String& name) -{ - return Utility::EscapeString(name, "<>:\"/\\|?*", true); -} - -String RepositoryUtility::UnescapeName(const String& name) -{ - return Utility::UnescapeString(name); -} - -/* - * collect functions - */ -std::vector RepositoryUtility::GetObjects(void) -{ - std::vector objects; - String path = GetRepositoryConfigPath(); - - Utility::GlobRecursive(path, "*.conf", - boost::bind(&RepositoryUtility::CollectObjects, _1, boost::ref(objects)), GlobFile); - - return objects; -} - -void RepositoryUtility::CollectObjects(const String& object_file, std::vector& objects) -{ - Log(LogDebug, "cli") - << "Adding object: '" << object_file << "'."; - - objects.push_back(object_file); -} - - -bool RepositoryUtility::GetChangeLog(const boost::function& callback) -{ - std::vector changelog; - String path = GetRepositoryChangeLogPath() + "/"; - - Utility::MkDirP(path, 0700); - - Utility::Glob(path + "/*.change", - boost::bind(&RepositoryUtility::CollectChangeLog, _1, boost::ref(changelog)), GlobFile); - - /* sort by timestamp ascending */ - std::sort(changelog.begin(), changelog.end()); - - for (const String& entry : changelog) { - String file = path + entry + ".change"; - Dictionary::Ptr change = GetObjectFromRepositoryChangeLog(file); - - Log(LogDebug, "cli") - << "Collecting entry " << entry << "\n"; - - if (change) - callback(change, file); - } - - return true; -} - -void RepositoryUtility::CollectChangeLog(const String& change_file, std::vector& changelog) -{ - String file = Utility::BaseName(change_file); - boost::algorithm::replace_all(file, ".change", ""); - - Log(LogDebug, "cli") - << "Adding change file: '" << file << "'."; - - changelog.push_back(file); -} - -void RepositoryUtility::CollectChange(const Dictionary::Ptr& change, Array::Ptr& changes) -{ - changes->Add(change); -} - -/* - * Commit Changelog entry - */ -void RepositoryUtility::CommitChange(const Dictionary::Ptr& change, const String& path) -{ - Log(LogDebug, "cli") - << "Got change " << change->Get("name"); - - String name = change->Get("name"); - String type = change->Get("type"); - String command = change->Get("command"); - Dictionary::Ptr attrs; - - if (change->Contains("attrs")) - attrs = change->Get("attrs"); - - bool success = false; - - if (command == "add") - success = AddObjectInternal(name, type, attrs); - else if (command == "remove") - success = RemoveObjectInternal(name, type, attrs); - - if (success) { - Log(LogNotice, "cli") - << "Removing changelog file '" << path << "'."; - RemoveObjectFileInternal(path); - } -} - -/* - * Clear Changelog entry - */ -void RepositoryUtility::ClearChange(const Dictionary::Ptr& change, const String& path) -{ - Log(LogDebug, "cli") - << "Clearing change " << change->Get("name"); - - Log(LogInformation, "cli") - << "Removing changelog file '" << path << "'."; - - RemoveObjectFileInternal(path); -} - -/* - * Print Changelog helpers - */ -void RepositoryUtility::FormatChangelogEntry(std::ostream& fp, const Dictionary::Ptr& change) -{ - if (!change) - return; - - if (change->Get("command") == "add") - fp << "Adding"; - if (change->Get("command") == "remove") - fp << "Removing"; - - String type = change->Get("type"); - boost::algorithm::to_lower(type); - Dictionary::Ptr attrs = change->Get("attrs"); - - fp << " " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << type << ConsoleColorTag(Console_Normal) << " '"; - fp << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << change->Get("name") << ConsoleColorTag(Console_Normal) << "'\n"; - - ObjectLock olock(attrs); - for (const Dictionary::Pair& kv : attrs) { - /* skip the name */ - if (kv.first == "name" || kv.first == "__name") - continue; - - fp << std::setw(4) << " " << ConsoleColorTag(Console_ForegroundGreen) << kv.first << ConsoleColorTag(Console_Normal) << " = "; - ConfigWriter::EmitValue(fp, 0, kv.second); - fp << "\n"; - } -} - -/* - * print helpers for configuration - * TODO: Move into a separate class - */ -void RepositoryUtility::SerializeObject(std::ostream& fp, const String& name, const String& type, const Dictionary::Ptr& object) -{ - fp << "object " << type << " "; - ConfigWriter::EmitString(fp, name); - fp << " {\n"; - - if (!object) { - fp << "}\n"; - return; - } - - if (object->Contains("import")) { - Array::Ptr imports = object->Get("import"); - - ObjectLock olock(imports); - for (const String& import : imports) { - fp << "\t" << "import "; - ConfigWriter::EmitString(fp, import); - fp << '\n'; - } - } - - ObjectLock xlock(object); - for (const Dictionary::Pair& kv : object) { - if (kv.first == "import" || kv.first == "name" || kv.first == "__name") { - continue; - } else { - fp << "\t"; - ConfigWriter::EmitIdentifier(fp, kv.first, true); - fp << " = "; - ConfigWriter::EmitValue(fp, 1, kv.second); - } - fp << "\n"; - } - fp << "}\n"; -} diff --git a/lib/cli/repositoryutility.hpp b/lib/cli/repositoryutility.hpp deleted file mode 100644 index bdd2cb0fb..000000000 --- a/lib/cli/repositoryutility.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * - * * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#ifndef REPOSITORYUTILITY_H -#define REPOSITORYUTILITY_H - -#include "base/i2-base.hpp" -#include "cli/i2-cli.hpp" -#include "base/dictionary.hpp" -#include "base/array.hpp" -#include "base/value.hpp" -#include "base/string.hpp" -#include - -namespace icinga -{ - -/** - * @ingroup cli - */ -class I2_CLI_API RepositoryUtility -{ -public: - static Dictionary::Ptr GetArgumentAttributes(const std::vector& arguments); - - static String GetRepositoryConfigPath(void); - static String GetRepositoryObjectConfigPath(const String& type, const Dictionary::Ptr& object); - static String GetRepositoryObjectConfigFilePath(const String& type, const Dictionary::Ptr& object); - - static String GetRepositoryChangeLogPath(void); - - static void CreateRepositoryPath(const String& path); - - static bool FilterRepositoryObjects(const String& type, const String& path); - - static void PrintObjects(std::ostream& fp, const String& type); - - static void PrintChangeLog(std::ostream& fp); - - static bool AddObject(const std::vector& object_paths, const String& name, const String& type, const Dictionary::Ptr& attrs, - const Array::Ptr& changes, bool check_config = true); - static bool RemoveObject(const String& name, const String& type, const Dictionary::Ptr& attrs, const Array::Ptr& changes); - - static bool CheckChangeExists(const Dictionary::Ptr& change, const Array::Ptr& changes); - - static bool SetObjectAttribute(const String& name, const String& type, const String& attr, const Value& val); - - static bool CommitChangeLog(void); - static bool ClearChangeLog(void); - static bool ChangeLogHasPendingChanges(void); - static bool GetChangeLog(const boost::function& callback); - static void CollectChangeLog(const String& change_file, std::vector& changelog); - static void CollectChange(const Dictionary::Ptr& change, Array::Ptr& changes); - - static std::vector GetObjects(void); - static void CollectObjects(const String& object_file, std::vector& objects); - -private: - RepositoryUtility(void); - - static bool RemoveObjectFileInternal(const String& path); - - static bool AddObjectInternal(const String& name, const String& type, const Dictionary::Ptr& attrs); - static bool RemoveObjectInternal(const String& name, const String& type, const Dictionary::Ptr& attrs); - static bool SetObjectAttributeInternal(const String& name, const String& type, const String& key, - const Value& val, const Dictionary::Ptr& attrs); - - /* repository.d */ - static bool WriteObjectToRepository(const String& path, const String& name, const String& type, const Dictionary::Ptr& item); - static Dictionary::Ptr GetObjectFromRepository(const String& filename); - - /* changelog */ - static bool WriteObjectToRepositoryChangeLog(const String& path, const Dictionary::Ptr& item); - static Dictionary::Ptr GetObjectFromRepositoryChangeLog(const String& filename); - - static void CommitChange(const Dictionary::Ptr& change, const String& path); - static void ClearChange(const Dictionary::Ptr& change, const String& path); - - static void FormatChangelogEntry(std::ostream& fp, const Dictionary::Ptr& change); - - /* config print helpers */ - static void SerializeObject(std::ostream& fp, const String& name, const String& type, const Dictionary::Ptr& object); - static void FormatValue(std::ostream& fp, const Value& val); - static void FormatArray(std::ostream& fp, const Array::Ptr& arr); - - static String EscapeName(const String& name); - static String UnescapeName(const String& name); -}; - -} - -#endif /* REPOSITORYUTILITY_H */ diff --git a/lib/remote/CMakeLists.txt b/lib/remote/CMakeLists.txt index 32538deb1..29bdf3973 100644 --- a/lib/remote/CMakeLists.txt +++ b/lib/remote/CMakeLists.txt @@ -66,7 +66,6 @@ endif() #install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api\")") install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api/log\")") -install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api/repository\")") install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api/zones\")")