From ddc5b951b3a692a4be02bb2d551327db65f65468 Mon Sep 17 00:00:00 2001
From: Markus Frosch <markus@lazyfrosch.de>
Date: Thu, 26 Jul 2018 17:09:06 +0200
Subject: [PATCH] Revert "Implement support for the --env command-line
 argument"

---
 doc/06-distributed-monitoring.md        |  32 --------
 icinga-app/icinga.cpp                   | 103 +-----------------------
 icinga-installer/icinga2.wixpatch.cmake |   6 +-
 lib/cli/apisetupcommand.cpp             |  13 +--
 lib/cli/apisetupcommand.hpp             |   2 -
 lib/cli/apisetuputility.cpp             |  10 +--
 lib/cli/apisetuputility.hpp             |   4 +-
 lib/cli/featureutility.cpp              |  14 ++--
 lib/cli/featureutility.hpp              |   4 +-
 lib/remote/apilistener.cpp              |  49 ++---------
 lib/remote/apilistener.hpp              |   1 -
 11 files changed, 27 insertions(+), 211 deletions(-)

diff --git a/doc/06-distributed-monitoring.md b/doc/06-distributed-monitoring.md
index 6402a1a3e..985e23fd9 100644
--- a/doc/06-distributed-monitoring.md
+++ b/doc/06-distributed-monitoring.md
@@ -2793,35 +2793,3 @@ Add the global zone `global-templates` in case it did not exist.
       global = true
     }
     EOF
-
-## Using Multiple Environments <a id="distributed-monitoring-environments"></a>
-
-In some cases it might be useful to run multiple Icinga instance on the same host. Two potential scenarios include:
-
-* running different versions of the same monitoring configuration (e.g. production and testing)
-* running disparate sets of checks for entirely unrelated monitoring environments (e.g. infrastructure and applications)
-
-Icinga supports these scenarios by providing a global variable called `Environment`. It can be set like any other
-global variable, e.g. in the `constants.conf` file or in a file in a global template zone.
-
-The `Environment` variable can also be set using the `--env` command-line option. Setting the variable this way
-has the added effect that Icinga tries to determine if the `Icinga Environments` add-on is available and
-if so uses its CLI commands to determine the configuration and data paths. This command-line option also has the
-effect of changing the listener port for cluster feature to a random port which is made available to the
-`Icinga Environments` add-on through its `config.json` file.
-
-When Icinga establishes a TLS connection to another cluster instance it automatically uses the SNI extension
-to signal which endpoint it is attempting to connect to. On its own this can already be used to position multiple
-Icinga instances behind a load balancer.
-
-SNI example: `icinga2-client1.localdomain`
-
-However, if the `Environment` variable is non-empty Icinga will append the environment name to the SNI hostname
-like this:
-
-SNI example with environment: `icinga2-client1.localdomain:production`
-
-The Icinga Environments add-on provides a reverse proxy which does SNI-based port multiplexing. I.e., it uses a
-single externally-visible TCP port (usually 5665) and forwards connections to one or more Icinga instances
-which are bound to a local TCP port. It does so by inspecting the environment name that is sent as part of the
-SNI extension.
diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp
index 957cea61b..404cedf30 100644
--- a/icinga-app/icinga.cpp
+++ b/icinga-app/icinga.cpp
@@ -32,8 +32,6 @@
 #include "base/context.hpp"
 #include "base/console.hpp"
 #include "base/process.hpp"
-#include "base/json.hpp"
-#include "base/tcpsocket.hpp"
 #include "config.h"
 #include <boost/program_options.hpp>
 #include <boost/algorithm/string/split.hpp>
@@ -48,9 +46,6 @@
 #	include <Lmcons.h>
 #	include <Shellapi.h>
 #	include <tchar.h>
-
-#	define popen _popen
-#	define pclose _pclose
 #endif /* _WIN32 */
 
 using namespace icinga;
@@ -220,6 +215,8 @@ static int Main()
 	Application::DeclareConcurrency(std::thread::hardware_concurrency());
 	Application::DeclareMaxConcurrentChecks(Application::GetDefaultMaxConcurrentChecks());
 
+	ScriptGlobal::Set("Environment", "production");
+
 	ScriptGlobal::Set("AttachDebugger", false);
 
 	ScriptGlobal::Set("PlatformKernel", Utility::GetPlatformKernel());
