Fawkes API  Fawkes Development Version
mongodb_client_config.cpp
1 
2 /***************************************************************************
3  * mongodb_client_config.cpp - MongoDB client configuration
4  *
5  * Created: Wed Jul 12 13:45:03 2017
6  * Copyright 2006-2017 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Library General Public License for more details.
18  *
19  * Read the full text in the LICENSE.GPL file in the doc directory.
20  */
21 
22 #include "mongodb_client_config.h"
23 
24 #include <config/config.h>
25 #include <logging/logger.h>
26 
27 using namespace fawkes;
28 
29 /** @class MongoDBClientConfig "mongodb_client_config.h"
30  * MongoDB Client Configuration.
31  * Instances of this class represent a single MongoDB client configuration
32  * used to initiate connections.
33  *
34  * @author Tim Niemueller
35  */
36 
37 /** Constructor.
38  * This will read the given configuration.
39  * @param config configuration to query
40  * @param logger logger for info messages
41  * @param cfgname configuration name
42  * @param prefix configuration path prefix
43  */
45  Logger * logger,
46  std::string cfgname,
47  std::string prefix)
48 {
49  logcomp_ = "MongoDBClient|" + cfgname;
50 
51  enabled_ = false;
52  try {
53  enabled_ = config->get_bool((prefix + "enabled").c_str());
54  } catch (Exception &e) {
55  }
56 
57  std::string mode = "connection";
58  try {
59  mode = config->get_string((prefix + "mode").c_str());
60  } catch (Exception &e) {
61  logger->log_info(logcomp_.c_str(),
62  "MongoDB config '%s' specifies no client "
63  "mode, assuming 'connection'.",
64  cfgname.c_str());
65  }
66 
67  auth_string_ = "";
68  read_authinfo(config, logger, cfgname, prefix);
69 
70  if (mode == "replica_set" || mode == "replicaset") {
71  mode_ = REPLICA_SET;
72  replicaset_name_ = config->get_string((prefix + "name").c_str());
73 
74  std::vector<std::string> hosts = config->get_strings(prefix + "hosts");
75  std::string uri{"mongodb://"};
76  for (auto it = hosts.begin(); it != hosts.end(); it++) {
77  uri += *it;
78  if (std::next(it) != hosts.end()) {
79  uri += ",";
80  }
81  }
82  uri += "/" + auth_dbname;
83  uri += "?replicaSet=" + replicaset_name_;
84  try {
85  uri += "&readPreference=" + config->get_string((prefix + "read-preference").c_str());
86  } catch (Exception &e) {
87  // use default read preference
88  }
89  try {
90  uri += "&readPreferenceTags=" + config->get_string((prefix + "read-preference-tags").c_str());
91  } catch (Exception &e) {
92  }
93  conn_uri_ = mongocxx::uri{uri};
94 
95  } else if (mode == "sync_cluster" || mode == "synccluster") {
96  throw Exception("sync_cluster connections are no longer supported");
97 
98  } else {
99  mode_ = CONNECTION;
100  conn_uri_ = mongocxx::uri{"mongodb://" + auth_string_ + config->get_string(prefix + "hostport")
101  + "/" + auth_dbname};
102  }
103 }
104 
105 /** Read authentication info for given configuration.
106  * This will try to read the fields auth_dbname, auth_username, and
107  * auth_password.
108  * @param config configuration to query
109  * @param logger logger for info messages
110  * @param cfgname configuration name
111  * @param prefix configuration path prefix
112  */
113 void
114 MongoDBClientConfig::read_authinfo(Configuration *config,
115  Logger * logger,
116  std::string cfgname,
117  std::string prefix)
118 {
119  try {
120  auth_dbname = config->get_string((prefix + "auth_dbname").c_str());
121  std::string username = config->get_string((prefix + "auth_username").c_str());
122  std::string password = config->get_string((prefix + "auth_password").c_str());
123  if (!username.empty() && !password.empty()) {
124  auth_string_ = username + ":" + password + "@";
125  }
126  } catch (Exception &e) {
127  logger->log_info(logcomp_.c_str(),
128  "No default authentication info for "
129  "MongoDB client '%s'",
130  cfgname.c_str());
131  }
132 }
133 
134 /** Create MongoDB client for this configuration.
135  * @return MongoDB client
136  */
137 mongocxx::client *
139 {
140  return new mongocxx::client(conn_uri_);
141 }
142 
143 /** Write client configuration information to log.
144  * @param logger logger to write to
145  * @param component component to pass to logger
146  * @param indent indentation to put before each string
147  */
148 void
149 MongoDBClientConfig::log(Logger *logger, const char *component, const char *indent)
150 {
151  switch (mode_) {
152  case REPLICA_SET: {
153  logger->log_info(component, "%smode: replica set", indent);
154  } break;
155  default: {
156  logger->log_info(component, "%smode: connection", indent);
157  } break;
158  }
159  std::string uri_string = conn_uri_.to_string();
160  if (!auth_string_.empty()) {
161  if (uri_string.find(auth_string_) != std::string::npos) {
162  uri_string.replace(uri_string.find(auth_string_), auth_string_.length(), "****@****");
163  }
164  }
165  logger->log_info(component, "%suri: %s", indent, uri_string.c_str());
166 }
167 
168 /** Get host and port of configuration.
169  * @return string of the form "host:port"
170  */
171 std::string
173 {
174  auto hosts = conn_uri_.hosts();
175  if (hosts.empty()) {
176  return "";
177  } else {
178  // If multiple hosts are specified, only use the first host.
179  return hosts[0].name + ":" + std::to_string(hosts[0].port);
180  }
181 }
182 
183 /** Get client configuration mode.
184  * @return mode, connection or replica set
185  */
188 {
189  return mode_;
190 }
MongoDBClientConfig::hostport
std::string hostport() const
Get host and port of configuration.
Definition: mongodb_client_config.cpp:172
fawkes::Configuration::get_bool
virtual bool get_bool(const char *path)=0
MongoDBClientConfig::MongoDBClientConfig
MongoDBClientConfig(fawkes::Configuration *config, fawkes::Logger *logger, std::string cfgname, std::string prefix)
Constructor.
Definition: mongodb_client_config.cpp:44
MongoDBClientConfig::create_client
mongocxx::client * create_client()
Create MongoDB client for this configuration.
Definition: mongodb_client_config.cpp:138
MongoDBClientConfig::mode
ConnectionMode mode() const
Get client configuration mode.
Definition: mongodb_client_config.cpp:187
fawkes::Configuration
Definition: config.h:68
MongoDBClientConfig::log
void log(fawkes::Logger *logger, const char *component, const char *indent)
Write client configuration information to log.
Definition: mongodb_client_config.cpp:149
fawkes::Logger
Definition: logger.h:40
fawkes
fawkes::Configuration::get_strings
virtual std::vector< std::string > get_strings(const char *path)=0
fawkes::Configuration::get_string
virtual std::string get_string(const char *path)=0
MongoDBClientConfig::ConnectionMode
ConnectionMode
Connection mode enumeration.
Definition: mongodb_client_config.h:39
fawkes::MultiLogger::log_info
virtual void log_info(const char *component, const char *format,...)
Definition: multi.cpp:199
fawkes::Exception
Definition: exception.h:39