diff --git a/lib/cli/nodeupdateconfigcommand.cpp b/lib/cli/nodeupdateconfigcommand.cpp index 10c464f98..e7bcc02cf 100644 --- a/lib/cli/nodeupdateconfigcommand.cpp +++ b/lib/cli/nodeupdateconfigcommand.cpp @@ -88,6 +88,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm std::vector object_paths = RepositoryUtility::GetObjects(); + bool creation_error = false; BOOST_FOREACH(const Dictionary::Ptr& node, NodeUtility::GetNodes()) { Dictionary::Ptr repository = node->Get("repository"); String zone = node->Get("zone"); @@ -97,6 +98,107 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm /* 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); + BOOST_FOREACH(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"); + + ObjectLock olock(old_node_repository); + BOOST_FOREACH(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); //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); + + Dictionary::Ptr endpoint_attrs = new Dictionary(); + endpoint_attrs->Set("name", endpoint); + RepositoryUtility::RemoveObject(endpoint, "Endpoint", endpoint_attrs); + } 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"); + + ObjectLock xlock(old_node_repository); + BOOST_FOREACH(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 << "' on node '" << old_node << "' 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); //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); + BOOST_FOREACH(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); + } + } + } + } + } + } + } + Dictionary::Ptr host_services = new Dictionary(); Log(LogInformation, "cli") @@ -110,122 +212,127 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm host_imports->Add("satellite-host"); //default host node template host_attrs->Set("import", host_imports); - if (!RepositoryUtility::AddObject(zone, "Host", host_attrs)) - continue; + if (!RepositoryUtility::AddObject(zone, "Host", host_attrs)) { + Log(LogCritical, "cli") + << "Cannot add node host '" << zone << "' to the config repository!\n"; + creation_error = true; + } - ObjectLock olock(repository); - BOOST_FOREACH(const Dictionary::Pair& kv, repository) { - String host = kv.first; - String host_pattern = host + ".conf"; - bool skip_host = false; + if (repository) { + ObjectLock olock(repository); + BOOST_FOREACH(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; - } - - BOOST_FOREACH(const String& object_path, object_paths) { - if (object_path.Contains(host_pattern)) { + if (host == "localhost") { Log(LogWarning, "cli") - << "Host '" << host << "' already existing. Skipping its creation."; - skip_host = true; - break; + << "Ignoring host '" << host << "'. Please make sure to configure a unique name on your node '" << endpoint << "'."; + continue; } - } - - /* 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. Skipping."; - 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(host, "Host", host_attrs); - } - - /* 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); - BOOST_FOREACH(const String& service, services) { - bool skip_service = false; - - String service_pattern = host + "/" + service + ".conf"; BOOST_FOREACH(const String& object_path, object_paths) { - if (object_path.Contains(service_pattern)) { + if (object_path.Contains(host_pattern)) { Log(LogWarning, "cli") - << "Service '" << service << "' on Host '" << host << "' already existing. Skipping its creation."; - skip_service = true; + << "Host '" << host << "' already existing. Skipping its creation."; + skip_host = true; break; } } - /* check against black/whitelist before trying to add service */ - if (NodeUtility::CheckAgainstBlackAndWhiteList("blacklist", endpoint, host, service) && - !NodeUtility::CheckAgainstBlackAndWhiteList("whitelist", endpoint, host, service)) { + /* 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") - << "Service '" << service << "' on host '" << host << "' on node '" - << node_name << "' is blacklisted, but not whitelisted. Skipping."; - skip_service = true; + << "Host '" << host << "' on node '" << node_name << "' is blacklisted, but not whitelisted. Skipping."; + skip_host = true; + host_was_blacklisted = true; //check this for services on this blacklisted host } - if (skip_service) + 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(host, "Host", host_attrs); + } + + /* 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; + } - /* 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 services = kv.second; - Array::Ptr service_imports = new Array(); - service_imports->Add("satellite-service"); //default service node template - service_attrs->Set("import", service_imports); - - if (!RepositoryUtility::AddObject(service, "Service", service_attrs)) + if (services->GetLength() == 0) { + Log(LogNotice, "cli") + << "Host '" << host << "' without services."; continue; + } + + ObjectLock xlock(services); + BOOST_FOREACH(const String& service, services) { + bool skip_service = false; + + String service_pattern = host + "/" + service + ".conf"; + + 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_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. Skipping."; + 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(service, "Service", service_attrs)) + continue; + } } } @@ -243,9 +350,13 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm endpoint_attrs->Set("port", settings->Get("port")); } + Log(LogInformation, "cli") + << "Adding endpoint '" << endpoint << "' to the repository."; + if (!RepositoryUtility::AddObject(endpoint, "Endpoint", endpoint_attrs)) { Log(LogCritical, "cli") << "Cannot add node endpoint '" << endpoint << "' to the config repository!\n"; + creation_error = true; } Dictionary::Ptr zone_attrs = new Dictionary(); @@ -275,107 +386,13 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm zone_attrs->Set("parent", parent_zone); + Log(LogInformation, "cli") + << "Adding zone '" << zone << "' to the repository."; + if (!RepositoryUtility::AddObject(zone, "Zone", zone_attrs)) { Log(LogCritical, "cli") << "Cannot add node zone '" << zone << "' to the config repository!\n"; - } - } - - /* check if there are objects inside the old_inventory which do not exist anymore */ - BOOST_FOREACH(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_inventory->Get(old_node_name); - Dictionary::Ptr old_node_repository = old_node->Get("repository"); - - ObjectLock olock(old_node_repository); - BOOST_FOREACH(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); //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); - - Dictionary::Ptr endpoint_attrs = new Dictionary(); - endpoint_attrs->Set("name", endpoint); - RepositoryUtility::RemoveObject(endpoint, "Endpoint", endpoint_attrs); - } 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_inventory->Get(old_node_name); - Dictionary::Ptr old_node_repository = old_node->Get("repository"); - - ObjectLock xlock(old_node_repository); - BOOST_FOREACH(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 << "' on node '" << old_node << "' 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); //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); - BOOST_FOREACH(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); - } - } - } - } + creation_error = true; } } diff --git a/lib/cli/nodeutility.cpp b/lib/cli/nodeutility.cpp index e3387e87b..2133bc9ec 100644 --- a/lib/cli/nodeutility.cpp +++ b/lib/cli/nodeutility.cpp @@ -56,17 +56,17 @@ String NodeUtility::GetNodeSettingsFile(const String& name) return GetRepositoryPath() + "/" + SHA256(name) + ".settings"; } -void NodeUtility::CreateRepositoryPath(void) +void NodeUtility::CreateRepositoryPath(const String& path) { - if (!Utility::PathExists(GetRepositoryPath())) - Utility::MkDirP(GetRepositoryPath(), 0750); + if (!Utility::PathExists(path)) + Utility::MkDirP(path, 0750); String user = ScriptVariable::Get("RunAsUser"); String group = ScriptVariable::Get("RunAsGroup"); - if (!Utility::SetFileOwnership(GetRepositoryPath(), user, group)) { + if (!Utility::SetFileOwnership(path, user, group)) { Log(LogWarning, "cli") - << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << GetRepositoryPath() << "'. Verify it yourself!"; + << "Cannot set ownership for user '" << user << "' group '" << group << "' on path '" << path << "'. Verify it yourself!"; } } @@ -370,7 +370,21 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt /* create a backup first */ CreateBackupFile(filename); - Utility::MkDirP(Utility::DirName(filename), 0755); + String path = Utility::DirName(filename); + + Utility::MkDirP(path, 0755); + + String user = ScriptVariable::Get("RunAsUser"); + String group = ScriptVariable::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!"; + } + if (!Utility::SetFileOwnership(filename, user, group)) { + Log(LogWarning, "cli") + << "Cannot set ownership for user '" << user << "' group '" << group << "' on path '" << path << "'. Verify it yourself!"; + } String tempPath = filename + ".tmp"; @@ -382,7 +396,6 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt fp << " */\n\n"; ObjectLock olock(objects); - BOOST_FOREACH(const Dictionary::Ptr& object, objects) { String name = object->Get("__name"); String type = object->Get("__type"); diff --git a/lib/cli/nodeutility.hpp b/lib/cli/nodeutility.hpp index f2c748d8c..f90f14919 100644 --- a/lib/cli/nodeutility.hpp +++ b/lib/cli/nodeutility.hpp @@ -39,7 +39,7 @@ public: static String GetRepositoryPath(void); static String GetNodeRepositoryFile(const String& name); static String GetNodeSettingsFile(const String& name); - static void CreateRepositoryPath(void); + static void CreateRepositoryPath(const String& path = GetRepositoryPath()); static std::vector GetNodeCompletionSuggestions(const String& word); static void PrintNodes(std::ostream& fp); diff --git a/lib/cli/objectlistcommand.cpp b/lib/cli/objectlistcommand.cpp index 951dd12b8..bbab345eb 100644 --- a/lib/cli/objectlistcommand.cpp +++ b/lib/cli/objectlistcommand.cpp @@ -154,7 +154,6 @@ void ObjectListCommand::PrintProperties(std::ostream& fp, const Dictionary::Ptr& int offset = 2; ObjectLock olock(props); - BOOST_FOREACH(const Dictionary::Pair& kv, props) { String key = kv.first; Value val = kv.second; diff --git a/lib/cli/repositoryutility.cpp b/lib/cli/repositoryutility.cpp index a02b024b9..d2a36bb66 100644 --- a/lib/cli/repositoryutility.cpp +++ b/lib/cli/repositoryutility.cpp @@ -25,6 +25,7 @@ #include "base/logger.hpp" #include "base/application.hpp" #include "base/convert.hpp" +#include "base/scriptvariable.hpp" #include "base/json.hpp" #include "base/netstring.hpp" #include "base/tlsutility.hpp" @@ -124,6 +125,20 @@ 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 = ScriptVariable::Get("RunAsUser"); + String group = ScriptVariable::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) { @@ -355,7 +370,7 @@ bool RepositoryUtility::WriteObjectToRepositoryChangeLog(const String& path, con { Log(LogInformation, "cli", "Dumping changelog items to file '" + path + "'"); - Utility::MkDirP(Utility::DirName(path), 0750); + CreateRepositoryPath(Utility::DirName(path)); String tempPath = path + ".tmp"; @@ -495,7 +510,7 @@ bool RepositoryUtility::WriteObjectToRepository(const String& path, const String Log(LogInformation, "cli") << "Writing config object '" << name << "' to file '" << path << "'"; - Utility::MkDirP(Utility::DirName(path), 0755); + CreateRepositoryPath(Utility::DirName(path)); String tempPath = path + ".tmp"; @@ -656,6 +671,7 @@ void RepositoryUtility::FormatChangelogEntry(std::ostream& fp, const Dictionary: 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); BOOST_FOREACH(const Dictionary::Pair& kv, attrs) { /* skip the name */ if (kv.first == "name" || kv.first == "__name") @@ -689,6 +705,7 @@ void RepositoryUtility::SerializeObject(std::ostream& fp, const String& name, co } } + ObjectLock xlock(object); BOOST_FOREACH(const Dictionary::Pair& kv, object) { if (kv.first == "import" || kv.first == "name" || kv.first == "__name") { continue; diff --git a/lib/cli/repositoryutility.hpp b/lib/cli/repositoryutility.hpp index 64d64392d..f4a6e302a 100644 --- a/lib/cli/repositoryutility.hpp +++ b/lib/cli/repositoryutility.hpp @@ -44,6 +44,8 @@ public: 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);