@@ -250,8 +247,7 @@ static int Main()
 		("include,I", po::value<std::vector<std::string> >(), "add include search directory")
 		("log-level,x", po::value<std::string>(), "specify the log level for the console log.\n"
 			"The valid value is either debug, notice, information (default), warning, or critical")
-		("script-debugger,X", "whether to enable the script debugger")
-		("env", po::value<std::string>(), "the name of the environment, e.g. \"production\"");
+		("script-debugger,X", "whether to enable the script debugger");
 
 	po::options_description hiddenDesc("Hidden options");
 
@@ -275,99 +271,6 @@ static int Main()
 		return EXIT_FAILURE;
 	}
 
-	if (vm.count("env") && vm["env"].as<std::string>() != "") {
-		String env = vm["env"].as<std::string>();
-		ScriptGlobal::Set("Environment", env);
-	} else {
-#ifndef _WIN32
-		String cmd = "icinga-envs";
-#else /* _WIN32 */
-		String cmd = "\"" + Utility::DirName(Application::GetExePath(argv[0])) + "\\icinga-envs.exe" + "\"";
-#endif /* _WIN32 */
-		cmd += " get-default";
-#ifndef _WIN32
-		cmd += " 2>/dev/null";
-#else /* _WIN32 */
-		cmd += " 2>NUL";
-		cmd = "\"" + cmd + "\"";
-#endif /* _WIN32 */
-
-		FILE *fp = popen(cmd.CStr(), "r");
-		std::stringstream msgbuf;
-		while (!ferror(fp) && !feof(fp)) {
-			char buf[512];
-			size_t num = fread(buf, 1, sizeof(buf), fp);
-			msgbuf << std::string(buf, buf + num);
-		}
-		pclose(fp);
-
-		String env = msgbuf.str();
-		ScriptGlobal::Set("Environment", env.Trim());
-	}
-
-	String env = ScriptGlobal::Get("Environment", NULL);
-#ifndef _WIN32
-	String cmd = "icinga-envs";
-#else /* _WIN32 */
-	String cmd = "\"" + Utility::DirName(Application::GetExePath(argv[0])) + "\\icinga-envs.exe" + "\"";
-#endif /* _WIN32 */
-	cmd += " info --json " + Utility::EscapeShellArg(env);
-#ifndef _WIN32
-	cmd += " 2>/dev/null";
-#else /* _WIN32 */
-	cmd += " 2>NUL";
-	cmd = "\"" + cmd + "\"";
-#endif /* _WIN32 */
-
-	FILE *fp = popen(cmd.CStr(), "r");
-	std::stringstream msgbuf;
-	while (!ferror(fp) && !feof(fp)) {
-		char buf[512];
-		size_t num = fread(buf, 1, sizeof(buf), fp);
-		msgbuf << std::string(buf, buf + num);
-	}
-	pclose(fp);
-
-	Dictionary::Ptr envInfo;
-	try {
-		envInfo = JsonDecode(msgbuf.str());
-	} catch (const std::exception&) {}
-
-	if (envInfo) {
-		Dictionary::Ptr config = envInfo->Get("config");
-
-		if (!config) {
-			Log(LogCritical, "app")
-			    << "Invalid JSON returned by icinga-envs: " << msgbuf.str();
-			return EXIT_FAILURE;
-		}
-
-		String configPath = config->Get("config_path");
-		String dataPath = config->Get("data_path");
-
-		ScriptGlobal::Set("SysconfDir", configPath);
-		ScriptGlobal::Set("RunDir", dataPath + "/run");
-		ScriptGlobal::Set("LocalStateDir", dataPath);
-
-		TcpSocket::Ptr agentListener = new TcpSocket();
-		agentListener->Bind("127.0.0.1", "0", AF_INET);
-		auto pieces = agentListener->GetClientAddress().Split(":");
-		config->Set("port", Convert::ToLong(pieces[pieces.size() - 1]));
-
-		Dictionary::Ptr envData = new Dictionary({
-			{ "listener", agentListener },
-			{ "config", config },
-			{ "meta_path", envInfo->Get("env_path") + "/config.json" }
-		});
-
-		// Make the agent listener available to the ApiListener later on
-		ScriptGlobal::Set("EnvironmentInfo", envData);
-	} else if (env != "") {
-		Log(LogCritical, "app")
-		    << "No such environment exists: " << env;
-		return EXIT_FAILURE;
-	}
-
 #ifdef _WIN32
 	char username[UNLEN + 1];
 	DWORD usernameLen = UNLEN + 1;
