mirror of https://github.com/Icinga/icinga2.git
Cli: Don't overwrite existing objects; delete old agent objects on 'agent update-config'
refs #7248
This commit is contained in:
parent
d92dc8539d
commit
16069a7368
|
@ -23,6 +23,7 @@
|
|||
#include "base/logger.hpp"
|
||||
#include "base/application.hpp"
|
||||
#include "base/objectlock.hpp"
|
||||
#include "base/json.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
@ -66,22 +67,57 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
|
|||
return 1;
|
||||
}
|
||||
|
||||
String inventory_path = AgentUtility::GetRepositoryPath() + "/inventory.index";
|
||||
|
||||
Dictionary::Ptr old_inventory = make_shared<Dictionary>();
|
||||
if (Utility::PathExists(inventory_path)) {
|
||||
old_inventory = Utility::LoadJsonFile(inventory_path);
|
||||
}
|
||||
|
||||
Dictionary::Ptr inventory = make_shared<Dictionary>();
|
||||
|
||||
Log(LogInformation, "cli")
|
||||
<< "Updating agent configuration for ";
|
||||
|
||||
AgentUtility::PrintAgents(std::cout);
|
||||
|
||||
Utility::LoadExtensionLibrary("icinga");
|
||||
|
||||
std::vector<String> object_paths = RepositoryUtility::GetObjects();
|
||||
|
||||
BOOST_FOREACH(const Dictionary::Ptr& agent, AgentUtility::GetAgents()) {
|
||||
|
||||
/* store existing structure in index */
|
||||
inventory->Set(agent->Get("endpoint"), agent);
|
||||
|
||||
Dictionary::Ptr repository = agent->Get("repository");
|
||||
String zone = agent->Get("zone");
|
||||
String endpoint = agent->Get("endpoint");
|
||||
|
||||
Dictionary::Ptr host_services = make_shared<Dictionary>();
|
||||
|
||||
ObjectLock olock(repository);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, repository) {
|
||||
String host = kv.first;
|
||||
String host_pattern = host + ".conf";
|
||||
bool skip = false;
|
||||
|
||||
BOOST_FOREACH(const String& object_path, object_paths) {
|
||||
if (object_path.Contains(host_pattern)) {
|
||||
Log(LogWarning, "cli")
|
||||
<< "Host '" << host << "' already existing. Skipping its creation.";
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
/* add a new host to the config repository */
|
||||
Dictionary::Ptr host_attrs = make_shared<Dictionary>();
|
||||
host_attrs->Set("__name", host);
|
||||
host_attrs->Set("name", host);
|
||||
host_attrs->Set("check_command", "dummy"); //TODO: add a repository-host template
|
||||
host_attrs->Set("zone", zone);
|
||||
|
||||
|
@ -92,11 +128,36 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
|
|||
}
|
||||
|
||||
Array::Ptr services = kv.second;
|
||||
|
||||
if (services->GetLength() == 0) {
|
||||
Log(LogNotice, "cli")
|
||||
<< "Host '" << host << "' without services.";
|
||||
continue;
|
||||
}
|
||||
|
||||
ObjectLock xlock(services);
|
||||
BOOST_FOREACH(const String& service, services) {
|
||||
|
||||
String service_pattern = host + "/" + service + ".conf";
|
||||
bool skip = false;
|
||||
|
||||
BOOST_FOREACH(const String& object_path, object_paths) {
|
||||
if (object_path.Contains(service_pattern)) {
|
||||
Log(LogWarning, "cli")
|
||||
<< "Service '" << service << "' on Host '" << host << "' already existing. Skipping its creation.";
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
/* add a new service for this host to the config repository */
|
||||
Dictionary::Ptr service_attrs = make_shared<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"); //TODO: add a repository-service template
|
||||
service_attrs->Set("zone", zone);
|
||||
|
@ -111,6 +172,8 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
|
|||
|
||||
/* write a new zone and endpoint for the agent */
|
||||
Dictionary::Ptr endpoint_attrs = make_shared<Dictionary>();
|
||||
endpoint_attrs->Set("__name", endpoint);
|
||||
endpoint_attrs->Set("name", endpoint);
|
||||
|
||||
Dictionary::Ptr settings = agent->Get("settings");
|
||||
|
||||
|
@ -130,6 +193,8 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
|
|||
Array::Ptr zone_members = make_shared<Array>();
|
||||
|
||||
zone_members->Add(endpoint);
|
||||
zone_attrs->Set("__name", zone);
|
||||
zone_attrs->Set("name", zone);
|
||||
zone_attrs->Set("endpoints", zone_members);
|
||||
zone_attrs->Set("parent", agent->Get("parent_zone"));
|
||||
|
||||
|
@ -139,12 +204,91 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
|
|||
}
|
||||
}
|
||||
|
||||
/* check if there are objects inside the old_inventory which do not exist anymore */
|
||||
BOOST_FOREACH(const Dictionary::Pair& old_agent_objs, old_inventory) {
|
||||
|
||||
String old_agent_name = old_agent_objs.first;
|
||||
|
||||
/* check if the agent was dropped */
|
||||
if (!inventory->Contains(old_agent_name)) {
|
||||
Log(LogInformation, "cli")
|
||||
<< "Agent update found old agent '" << old_agent_name << "'. Removing it and all of its hosts/services.";
|
||||
|
||||
//TODO Remove an agent and all of his hosts
|
||||
Dictionary::Ptr old_agent = old_inventory->Get(old_agent_name);
|
||||
Dictionary::Ptr old_agent_repository = old_agent->Get("repository");
|
||||
|
||||
ObjectLock olock(old_agent_repository);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, old_agent_repository) {
|
||||
String host = kv.first;
|
||||
|
||||
Dictionary::Ptr host_attrs = make_shared<Dictionary>();
|
||||
host_attrs->Set("name", host);
|
||||
RepositoryUtility::RemoveObject(host, "Host", host_attrs); //this removes all services for this host as well
|
||||
}
|
||||
|
||||
//TODO: Remove zone/endpoint information as well
|
||||
String zone = old_agent->Get("zone");
|
||||
String endpoint = old_agent->Get("endpoint");
|
||||
|
||||
Dictionary::Ptr zone_attrs = make_shared<Dictionary>();
|
||||
zone_attrs->Set("name", zone);
|
||||
RepositoryUtility::RemoveObject(zone, "Zone", zone_attrs);
|
||||
|
||||
Dictionary::Ptr endpoint_attrs = make_shared<Dictionary>();
|
||||
endpoint_attrs->Set("name", endpoint);
|
||||
RepositoryUtility::RemoveObject(endpoint, "Endpoint", endpoint_attrs);
|
||||
} else {
|
||||
/* get the current agent */
|
||||
Dictionary::Ptr new_agent = inventory->Get(old_agent_name);
|
||||
Dictionary::Ptr new_agent_repository = new_agent->Get("repository");
|
||||
|
||||
Dictionary::Ptr old_agent = old_inventory->Get(old_agent_name);
|
||||
Dictionary::Ptr old_agent_repository = old_agent->Get("repository");
|
||||
|
||||
ObjectLock xlock(old_agent_repository);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, old_agent_repository) {
|
||||
String old_host = kv.first;
|
||||
|
||||
if (!new_agent_repository->Contains(old_host)) {
|
||||
Log(LogInformation, "cli")
|
||||
<< "Agent update found old host '" << old_host << "' on agent '" << old_agent_name << "'. Removing it.";
|
||||
|
||||
Dictionary::Ptr host_attrs = make_shared<Dictionary>();
|
||||
host_attrs->Set("name", old_host);
|
||||
RepositoryUtility::RemoveObject(old_host, "Host", host_attrs); //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_agent_repository->Get(old_host);
|
||||
|
||||
ObjectLock ylock(old_services);
|
||||
BOOST_FOREACH(const String& old_service, old_services) {
|
||||
if (!new_services->Contains(old_service)) {
|
||||
Log(LogInformation, "cli")
|
||||
<< "Agent update found old service '" << old_service << "' on host '" << old_host
|
||||
<< "' on agent '" << old_agent_name << "'. Removing it.";
|
||||
|
||||
Dictionary::Ptr service_attrs = make_shared<Dictionary>();
|
||||
service_attrs->Set("name", old_service);
|
||||
service_attrs->Set("host_name", old_host);
|
||||
RepositoryUtility::RemoveObject(old_service, "Service", service_attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log(LogInformation, "cli", "Committing agent configuration.");
|
||||
|
||||
RepositoryUtility::PrintChangeLog(std::cout);
|
||||
std::cout << "\n";
|
||||
RepositoryUtility::CommitChangeLog();
|
||||
|
||||
/* store the new inventory for next run */
|
||||
Utility::SaveJsonFile(inventory_path, inventory);
|
||||
|
||||
std::cout << "Make sure to reload Icinga 2 for these changes to take effect." << std::endl;
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue