]> granicus.if.org Git - icinga2/commitdiff
CLI: Add feature enable/disable auto-completion
authorMichael Friedrich <michael.friedrich@netways.de>
Sat, 18 Oct 2014 17:31:52 +0000 (19:31 +0200)
committerMichael Friedrich <michael.friedrich@netways.de>
Sat, 18 Oct 2014 18:13:09 +0000 (20:13 +0200)
Refactor feature list code.
Add disabled features to list output.
Add more console colors.
Change output to stdout for general logging.

fixes #7381
fixes #7415
refs #7376

lib/cli/CMakeLists.txt
lib/cli/featuredisablecommand.cpp
lib/cli/featuredisablecommand.hpp
lib/cli/featureenablecommand.cpp
lib/cli/featureenablecommand.hpp
lib/cli/featurelistcommand.cpp
lib/cli/featurelistcommand.hpp
lib/cli/featureutility.cpp [new file with mode: 0644]
lib/cli/featureutility.hpp [new file with mode: 0644]

index aed5ce951c7e4566c55d33fa3f04cf679d27a157..49f270e0c3b854bf87724634bb2cea0e8e14f355 100644 (file)
@@ -18,7 +18,7 @@
 set(cli_SOURCES
   agentaddcommand.cpp agentblackandwhitelistcommand.cpp agentlistcommand.cpp agentremovecommand.cpp
   agentsetcommand.cpp agentsetupcommand.cpp agentupdateconfigcommand.cpp agentwizardcommand.cpp agentutility.cpp
-  featureenablecommand.cpp featuredisablecommand.cpp featurelistcommand.cpp
+  featureenablecommand.cpp featuredisablecommand.cpp featurelistcommand.cpp featureutility.cpp
   objectlistcommand.cpp
   pkinewcacommand.cpp pkinewcertcommand.cpp pkisigncsrcommand.cpp pkirequestcommand.cpp pkiticketcommand.cpp
   repositoryobjectcommand.cpp
index 17b06662bd8d82c5fb0b3cca821bc68f1724dd8e..0faa98687f664dd88a3f09878346df3069e4d9a7 100644 (file)
  ******************************************************************************/
 
 #include "cli/featuredisablecommand.hpp"
+#include "cli/featureutility.hpp"
 #include "base/logger_fwd.hpp"
 #include "base/clicommand.hpp"
 #include "base/application.hpp"
 #include "base/convert.hpp"
+#include "base/console.hpp"
 #include <boost/foreach.hpp>
 #include <boost/algorithm/string/join.hpp>
 #include <fstream>
@@ -42,10 +44,9 @@ String FeatureDisableCommand::GetShortDescription(void) const
        return "disables specified feature";
 }
 
-void FeatureDisableCommand::InitParameters(boost::program_options::options_description& visibleDesc,
-    boost::program_options::options_description& hiddenDesc) const
+std::vector<String> FeatureDisableCommand::GetPositionalSuggestions(const String& word) const
 {
-       /* Command doesn't support any parameters. */
+       return FeatureUtility::GetFieldCompletionSuggestions(FeatureCommandDisable, word);
 }
 
 /**
@@ -89,7 +90,8 @@ int FeatureDisableCommand::Run(const boost::program_options::variables_map& vm,
                        continue;
                }
 
-               Log(LogInformation, "cli", "Disabling feature " + feature + " in '" + features_enabled_dir + "'.");
+               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()) {
index fcb6f783989402259ab6e3c90a9e39722db91706..5558442aabedc31cd4cb3c209f1db98ec5676b89 100644 (file)
@@ -38,8 +38,7 @@ public:
 
        virtual String GetDescription(void) const;
        virtual String GetShortDescription(void) const;
-       virtual void InitParameters(boost::program_options::options_description& visibleDesc,
-           boost::program_options::options_description& hiddenDesc) const;
+        virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
        virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
 
 };
index 642924bacb9454fa1698eb3e61877d29006eaf25..23dbe862b8d986c3cb0df5ac610d5edb38d6334a 100644 (file)
  ******************************************************************************/
 
 #include "cli/featureenablecommand.hpp"
+#include "cli/featureutility.hpp"
 #include "base/logger_fwd.hpp"
 #include "base/clicommand.hpp"
 #include "base/application.hpp"
 #include "base/convert.hpp"
+#include "base/console.hpp"
 #include <boost/foreach.hpp>
 #include <boost/algorithm/string/join.hpp>
 #include <fstream>
-#include <vector>
-#include <string>
-#include <fstream>
 
 using namespace icinga;
 namespace po = boost::program_options;
@@ -44,10 +43,9 @@ String FeatureEnableCommand::GetShortDescription(void) const
        return "enables specified feature";
 }
 
