Leosac  0.8.0
Open Source Access Control
ConfigManager.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2016 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "ConfigManager.hpp"
21 #include "core/kernel.hpp"
24 #include "tools/log.hpp"
25 #include <boost/archive/binary_iarchive.hpp>
26 #include <boost/archive/text_iarchive.hpp>
27 #include <boost/property_tree/ptree_serialization.hpp>
28 
29 using namespace Leosac;
30 
31 ConfigManager::ConfigManager(const boost::property_tree::ptree &cfg)
32  : kernel_config_(cfg)
33  , version_(0)
34 {
35  Tools::PropertyTreeExtractor extractor(cfg, "General Config");
36 
37  version_ = extractor.get<uint64_t>("version", 0);
38  instance_name_ = extractor.get<std::string>("instance_name");
39 }
40 
41 boost::property_tree::ptree ConfigManager::get_application_config()
42 {
43  boost::property_tree::ptree app_config;
44  boost::property_tree::ptree modules_config;
45 
46  app_config.add_child("kernel", get_general_config());
47 
48  std::string module_name;
49  boost::property_tree::ptree tree;
50  for (auto &it : modules_configs_)
51  {
52  std::tie(module_name, tree) = it;
53  modules_config.add_child("module", load_config(module_name));
54  }
55  app_config.get_child("kernel").add_child("modules", modules_config);
56  return app_config;
57 }
58 
59 boost::property_tree::ptree ConfigManager::get_general_config() const
60 {
61  boost::property_tree::ptree general_cfg;
62 
63  for (const std::string &cfg_name :
64  {"remote", "plugin_directories", "log", "network", "autosave", "sync_dest",
65  "no_import", "instance_name"})
66  {
67  auto child_opt = kernel_config_.get_child_optional(cfg_name);
68  if (child_opt)
69  general_cfg.add_child(cfg_name, *child_opt);
70  }
71  // Use the in-memory configuration version.
72  general_cfg.add("version", config_version());
73  return general_cfg;
74 }
75 
76 boost::property_tree::ptree ConfigManager::get_exportable_general_config() const
77 {
78  auto general_cfg = get_general_config();
79  auto child_opt = kernel_config_.get_child_optional("sync_source");
80  std::vector<std::string> exportable_config;
81  boost::property_tree::ptree ret;
82 
83  if (!child_opt)
84  {
85  // return all minus the `no_import` tag.
86  general_cfg.erase("no_import");
87  general_cfg.erase("instance_name");
88  return general_cfg;
89  }
90 
91  for (const auto &c : *child_opt)
92  {
93  ASSERT_LOG(c.first != "no_import" || c.first == "instance_name",
94  "Cannot export the " << c.first
95  << " tag. Check your"
96  " `sync_source` configuration tag.");
97  if (c.first == "no_import" || c.first == "instance_name")
98  {
99  WARN("You cannot export the " << c.first << " tag.");
100  continue;
101  }
102  if (c.second.get_value<bool>())
103  exportable_config.push_back(c.first);
104  }
105 
106  for (const auto &child : general_cfg)
107  {
108  if (std::find(exportable_config.begin(), exportable_config.end(),
109  child.first) != exportable_config.end())
110  {
111  ret.add_child(child.first, child.second);
112  }
113  }
114  return ret;
115 }
116 
117 bool ConfigManager::store_config(std::string const &module,
118  boost::property_tree::ptree const &cfg)
119 {
120  bool ret;
121 
122  if (modules_configs_.count(module))
123  ret = true;
124  else
125  ret = false;
126 
127  modules_configs_[module] = cfg;
128 
129  return ret;
130 }
131 
132 const boost::property_tree::ptree &
133 ConfigManager::load_config(const std::string &module) const
134 {
135  assert(modules_configs_.count(module));
136  auto itr = modules_configs_.find(module);
137  if (itr != modules_configs_.end())
138  return itr->second;
139  throw std::runtime_error("");
140 }
141 
142 zmqpp::message &operator>>(zmqpp::message &msg,
144 {
145  static_assert(
146  std::is_same<std::underlying_type<Leosac::ConfigManager::ConfigFormat>::type,
147  uint8_t>::value,
148  "Bad underlying type for enum");
149  uint8_t tmp;
150  msg >> tmp;
151  fmt = static_cast<Leosac::ConfigManager::ConfigFormat>(tmp);
152  return msg;
153 }
154 
155 zmqpp::message &operator<<(zmqpp::message &msg,
157 {
158  static_assert(
159  std::is_same<std::underlying_type<Leosac::ConfigManager::ConfigFormat>::type,
160  uint8_t>::value,
161  "Bad underlying type for enum");
162  msg << static_cast<uint8_t>(fmt);
163  return msg;
164 }
165 
166 const boost::property_tree::ptree &ConfigManager::kconfig() const
167 {
168  return kernel_config_;
169 }
170 
171 boost::property_tree::ptree &ConfigManager::kconfig()
172 {
173  return kernel_config_;
174 }
175 
176 bool ConfigManager::remove_config(const std::string &module)
177 {
178  if (modules_configs_.find(module) != modules_configs_.end())
179  {
180  modules_configs_.erase(module);
181  return true;
182  }
183  return false;
184 }
185 
186 void ConfigManager::set_kconfig(boost::property_tree::ptree const &new_cfg)
187 {
188  INFO("Attempting to set kernel config. We need to somehow merge.");
189  auto kernel_cfg_file = kernel_config_.get<std::string>("kernel-cfg");
190 
191  auto child_opt = kernel_config_.get_child_optional("sync_dest");
192  std::vector<std::string> exportable_config;
193  boost::property_tree::ptree ret;
194 
195  if (!child_opt)
196  {
197  auto no_import_child = kernel_config_.get_child_optional("no_import");
198  boost::property_tree::ptree cpy;
199  if (no_import_child)
200  {
201  cpy = *no_import_child;
202  }
203  // import all (except no_import tag)
204  kernel_config_ = new_cfg;
205  // restore
206  if (no_import_child)
207  kernel_config_.put_child("no_import", cpy);
208  kernel_config_.add("kernel-cfg", kernel_cfg_file);
209  kernel_config_.put("instance_name", instance_name());
210  }
211  else
212  {
213  for (const auto &c : *child_opt)
214  {
215  if (c.second.get_value<bool>())
216  exportable_config.push_back(c.first);
217  }
218 
219  for (const auto &child : new_cfg)
220  {
221  if (std::find(exportable_config.begin(), exportable_config.end(),
222  child.first) != exportable_config.end())
223  {
224  kernel_config_.put_child(child.first, child.second);
225  }
226  }
227  }
228 }
229 
230 std::list<std::string> ConfigManager::get_non_importable_modules() const
231 {
232  std::list<std::string> ret;
233  const auto &no_import = kernel_config_.get_child_optional("no_import");
234 
235  if (no_import)
236  {
237  for (const auto &module : *no_import)
238  {
239  ret.push_back(module.first);
240  }
241  }
242  return ret;
243 }
244 
245 bool ConfigManager::is_module_importable(std::string const &module_name) const
246 {
247  auto lst = get_non_importable_modules();
248  return std::find(lst.begin(), lst.end(), module_name) == lst.end();
249 }
250 
252 {
253  return version_;
254 }
255 
257 {
258  ++version_;
259 }
260 
261 bool ConfigManager::has_config(const std::string &module) const
262 {
263  return modules_configs_.count(module);
264 }
265 
266 void ConfigManager::config_version(uint64_t new_version)
267 {
268  version_ = new_version;
269 }
270 
271 const std::string &ConfigManager::instance_name() const
272 {
273  return instance_name_;
274 }
Leosac::ConfigManager::load_config
const boost::property_tree::ptree & load_config(const std::string &module) const
Return the stored configuration for a given module.
Definition: ConfigManager.cpp:133
Leosac::ConfigManager::instance_name
const std::string & instance_name() const
Return the name of the instanced assigned in the configuration file.
Definition: ConfigManager.cpp:271
Leosac::Tools::PropertyTreeExtractor::get
T get(const std::string &node_name)
Extract a mandatory property from the tree.
Definition: PropertyTreeExtractor.cpp:36
WARN
@ WARN
Definition: log.hpp:33
operator<<
zmqpp::message & operator<<(zmqpp::message &msg, const Leosac::ConfigManager::ConfigFormat &fmt)
Definition: ConfigManager.cpp:155
ASSERT_LOG
#define ASSERT_LOG(cond, msg)
Definition: log.hpp:190
INFO
@ INFO
Definition: log.hpp:34
Leosac::ConfigManager::ConfigFormat
ConfigFormat
This enum is used internally, when core request module configuration.
Definition: ConfigManager.hpp:118
Leosac::ConfigManager::kconfig
const boost::property_tree::ptree & kconfig() const
Return const & on the general config tree.
Definition: ConfigManager.cpp:166
Leosac::ConfigManager::store_config
bool store_config(const std::string &module, const boost::property_tree::ptree &cfg)
Store the configuration tree for a module.
Definition: ConfigManager.cpp:117
Leosac::ConfigManager::ConfigManager
ConfigManager(const boost::property_tree::ptree &cfg)
Construct the Configuration Manager from a property tree.
Definition: ConfigManager.cpp:31
Leosac::ConfigManager::set_kconfig
void set_kconfig(const boost::property_tree::ptree &new_cfg)
Update Leosac's core config ptree.
Definition: ConfigManager.cpp:186
Leosac::ConfigManager::instance_name_
std::string instance_name_
Definition: ConfigManager.hpp:189
PropertyTreeExtractor.hpp
operator>>
zmqpp::message & operator>>(zmqpp::message &msg, Leosac::ConfigManager::ConfigFormat &fmt)
Definition: ConfigManager.cpp:142
Leosac
This is the header file for a generated source file, GitSHA1.cpp.
Definition: APIStatusCode.hpp:22
kernel.hpp
Leosac::ConfigManager::get_general_config
boost::property_tree::ptree get_general_config() const
Extract the current "general configuration".
Definition: ConfigManager.cpp:59
Leosac::ConfigManager::modules_configs_
std::map< std::string, boost::property_tree::ptree > modules_configs_
Maps a module's name to a property tree object.
Definition: ConfigManager.hpp:179
Leosac::ConfigManager::has_config
bool has_config(const std::string &module) const
Do we have config information for the module.
Definition: ConfigManager.cpp:261
Leosac::ConfigManager::incr_version
void incr_version()
Increment by 1 the current version number.
Definition: ConfigManager.cpp:256
Leosac::ConfigManager::get_exportable_general_config
boost::property_tree::ptree get_exportable_general_config() const
Return the property_tree of item inside the <kernel> tag (except <modules>`) that are marked exportab...
Definition: ConfigManager.cpp:76
XmlPropertyTree.hpp
Leosac::ConfigManager::config_version
uint64_t config_version() const
Return the current configuration version.
Definition: ConfigManager.cpp:251
Leosac::ConfigManager::get_non_importable_modules
std::list< std::string > get_non_importable_modules() const
Returns a list of module name that should not be imported.
Definition: ConfigManager.cpp:230
Leosac::Tools::PropertyTreeExtractor
This class is a simpler helper to extract value from a property tree.
Definition: PropertyTreeExtractor.hpp:38
Leosac::ConfigManager::is_module_importable
bool is_module_importable(const std::string &) const
Helper around get_non_importable_modules()
Definition: ConfigManager.cpp:245
log.hpp
Leosac::ConfigManager::kernel_config_
boost::property_tree::ptree kernel_config_
Property tree for general configuration.
Definition: ConfigManager.hpp:185
Leosac::ConfigManager::remove_config
bool remove_config(const std::string &module)
Remove the config entry for the module named module.
Definition: ConfigManager.cpp:176
ConfigManager.hpp
Leosac::ConfigManager::get_application_config
boost::property_tree::ptree get_application_config()
Retrieve the (current, running) configuration from the application and its modules.
Definition: ConfigManager.cpp:41
Leosac::ConfigManager::version_
uint64_t version_
Definition: ConfigManager.hpp:187