diff --git a/icinga-installer/icinga2.wixpatch.cmake b/icinga-installer/icinga2.wixpatch.cmake
index ab400ed1e..0666261d2 100644
--- a/icinga-installer/icinga2.wixpatch.cmake
+++ b/icinga-installer/icinga2.wixpatch.cmake
@@ -10,9 +10,9 @@
     <Binary Id="icinga2_installer" SourceFile="$<TARGET_FILE:icinga-installer>" />
     
     <InstallExecuteSequence>
-      <Custom Action="XtraUpgradeNSIS" After="InstallInitialize">$CM_CP_sbin.icinga2_installer.exe&gt;2 AND NOT SUPPRESS_XTRA</Custom>
-      <Custom Action="XtraInstall" Before="InstallFinalize">$CM_CP_sbin.icinga2_installer.exe&gt;2 AND NOT SUPPRESS_XTRA</Custom>
-      <Custom Action="XtraUninstall" Before="RemoveExistingProducts">$CM_CP_sbin.icinga2_installer.exe=2 AND NOT SUPPRESS_XTRA</Custom>
+      <Custom Action="XtraUpgradeNSIS" After="InstallInitialize">$CM_CP_sbin.icinga2_installer.exe&gt;2</Custom>
+      <Custom Action="XtraInstall" Before="InstallFinalize">$CM_CP_sbin.icinga2_installer.exe&gt;2</Custom>
+      <Custom Action="XtraUninstall" Before="RemoveExistingProducts">$CM_CP_sbin.icinga2_installer.exe=2</Custom>
     </InstallExecuteSequence>
 
     <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Run Icinga 2 setup wizard" />
diff --git a/lib/cli/apisetupcommand.cpp b/lib/cli/apisetupcommand.cpp
index f13b985a1..bc832c525 100644
--- a/lib/cli/apisetupcommand.cpp
+++ b/lib/cli/apisetupcommand.cpp
@@ -49,14 +49,6 @@ int ApiSetupCommand::GetMaxArguments() const
 	return -1;
 }
 
-void ApiSetupCommand::InitParameters(boost::program_options::options_description& visibleDesc,
-	boost::program_options::options_description& hiddenDesc) const
-{
-	visibleDesc.add_options()
-		("quiet,q", "be less verbose")
-	;
-}
-
 /**
  * The entry point for the "api setup" CLI command.
  *
@@ -64,15 +56,12 @@ void ApiSetupCommand::InitParameters(boost::program_options::options_description
  */
 int ApiSetupCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const
 {
-	if (vm.count("quiet"))
-		Logger::SetConsoleLogSeverity(LogWarning);
-
 	String cn = VariableUtility::GetVariable("NodeName");
 
 	if (cn.IsEmpty())
 		cn = Utility::GetFQDN();
 
-	if (!ApiSetupUtility::SetupMaster(cn, true, vm.count("quiet")))
+	if (!ApiSetupUtility::SetupMaster(cn, true))
 		return 1;
 
 	return 0;
diff --git a/lib/cli/apisetupcommand.hpp b/lib/cli/apisetupcommand.hpp
index fcdb56428..f54da0685 100644
--- a/lib/cli/apisetupcommand.hpp
+++ b/lib/cli/apisetupcommand.hpp
@@ -38,8 +38,6 @@ public:
 	String GetDescription() const override;
 	String GetShortDescription() const override;
 	int GetMaxArguments() const override;
-	void InitParameters(boost::program_options::options_description& visibleDesc,
-		boost::program_options::options_description& hiddenDesc) const override;
 	int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const override;
 	ImpersonationLevel GetImpersonationLevel() const override;
 };
diff --git a/lib/cli/apisetuputility.cpp b/lib/cli/apisetuputility.cpp
index 3c7336c16..1b60a2c1a 100644
--- a/lib/cli/apisetuputility.cpp
+++ b/lib/cli/apisetuputility.cpp
@@ -48,7 +48,7 @@ String ApiSetupUtility::GetApiUsersConfPath()
 	return ApiSetupUtility::GetConfdPath() + "/api-users.conf";
 }
 
