mirror of https://github.com/Icinga/icinga2.git
parent
aa6ad55212
commit
601c10b997
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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 <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
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<std::string>& ap) const
|
||||
{
|
||||
NodeUtility::AddNode(ap[0]);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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<std::string>& ap) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* NODEADDCOMMAND_H */
|
|
@ -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 <iostream>
|
||||
#include <fstream>
|
||||
|
||||
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<std::string>(), "The name of the zone")
|
||||
("host", po::value<std::string>(), "The name of the host")
|
||||
("service", po::value<std::string>(), "The name of the service");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The entry point for the "node <whitelist/blacklist> <add/remove/list>" CLI command.
|
||||
*
|
||||
* @returns An exit status.
|
||||
*/
|
||||
int BlackAndWhitelistCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& 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<std::string>();
|
||||
|
||||
return NodeUtility::UpdateBlackAndWhiteList(m_Type, vm["zone"].as<std::string>(), vm["host"].as<std::string>(), 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<std::string>();
|
||||
String host_filter = vm["host"].as<std::string>();
|
||||
String service_filter;
|
||||
|
||||
if (vm.count("service")) {
|
||||
service_filter = vm["service"].as<std::string>();
|
||||
}
|
||||
|
||||
return NodeUtility::RemoveBlackAndWhiteList(m_Type, vm["zone"].as<std::string>(), vm["host"].as<std::string>(), service_filter);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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 <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
enum BlackAndWhitelistCommandType
|
||||
{
|
||||
BlackAndWhitelistCommandAdd,
|
||||
BlackAndWhitelistCommandRemove,
|
||||
BlackAndWhitelistCommandList
|
||||
};
|
||||
|
||||
/**
|
||||
* The "repository <type> <add/remove/list>" 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<std::string>& 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<String> 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 */
|
|
@ -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 <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
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<std::string>& 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;
|
||||
}
|
|
@ -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<std::string>& ap) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* NODELISTCOMMAND_H */
|
|
@ -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 <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
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<String> 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<std::string>& ap) const
|
||||
{
|
||||
for (const String& node : ap) {
|
||||
NodeUtility::RemoveNode(node);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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<String> GetPositionalSuggestions(const String& word) const override;
|
||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* NODEREMOVECOMMAND_H */
|
|
@ -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 <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
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<std::string>(), "Icinga 2 host")
|
||||
("port", po::value<std::string>(), "Icinga 2 port")
|
||||
("log_duration", po::value<double>(), "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<std::string>& 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<std::string>();
|
||||
|
||||
if (vm.count("port"))
|
||||
port = vm["port"].as<std::string>();
|
||||
|
||||
if (vm.count("log_duration"))
|
||||
log_duration = vm["log_duration"].as<double>();
|
||||
|
||||
NodeUtility::AddNodeSettings(ap[0], host, port, log_duration);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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<std::string>& ap) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* NODESETCOMMAND_H */
|
|
@ -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 <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
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<std::string>& 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<String> 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<Dictionary::Ptr> 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;
|
||||
}
|
|
@ -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<std::string>& ap) const override;
|
||||
virtual ImpersonationLevel GetImpersonationLevel(void) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* NODEUPDATECONFIGCOMMAND_H */
|
|
@ -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 <fstream>
|
||||
#include <iostream>
|
||||
|
||||
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<std::string>& 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;
|
||||
}
|
|
@ -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 <ostream>
|
||||
|
||||
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<std::string>& ap) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* REPOSITORYCLEARCHANGESCOMMAND_H */
|
|
@ -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 <fstream>
|
||||
#include <iostream>
|
||||
|
||||
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<std::string>& 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;
|
||||
}
|
|
@ -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 <ostream>
|
||||
|
||||
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<std::string>& ap) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* REPOSITORYCOMMITCOMMAND_H */
|
|
@ -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 <fstream>
|
||||
#include <iostream>
|
||||
|
||||
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<std::vector<std::string> >(), "Import the defined template into the object. Must be defined and included separately in Icinga 2");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<String> 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<String> 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 <type> <add/remove/list>" CLI command.
|
||||
*
|
||||
* @returns An exit status.
|
||||
*/
|
||||
int RepositoryObjectCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& 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=<objectname>')!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
String name = attrs->Get("name");
|
||||
|
||||
if (vm.count("import")) {
|
||||
Array::Ptr imports = new Array();
|
||||
|
||||
for (const String& import : vm["import"].as<std::vector<std::string> >()) {
|
||||
imports->Add(import);
|
||||
}
|
||||
|
||||
//Update object attributes
|
||||
if (imports->GetLength() > 0)
|
||||
attrs->Set("import", imports);
|
||||
}
|
||||
|
||||
if (m_Command == RepositoryCommandAdd) {
|
||||
std::vector<String> 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;
|
||||
}
|
|
@ -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 <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
enum RepositoryCommandType
|
||||
{
|
||||
RepositoryCommandAdd,
|
||||
RepositoryCommandRemove,
|
||||
RepositoryCommandList,
|
||||
RepositoryCommandSet
|
||||
};
|
||||
|
||||
/**
|
||||
* The "repository <type> <add/remove/list>" 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<String> GetPositionalSuggestions(const String& word) const override;
|
||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& 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<String> 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 */
|
|
@ -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 <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
Dictionary::Ptr RepositoryUtility::GetArgumentAttributes(const std::vector<std::string>& arguments)
|
||||
{
|
||||
Dictionary::Ptr attrs = new Dictionary();
|
||||
|
||||
for (const String& kv : arguments) {
|
||||
std::vector<String> 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<String> 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<String> 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<String>& 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<ConfigObject>(utype->Instantiate(std::vector<Value>()));
|
||||
/* 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<ConfigObject>(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<char>(fp)), std::istreambuf_iterator<char>());
|
||||
|
||||
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<String> 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<String> RepositoryUtility::GetObjects(void)
|
||||
{
|
||||
std::vector<String> 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<String>& objects)
|
||||
{
|
||||
Log(LogDebug, "cli")
|
||||
<< "Adding object: '" << object_file << "'.";
|
||||
|
||||
objects.push_back(object_file);
|
||||
}
|
||||
|
||||
|
||||
bool RepositoryUtility::GetChangeLog(const boost::function<void (const Dictionary::Ptr&, const String&)>& callback)
|
||||
{
|
||||
std::vector<String> 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<String>& 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";
|
||||
}
|
|
@ -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 <boost/function.hpp>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* @ingroup cli
|
||||
*/
|
||||
class I2_CLI_API RepositoryUtility
|
||||
{
|
||||
public:
|
||||
static Dictionary::Ptr GetArgumentAttributes(const std::vector<std::string>& 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<String>& 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<void (const Dictionary::Ptr&, const String&)>& callback);
|
||||
static void CollectChangeLog(const String& change_file, std::vector<String>& changelog);
|
||||
static void CollectChange(const Dictionary::Ptr& change, Array::Ptr& changes);
|
||||
|
||||
static std::vector<String> GetObjects(void);
|
||||
static void CollectObjects(const String& object_file, std::vector<String>& 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 */
|
|
@ -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\")")
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue