void SessionHelper::set(const std::vector<std::string> &patternList, const std::string &arg, bool hidden, bool json, bool cont) { forEachService(patternList, boost::bind(&ServiceHelper::setProperty, _1, _2, decodeArg(arg, json)), &ServiceHelper::getMatchingPropertiesName, hidden, cont); }
int main(int argc, char* argv[]) { el::Configurations defaultConf; defaultConf.setToDefault(); defaultConf.setGlobally(el::ConfigurationType::ToFile, std::string("false")); defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, std::string("true")); el::Loggers::reconfigureLogger("default", defaultConf); if (::isatty(::fileno(stdout))) el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); ::consul::Agent agent; ::consul::KVPair::ValueT value; TCLAP::ValueArg<::consul::KVPair::IndexT> casArg("C", "cas", "Check-and-Set index. When performing a PUT or DELETE, only operate if the ModifyIndex matches the passed in CAS value", false, std::numeric_limits<::consul::KVPair::IndexT>::max(), "modify-index"); TCLAP::ValueArg<::consul::KVPair::SessionT> sessionArg("S", "session", "Acquire a lock using the specified Session", false, "", "session"); TCLAP::ValueArg<::consul::KVPair::FlagsT> flagsArg("F", "flags", "Opaque numeric value attached to a key (0 through (2^64)-1)", false, std::numeric_limits<::consul::KVPair::FlagsT>::max() - 1, "flag"); enum class MethodType : char { GET, PUT, DELETE }; MethodType methodType; bool debugFlag = false; bool recursiveFlag = false; std::vector<::consul::KVPair::KeyT> keys; try { TCLAP::CmdLine cmd(COMMAND_HELP_MSG, '=', "0.1"); // Args are displayed LIFO std::vector<TCLAP::Arg*> cmdMajorModes; TCLAP::MultiArg<::consul::KVPair::KeyT> keyArg("k", "key", "Key(s) operate on with the consul agent", true, "string"); cmdMajorModes.push_back(&keyArg); TCLAP::ValueArg<std::string> decodeArg("D", "decode", "Decode a base64 encoded string", false, "dGVzdA==", "base64-encoded-string"); cmdMajorModes.push_back(&decodeArg); TCLAP::ValueArg<std::string> encodeArg("E", "encode", "Encode a stream of bytes using base64", false, "test", "stream of bytes"); cmdMajorModes.push_back(&encodeArg); cmd.xorAdd(cmdMajorModes); TCLAP::SwitchArg debugArg("d", "debug", "Print additional information with debugging", false); cmd.add(debugArg); TCLAP::ValueArg<consul::Agent::PortT> portArg("p", "port", "Port number of consul agent", false, agent.port(), "port"); cmd.add(portArg); TCLAP::ValueArg<consul::Agent::HostT> hostArg("H", "host", "Hostname of consul agent", false, agent.host().c_str(), "hostname"); cmd.add(hostArg); std::vector<std::string> methods{{"GET","PUT","DELETE"}}; TCLAP::ValuesConstraint<std::string> methodConstraint(methods); TCLAP::ValueArg<std::string> methodArg("m", "method", "HTTP method used to act on the key", false, "get", &methodConstraint); cmd.add(methodArg); TCLAP::ValueArg<std::string> valueArg("v", "value", "Value to be used when PUT'ing a key (will be base64 encoded automatically).", false, "", "value"); cmd.add(valueArg); TCLAP::SwitchArg recursiveArg("r", "recursive", "Pass the '?recurse' query parameter to recursively find all keys"); cmd.add(recursiveArg); // NOTE: the following *Args were defined above try{} block cmd.add(casArg); cmd.add(flagsArg); cmd.add(sessionArg); TCLAP::ValueArg<std::string> clusterArg("c", "cluster", "consul Cluster (i.e. '?dc=<cluster>')", false, "", "dc1"); cmd.add(clusterArg); cmd.parse(argc, argv); if (debugArg.isSet()) { debugFlag = debugArg.getValue(); } if (hostArg.isSet()) { agent.setHost(hostArg.getValue()); } if (portArg.isSet()) { agent.setPort(portArg.getValue()); } if (decodeArg.isSet()) { base64::decoder D; const std::string testInput{decodeArg.getValue()}; std::istringstream iss{testInput}; std::ostringstream oss; D.decode(iss, oss); std::cout << "Result: \"" << oss.str() << "\"" << std::endl; return EX_OK; } if (encodeArg.isSet()) { base64::encoder E; const std::string testInput{encodeArg.getValue()}; std::istringstream iss{testInput}; std::ostringstream oss; E.encode(iss, oss); std::cout << "-----BEGIN BASE64 ENCODED STREAM-----" << std::endl << oss.str() << "-----END BASE64 ENCODED STREAM-----" << std::endl ; return EX_OK; } keys = keyArg.getValue(); if (clusterArg.isSet()) { agent.setCluster(clusterArg.getValue()); } if (recursiveArg.isSet()) { recursiveFlag = recursiveArg.getValue(); } if (methodArg.isSet()) { const auto& v = methodArg.getValue(); if (v == "GET") { methodType = MethodType::GET; } else if (v == "PUT") { if (!valueArg.isSet()) { LOG(ERROR) << "Unable to use PUT method without specifying a value argument (--value=)"; return EX_USAGE; } if (keys.size() > 1) { LOG(ERROR) << "Unable to pass multiple key arguments when PUT'ing a value"; return EX_USAGE; } methodType = MethodType::PUT; } else if (v == "DELETE") { methodType = MethodType::DELETE; } else { LOG(FATAL) << "Unknown type: " << v; return EX_SOFTWARE; } } if (valueArg.isSet()) { value = valueArg.getValue(); } } catch (TCLAP::ArgException &e) { LOG(FATAL) << e.error() << " for arg " << e.argId(); return EX_USAGE; } try { for (auto& key : keys) { auto kvUrl = agent.kvUrl(key); LOG_IF(debugFlag, INFO) << "Key URL: " << kvUrl; auto params = cpr::Parameters(); if (!agent.cluster().empty()) { LOG_IF(debugFlag, INFO) << "Passing ?dc=" << agent.cluster() << " flag"; params.AddParameter({"dc", agent.cluster()}); } else { LOG_IF(debugFlag, INFO) << "No consul ?dc= specified"; } if (recursiveFlag && (methodType == MethodType::GET || methodType == MethodType::DELETE)) { LOG_IF(debugFlag, INFO) << "Passing ?recurse flag"; params.AddParameter({"recurse", ""}); } else { LOG_IF(debugFlag, INFO) << "Not passing the ?recurse flag"; } if (casArg.isSet() && (methodType == MethodType::PUT || methodType == MethodType::DELETE)) { auto casStr = ::boost::lexical_cast<std::string>(casArg.getValue()); LOG_IF(debugFlag, INFO) << "Passing ?cas=" << casStr << " parameter"; params.AddParameter({"cas", casStr}); } if (sessionArg.isSet() && methodType == MethodType::PUT) { LOG_IF(debugFlag, INFO) << "Passing ?acquire=" << sessionArg.getValue() << " parameter"; params.AddParameter({"acquire", sessionArg.getValue()}); } if (flagsArg.isSet() && methodType == MethodType::PUT) { auto flagsStr = ::boost::lexical_cast<std::string>(flagsArg.getValue()); LOG_IF(debugFlag, INFO) << "Passing ?flags=" << flagsStr << " parameter"; params.AddParameter({"flags", flagsStr}); } if (methodType == MethodType::GET) { auto r = cpr::Get(cpr::Url{kvUrl}, cpr::Header{{"Connection", "close"}}, cpr::Timeout{agent.timeoutMs()}, params); if (r.status_code != 200) { LOG(ERROR) << "consul agent returned error " << r.status_code; return EX_TEMPFAIL; } DLOG_IF(debugFlag, INFO) << "URL: " << r.url; consul::KVPairs kvps; std::string err; if (!::consul::KVPairs::InitFromJson(kvps, r.text, err)) { LOG(ERROR) << "Failed to load KVPair(s) from JSON: " << err; return EX_PROTOCOL; } if (recursiveFlag) { LOG_IF(debugFlag, INFO) << "Found " << kvps.size() << " objects when searching for " << kvUrl; } else { if (kvps.size() > 1) { LOG(ERROR) << "Non-recursive GET for " << r.url << " returned " << kvps.size() << " objects"; return EX_PROTOCOL; } } std::size_t i = 0; for (auto& kvp : kvps.objs()) { if (recursiveFlag) { std::cout << "========== BEGIN KEY " << ++i << "/" << kvps.size() << " ==========" << std::endl; } std::cout << "Key: " << kvp.key() << std::endl; std::cout << "Value: " << kvp.value() << std::endl; if (!kvp.session().empty()) { std::cout << "Session: " << kvp.session() << std::endl; } DLOG_IF(debugFlag, INFO) << "Value (base64-encoded): " << kvp.valueEncoded(); LOG_IF(debugFlag, INFO) << "CreateIndex: " << kvp.createIndex(); LOG_IF(debugFlag, INFO) << "ModifyIndex: " << kvp.modifyIndex(); LOG_IF(debugFlag, INFO) << "LockIndex: " << kvp.lockIndex(); LOG_IF(debugFlag, INFO) << "Flags: " << kvp.flags(); LOG_IF(debugFlag, INFO) << "Session: " << (!kvp.session().empty() ? kvp.session() : "[none]"); LOG_IF(debugFlag, INFO) << "JSON: " << kvp.json(); } } else if (methodType == MethodType::DELETE) { auto r = cpr::Delete(cpr::Url{kvUrl}, cpr::Header{{"Connection", "close"}}, cpr::Timeout{agent.timeoutMs()}, cpr::Payload{value}, params); if (r.status_code != 200) { LOG(ERROR) << "consul agent returned error " << r.status_code; return EX_TEMPFAIL; } DLOG_IF(debugFlag, INFO) << "URL: " << r.url; } else if (methodType == MethodType::PUT) { auto r = cpr::Put(cpr::Url{kvUrl}, cpr::Header{{"Connection", "close"}}, cpr::Timeout{agent.timeoutMs()}, cpr::Payload{value}, params); if (r.status_code != 200) { LOG(ERROR) << "consul agent returned error " << r.status_code; return EX_TEMPFAIL; } DLOG_IF(debugFlag, INFO) << "URL: " << r.url; if (r.text == "true") { LOG(INFO) << "Succeeded in posting key \"" << keys.at(0) << "\""; } else if (r.text == "false") { LOG(WARNING) << "Unable to PUT key \"" << keys.at(0) << "\""; return EX_CANTCREAT; } } else { DLOG(FATAL) << "Unsupported methodType"; } } return EX_OK; } catch (std::exception & e) { LOG(FATAL) << "cpr threw an exception: " << e.what(); return EX_SOFTWARE; } return EX_OK; }