Skip to content

Commit

Permalink
CLI: Add feature enable/disable auto-completion
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Michael Friedrich authored and TheFlyingCorpse committed Oct 19, 2014
1 parent 7dcfee5 commit 2647be2
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 55 deletions.
2 changes: 1 addition & 1 deletion lib/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions lib/cli/featuredisablecommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
******************************************************************************/

#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>
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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()) {
Expand Down
3 changes: 1 addition & 2 deletions lib/cli/featuredisablecommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ class FeatureDisableCommand : public CLICommand

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;

};
Expand Down
15 changes: 7 additions & 8 deletions lib/cli/featureenablecommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@
******************************************************************************/

#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;
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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 +
Expand All @@ -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()) {
Expand Down
4 changes: 1 addition & 3 deletions lib/cli/featureenablecommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,8 @@ class FeatureEnableCommand : public CLICommand

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;

};

}
Expand Down
52 changes: 19 additions & 33 deletions lib/cli/featurelistcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@
******************************************************************************/

#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;
Expand Down Expand Up @@ -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);
}
}
4 changes: 0 additions & 4 deletions lib/cli/featurelistcommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ class FeatureListCommand : public CLICommand
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);

};

}
Expand Down
99 changes: 99 additions & 0 deletions lib/cli/featureutility.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
59 changes: 59 additions & 0 deletions lib/cli/featureutility.hpp
Original file line number Diff line number Diff line change
@@ -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 */

0 comments on commit 2647be2

Please sign in to comment.