-void FeatureEnableCommand::InitParameters(boost::program_options::options_description& visibleDesc,
-    boost::program_options::options_description& hiddenDesc) const
+std::vector<String> FeatureEnableCommand::GetPositionalSuggestions(const String& word) const
 {
-       /* Command doesn't support any parameters. */
+       return FeatureUtility::GetFieldCompletionSuggestions(FeatureCommandEnable, word);
 }
 
 /**
@@ -93,8 +91,6 @@ int FeatureEnableCommand::Run(const boost::program_options::variables_map& vm, c
                        continue;
                }
 
-               Log(LogInformation, "cli", "Enabling feature '" + feature + "' in '" + features_enabled_dir + "'.");
-
 #ifndef _WIN32
                if (symlink(source.CStr(), target.CStr()) < 0) {
                        Log(LogCritical, "cli", "Cannot enable feature '" + feature + "'. Linking source '" + source + "' to target file '" + target +
@@ -113,6 +109,9 @@ int FeatureEnableCommand::Run(const boost::program_options::variables_map& vm, c
                fp << "include \"../features-available/" << feature << ".conf\"" << std::endl;
                fp.close();
 #endif /* _WIN32 */
+
+               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";
        }
 
        if (!errors.empty()) {
index e675fe4657ef949ea8a7f253142bc31c80591a9f..bf5d6bab26b08ec55163d9b8f37de7d495e4b96b 100644 (file)
@@ -38,10 +38,8 @@ public:
 
        virtual String GetDescription(void) const;
        virtual String GetShortDescription(void) const;
-       virtual void InitParameters(boost::program_options::options_description& visibleDesc,
-           boost::program_options::options_description& hiddenDesc) const;
+        virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
        virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
-
 };
 
 }
index 8dd47b86fd38ac71fae7094179953ee6700bd5ce..c5e09040d3420a6a731b65255620fe2bf166577e 100644 (file)
  ******************************************************************************/
 
 #include "cli/featurelistcommand.hpp"
+#include "cli/featureutility.hpp"
 #include "base/logger_fwd.hpp"
 #include "base/clicommand.hpp"
-#include "base/application.hpp"
+#include "base/convert.hpp"
+#include "base/console.hpp"
 #include <boost/foreach.hpp>
 #include <boost/algorithm/string/join.hpp>
-#include <boost/algorithm/string/replace.hpp>
-#include <fstream>
-#include <vector>
-#include <string>
+#include <iostream>
 
 using namespace icinga;
 namespace po = boost::program_options;
@@ -54,36 +53,23 @@ int FeatureListCommand::Run(const boost::program_options::variables_map& vm, con
                Log(LogWarning, "cli", "Ignoring parameters: " + boost::algorithm::join(ap, " "));
        }
 
-#ifdef _WIN32
-       //TODO: Add Windows support
-       Log(LogInformation, "cli", "This command is not available on Windows.");
-#else
-       std::vector<String> enabled_features;
        std::vector<String> available_features;
+       std::vector<String> disabled_features;
+       std::vector<String> enabled_features;
 
-       if (!Utility::Glob(Application::GetSysconfDir() + "/icinga2/features-enabled/*.conf",
-           boost::bind(&FeatureListCommand::CollectFeatures, _1, boost::ref(enabled_features)), GlobFile)) {
-               Log(LogCritical, "cli", "Cannot access path '" + Application::GetSysconfDir() + "/icinga2/features-enabled/'.");
-       }
-
-       if (!Utility::Glob(Application::GetSysconfDir() + "/icinga2/features-available/*.conf",
-           boost::bind(&FeatureListCommand::CollectFeatures, _1, boost::ref(available_features)), GlobFile)) {
-               Log(LogCritical, "cli", "Cannot access path '" + Application::GetSysconfDir() + "/icinga2/available-available/'.");
-       }
+       if (!FeatureUtility::GetFeatures(FeaturesAvailable, available_features))
+               return 1;
+       if (!FeatureUtility::GetFeatures(FeaturesDisabled, disabled_features))
+               return 1;
+       if (!FeatureUtility::GetFeatures(FeaturesEnabled, enabled_features))
+               return 1;
 
-       Log(LogInformation, "cli", "Available features: " + boost::algorithm::join(available_features, " "));
-       Log(LogInformation, "cli", "---");
-       Log(LogInformation, "cli", "Enabled features: " + boost::algorithm::join(enabled_features, " "));
-#endif /* _WIN32 */
+       std::cout << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << "Available features: " << ConsoleColorTag(Console_Normal)
+           << boost::algorithm::join(available_features, " ") << "\n";
+       std::cout << ConsoleColorTag(Console_ForegroundRed | Console_Bold) << "Disabled features: " << ConsoleColorTag(Console_Normal)
+           << boost::algorithm::join(disabled_features, " ") << "\n";
+       std::cout << ConsoleColorTag(Console_ForegroundGreen | Console_Bold) << "Enabled features: " << ConsoleColorTag(Console_Normal)
+           << boost::algorithm::join(enabled_features, " ") << "\n";
 
        return 0;