-bool ApiSetupUtility::SetupMaster(const String& cn, bool prompt_restart, bool quiet)
+bool ApiSetupUtility::SetupMaster(const String& cn, bool prompt_restart)
 {
 	if (!SetupMasterCertificates(cn))
 		return false;
@@ -56,13 +56,13 @@ bool ApiSetupUtility::SetupMaster(const String& cn, bool prompt_restart, bool qu
 	if (!SetupMasterApiUser())
 		return false;
 
-	if (!SetupMasterEnableApi(quiet))
+	if (!SetupMasterEnableApi())
 		return false;
 
 	if (!SetupMasterUpdateConstants(cn))
 		return false;
 
-	if (prompt_restart && !quiet) {
+	if (prompt_restart) {
 		std::cout << "Done.\n\n";
 		std::cout << "Now restart your Icinga 2 daemon to finish the installation!\n\n";
 	}
@@ -196,11 +196,11 @@ bool ApiSetupUtility::SetupMasterApiUser()
 	return true;
 }
 
-bool ApiSetupUtility::SetupMasterEnableApi(bool quiet)
+bool ApiSetupUtility::SetupMasterEnableApi()
 {
 	Log(LogInformation, "cli", "Enabling the 'api' feature.");
 
-	FeatureUtility::EnableFeatures({ "api" }, quiet);
+	FeatureUtility::EnableFeatures({ "api" });
 
 	return true;
 }
diff --git a/lib/cli/apisetuputility.hpp b/lib/cli/apisetuputility.hpp
index 26b163d90..9523ebffc 100644
--- a/lib/cli/apisetuputility.hpp
+++ b/lib/cli/apisetuputility.hpp
@@ -37,11 +37,11 @@ namespace icinga
 class ApiSetupUtility
 {
 public:
-	static bool SetupMaster(const String& cn, bool prompt_restart = false, bool quiet = false);
+	static bool SetupMaster(const String& cn, bool prompt_restart = false);
 
 	static bool SetupMasterCertificates(const String& cn);
 	static bool SetupMasterApiUser();
-	static bool SetupMasterEnableApi(bool quiet = false);
+	static bool SetupMasterEnableApi();
 	static bool SetupMasterUpdateConstants(const String& cn);
 
 	static String GetConfdPath();
diff --git a/lib/cli/featureutility.cpp b/lib/cli/featureutility.cpp
index e06690f0d..9056b60fe 100644
--- a/lib/cli/featureutility.cpp
+++ b/lib/cli/featureutility.cpp
@@ -56,7 +56,7 @@ std::vector<String> FeatureUtility::GetFieldCompletionSuggestions(const String&
 	return suggestions;
 }
 
-int FeatureUtility::EnableFeatures(const std::vector<std::string>& features, bool quiet)
+int FeatureUtility::EnableFeatures(const std::vector<std::string>& features)
 {
 	String features_available_dir = GetFeaturesAvailablePath();
 	String features_enabled_dir = GetFeaturesEnabledPath();
@@ -93,9 +93,8 @@ int FeatureUtility::EnableFeatures(const std::vector<std::string>& features, boo
 			continue;
 		}
 
-		if (!quiet)
-			std::cout << "Enabling feature " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << feature
-				<< ConsoleColorTag(Console_Normal) << ". Make sure to restart Icinga 2 for these changes to take effect.\n";
+		std::cout << "Enabling feature " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << feature
+			<< ConsoleColorTag(Console_Normal) << ". Make sure to restart Icinga 2 for these changes to take effect.\n";
 
 #ifndef _WIN32
 		String relativeSource = "../features-available/" + feature + ".conf";
@@ -132,7 +131,7 @@ int FeatureUtility::EnableFeatures(const std::vector<std::string>& features, boo
 	return 0;
 }
 
-int FeatureUtility::DisableFeatures(const std::vector<std::string>& features, bool quiet)
+int FeatureUtility::DisableFeatures(const std::vector<std::string>& features)
 {
 	String features_enabled_dir = GetFeaturesEnabledPath();
 
@@ -161,9 +160,8 @@ int FeatureUtility::DisableFeatures(const std::vector<std::string>& features, bo
 			continue;
 		}
 
-		if (!quiet)
-			std::cout << "Disabling feature " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << feature
-				<< ConsoleColorTag(Console_Normal) << ". Make sure to restart Icinga 2 for these changes to take effect.\n";
+		std::cout << "Disabling feature " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << feature
+			<< ConsoleColorTag(Console_Normal) << ". Make sure to restart Icinga 2 for these changes to take effect.\n";
 	}
 
 	if (!errors.empty()) {
diff --git a/lib/cli/featureutility.hpp b/lib/cli/featureutility.hpp
index 23115ccca..38f91cce0 100644
--- a/lib/cli/featureutility.hpp
+++ b/lib/cli/featureutility.hpp
@@ -40,8 +40,8 @@ public:
 
 	static std::vector<String> GetFieldCompletionSuggestions(const String& word, bool enable);
 
-	static int EnableFeatures(const std::vector<std::string>& features, bool quiet = false);
-	static int DisableFeatures(const std::vector<std::string>& features, bool quiet = false);
+	static int EnableFeatures(const std::vector<std::string>& features);
+	static int DisableFeatures(const std::vector<std::string>& features);
 	static int ListFeatures(std::ostream& os = std::cout);
 
 	static bool GetFeatures(std::vector<String>& features, bool enable);
diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp
index d1190a703..c1546710d 100644
--- a/lib/remote/apilistener.cpp
+++ b/lib/remote/apilistener.cpp
@@ -224,23 +224,11 @@ void ApiListener::Start(bool runtimeCreated)
 		OpenLogFile();
 	}
 
-	Dictionary::Ptr envData = ScriptGlobal::Get("EnvironmentInfo", &Empty);
-	if (envData) {
-		ScriptGlobal::Set("EnvironmentInfo", Empty);
-		TcpSocket::Ptr listener = envData->Get("listener");
-		if (!AddListener(listener)) {
-			Log(LogCritical, "ApiListener")
-			    << "Failed to set up pre-configured agent listener.";
-			Application::Exit(EXIT_FAILURE);
-		}
-		Utility::SaveJsonFile(envData->Get("meta_path"), 0600, envData->Get("config"));
-	} else {
-		/* create the primary JSON-RPC listener */
-		if (!AddListener(GetBindHost(), GetBindPort())) {
-			Log(LogCritical, "ApiListener")
-				<< "Cannot add listener on host '" << GetBindHost() << "' for port '" << GetBindPort() << "'.";
-			Application::Exit(EXIT_FAILURE);
-		}
+	/* create the primary JSON-RPC listener */
+	if (!AddListener(GetBindHost(), GetBindPort())) {
+		Log(LogCritical, "ApiListener")
+			<< "Cannot add listener on host '" << GetBindHost() << "' for port '" << GetBindPort() << "'.";
+		Application::Exit(EXIT_FAILURE);
 	}
 
 	m_Timer = new Timer();
@@ -313,33 +301,6 @@ bool ApiListener::IsMaster() const
 	return master == GetLocalEndpoint();
 }
 
-/**
- * Creates a new JSON-RPC listener using the specified TCP socket object.
- *
- * @param listener The TCP socket to use.
- */
-bool ApiListener::AddListener(const TcpSocket::Ptr& listener)
-{
-	ObjectLock olock(this);
-
-	std::shared_ptr<SSL_CTX> sslContext = m_SSLContext;
-
-	if (!sslContext) {
-		Log(LogCritical, "ApiListener", "SSL context is required for AddListener()");
-		return false;
-	}
-
-	Log(LogInformation, "ApiListener")
-		<< "Adding pre-configured listener on address " << listener->GetClientAddress();
-
-	std::thread thread(std::bind(&ApiListener::ListenerThreadProc, this, listener));
-	thread.detach();
-
-	m_Servers.insert(listener);
-
-	return true;
-}
-
 /**
  * Creates a new JSON-RPC listener on the specified port.
  *
diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp
index 41c4c3d23..b3894992a 100644
--- a/lib/remote/apilistener.hpp
+++ b/lib/remote/apilistener.hpp
@@ -138,7 +138,6 @@ private:
 	void CleanupCertificateRequestsTimerHandler();
 
 	bool AddListener(const String& node, const String& service);
-	bool AddListener(const TcpSocket::Ptr& listener);
 	void AddConnection(const Endpoint::Ptr& endpoint);
 
 	void NewClientHandler(const Socket::Ptr& client, const String& hostname, ConnectionRole role);