-}
-
-void FeatureListCommand::CollectFeatures(const String& feature_file, std::vector<String>& features)
-{
-       String feature = Utility::BaseName(feature_file);
-       boost::algorithm::replace_all(feature, ".conf", "");
-
-       Log(LogDebug, "cli", "Adding feature: " + feature);
-       features.push_back(feature);
-}
+}
\ No newline at end of file
index 399bf3c69f3e1e4e563fcf52f027b641f6433886..1dcb18b0957f9b0ecfbd3084524439022f479a66 100644 (file)
@@ -39,10 +39,6 @@ public:
        virtual String GetDescription(void) const;
        virtual String GetShortDescription(void) const;
        virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
-
-private:
-       static void CollectFeatures(const String& feature_file, std::vector<String>& features);
-
 };
 
 }
diff --git a/lib/cli/featureutility.cpp b/lib/cli/featureutility.cpp
new file mode 100644 (file)
index 0000000..91ab66d
--- /dev/null
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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/featureutility.hpp"
+#include "base/logger_fwd.hpp"
+#include "base/clicommand.hpp"
+#include "base/application.hpp"
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+using namespace icinga;
+
+std::vector<String> FeatureUtility::GetFieldCompletionSuggestions(FeatureCommandType fctype, const String& word)
+{
+       std::vector<String> cache;
+       std::vector<String> suggestions;
+
+       if (fctype == FeatureCommandEnable) {
+               /* only suggest features not already enabled */
+               GetFeatures(FeaturesDisabled, cache);
+       } else if (fctype == FeatureCommandDisable) {
+               /* suggest all enabled features */
+               GetFeatures(FeaturesEnabled, cache);
+       }
+
+       std::sort(cache.begin(), cache.end());
+
+       BOOST_FOREACH(const String& suggestion, cache) {
+               if (suggestion.Find(word) == 0)
+                       suggestions.push_back(suggestion);
+       }
+
+       return suggestions;
+}
+
+bool FeatureUtility::GetFeatures(FeatureType ftype, std::vector<String>& features)
+{
+       String path = Application::GetSysconfDir() + "/icinga2/";
+
+       /* disabled = available-enabled */
+       if (ftype == FeaturesDisabled) {
+               std::vector<String> enabled;
+               std::vector<String> available;
+               GetFeatures(FeaturesAvailable, available);
+               GetFeatures(FeaturesEnabled, enabled);
+
+               std::sort(available.begin(), available.end());
+               std::sort(enabled.begin(), enabled.end());
+               std::set_difference(
+                       available.begin(), available.end(),
+                       enabled.begin(), enabled.end(),
+                       std::back_inserter(features)
+               );
+
+               return true;
+       } else {
+               if (ftype == FeaturesAvailable)
+                       path += "features-available/";
+               else if (ftype == FeaturesEnabled)
+                       path += "features-enabled/";
+               else {
+                       Log(LogCritical, "cli", "Unknown feature type passed. Bailing out.");
+                       return false;
+               }
+
+               if (!Utility::Glob(path + "/*.conf",
+                   boost::bind(&FeatureUtility::CollectFeatures, _1, boost::ref(features)), GlobFile)) {
+                       Log(LogCritical, "cli", "Cannot access path '" + path + "'.");
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+void FeatureUtility::CollectFeatures(const String& feature_file, std::vector<String>& features)
+{
+       String feature = Utility::BaseName(feature_file);
+       boost::algorithm::replace_all(feature, ".conf", "");
+
+       Log(LogDebug, "cli", "Adding feature: " + feature);
+       features.push_back(feature);
+}
diff --git a/lib/cli/featureutility.hpp b/lib/cli/featureutility.hpp
new file mode 100644 (file)
index 0000000..4af3602
--- /dev/null
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 FEATUREUTILITY_H
+#define FEATUREUTILITY_H
+
+#include "base/i2-base.hpp"
+#include "base/qstring.hpp"
+#include <vector>
+
+namespace icinga
+{
+
+enum FeatureType
+{
+       FeaturesAvailable,
+       FeaturesEnabled,
+       FeaturesDisabled
+};
+
+enum FeatureCommandType
+{
+       FeatureCommandEnable,
+       FeatureCommandDisable
+};
+
+/**
+ * @ingroup cli
+ */
+class FeatureUtility
+{
+public:
+       static std::vector<String> GetFieldCompletionSuggestions(FeatureCommandType fctype, const String& word);
+       static bool GetFeatures(FeatureType ftype, std::vector<String>& features);
+
+private:
+       FeatureUtility(void);
+       static void CollectFeatures(const String& feature_file, std::vector<String>& features);
+};
+
+}
+
+#endif /* FEATUREUTILITY_H */