dodo  0.0.1
A C++ library to create containerized Linux services
config.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the dodo library (https://github.com/jmspit/dodo).
3  * Copyright (c) 2019 Jan-Marten Spit.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /**
19  * @file config.hpp
20  * Defines the dodo::common::Config class.
21  */
22 
23 #include <map>
24 #include <string>
25 
26 #include <yaml-cpp/yaml.h>
27 #include <common/bytes.hpp>
28 #include <common/exception.hpp>
29 #include <threads/mutex.hpp>
30 
31 #ifndef common_config_hpp
32 #define common_config_hpp
33 
34 namespace dodo::common {
35 
36  /**
37  * Singleton interface to a (read-only) deployment configuration, combining data from the deployment configuration
38  * file, environment variables and some operating system attributes such as the CPU count, RAM and virtual memory size.
39  *
40  * As multiple threads may be reading and modifying the configuration data, access must be serialized. However, as the
41  * data is exposed as a reference to a YAML::Node, this class cannot control serialization transparently. Developers
42  * know when they are done reading or writing the configuration data. For example
43  *
44  * @code
45  * {
46  * threads::Mutexer( getConfig()->getMutex() );
47  * const std::string username = config["username"].as<std::string>();
48  * }
49  * // Mutexer is out of scope, destructed and the getConfig()->getMutex() lock is released.
50  * @endcode
51  */
52  class Config {
53  public:
54 
55  /**
56  * Used by getValue, enable use of list initializers as path specification, eg
57  * @code
58  * std::string s = getvalue<std::string>( { "level1","level2","level2"} )
59  * @endcode
60  * on this YAML
61  * @code
62  * level1:
63  * level2:
64  * level3: foo
65  * @endcode
66  * would set s to "foo". A KeyPath cannot index into arrays.
67  */
68  typedef std::list<std::string> KeyPath;
69 
70  /** The dodo root node */
72 
73  /** The dodo.common node */
75 
76  /** The dodo.common.application node */
78 
79  /** The dodo.common.application.name node */
81 
82  /** The dodo.common.application.secret node */
84 
85  /** The dodo.common.application.secret.file node */
87 
88  /** The dodo.common.application.secret.env node */
90 
91  /** The dodo.common.logger node */
93 
94  /** The dodo.common.logger.console node */
96 
97  /** The dodo.common.logger.console.level node */
99 
100  /** The dodo.common.logger.file node */
102 
103  /** The dodo.common.logger.file.level node */
105 
106  /** The dodo.common.logger.file.directory node */
108 
109  /** The dodo.common.logger.file.max-size-mib node */
111 
112  /** The dodo.common.logger.file.max-file-trail node */
114 
115  /** The dodo.common.logger.syslog node */
117 
118  /** The dodo.common.logger.syslog.level node */
120 
121  /** The dodo.common.logger.syslog.facility node */
123 
124 
125 
126  /**
127  * Transform a keypath to a string with ":" as seperator between levels.
128  * @param keypath The KeyPath to flatten.
129  * @return The flattened keypath.
130  */
131  static std::string flattenKeyPath( const KeyPath& keypath );
132 
133  /**
134  * Disallow the copy constructor as this is a singleton.
135  */
136  Config( const Config& ) = delete;
137 
138  /**
139  * Disallow assignment from another Config, as this is a singleton.
140  */
141  Config& operator=( const Config& ) = delete;
142 
143  /**
144  * Initialize the singleton. Once initialize is called, subsequent calls
145  * to getConfig() will return the same pointer as returned by this function.
146  * @param path The path to the configuration file.
147  * @return a pointer to the Config singleton.
148  */
149  static Config* initialize( const std::string path );
150 
151  /**
152  * return the singleton.
153  * @return a pointer to the Config instance.
154  * @throw Exception when
155  */
156  static Config* getConfig();
157 
158  /**
159  * Return the path of the configuration file.
160  * @return The path of the configuration file.
161  */
162  std::string getConfigPath() const { return path_; }
163 
164  /**
165  * Read the configuration file.
166  */
167  void readConfig();
168 
169 
170  /**
171  * Return the application name.
172  * @return the application name.
173  */
174  std::string getAppName() const { return getValue<std::string>( {"dodo","common","application","name"} ); }
175 
176  /**
177  * Get the application secret.
178  * @return The secret.
179  */
180  std::string getSecret() const { return secret_; }
181 
182  /**
183  * Get the value at keypath.
184  * @param keypath The KeyPath to get the value for.
185  * @return The value.
186  */
187  template <typename T> T getValue( const KeyPath &keypath ) const {
188  YAML::Node ref = Clone( yaml_ );
189  for( const auto &k : keypath ) {
190  if ( ! ref[k] ) throw_Exception( "key " << flattenKeyPath(keypath) << " not found in " << path_ );
191  ref = ref[k];
192  }
193  return ref.as<T>();
194  }
195 
196  /**
197  * Return true if the KeyPath exists.
198  * @param keypath The KeyPath to check.
199  * @return True if the keypath exists.
200  */
201  bool exists( const KeyPath &keypath ) const {
202  YAML::Node ref = Clone( yaml_ );
203  for( const auto &k : keypath ) {
204  if ( ! ref[k] ) return false;
205  ref = ref[k];
206  }
207  return true;
208  }
209 
210  /**
211  * Get the decrypted value from KeyPath - decrypted using the secret from getSecret().
212  * @param keypath The KeyPath to the the value for.
213  * @param decrypted Receives the decrypted Bytes.
214  */
215  void getDecryptedValue( const KeyPath &keypath, Bytes &decrypted );
216 
217  protected:
218 
219  /**
220  * Constructor called by initialize().
221  * @param path The path to the configuration file.
222  */
223  Config( const std::string path );
224 
225  /**
226  * Destructor.
227  */
228  virtual ~Config() {}
229 
230  /**
231  * Check for required elements in the config file.
232  */
233  void checkConfig();
234 
235  /**
236  * The singleton pointer.
237  */
238  static Config* config_;
239 
240  /**
241  * The path to the configuration file.
242  */
243  static std::string path_;
244 
245  /**
246  * The root YAML node.
247  */
248  YAML::Node yaml_;
249 
250  /**
251  * The encryption secret / key.
252  */
253  std::string secret_;
254 
255  /**
256  * Application::~Application() will destruct this singleton
257  */
258  friend class Application;
259  };
260 
261 }
262 
263 #endif
dodo::common::Config::config_dodo_common_logger
static const Config::KeyPath config_dodo_common_logger
The dodo.common.logger node.
Definition: config.hpp:92
dodo::common::Config::exists
bool exists(const KeyPath &keypath) const
Return true if the KeyPath exists.
Definition: config.hpp:201
dodo::common::Config::getConfig
static Config * getConfig()
return the singleton.
Definition: config.cpp:68
dodo::common::Config::secret_
std::string secret_
The encryption secret / key.
Definition: config.hpp:253
dodo::common::Config::getAppName
std::string getAppName() const
Return the application name.
Definition: config.hpp:174
dodo::common::Config::config_
static Config * config_
The singleton pointer.
Definition: config.hpp:238
dodo::common::Config::config_dodo_common_application_secret_file
static const Config::KeyPath config_dodo_common_application_secret_file
The dodo.common.application.secret.file node.
Definition: config.hpp:86
dodo::common::Bytes
An array of Octets with size elements.
Definition: bytes.hpp:44
dodo::common::Config::config_dodo_common_logger_syslog_level
static const Config::KeyPath config_dodo_common_logger_syslog_level
The dodo.common.logger.syslog.level node.
Definition: config.hpp:119
dodo::common::Config::getSecret
std::string getSecret() const
Get the application secret.
Definition: config.hpp:180
dodo::common::Config::config_dodo
static const Config::KeyPath config_dodo
The dodo root node.
Definition: config.hpp:71
dodo::common::Config::config_dodo_common_application
static const Config::KeyPath config_dodo_common_application
The dodo.common.application node.
Definition: config.hpp:77
dodo::common::Config::config_dodo_common_logger_file_directory
static const Config::KeyPath config_dodo_common_logger_file_directory
The dodo.common.logger.file.directory node.
Definition: config.hpp:107
dodo::common::Config::yaml_
YAML::Node yaml_
The root YAML node.
Definition: config.hpp:248
dodo::common::Config::Config
Config(const Config &)=delete
Disallow the copy constructor as this is a singleton.
dodo::common::Config::config_dodo_common_logger_syslog
static const Config::KeyPath config_dodo_common_logger_syslog
The dodo.common.logger.syslog node.
Definition: config.hpp:116
dodo::common::Config::operator=
Config & operator=(const Config &)=delete
Disallow assignment from another Config, as this is a singleton.
dodo::common::Config::readConfig
void readConfig()
Read the configuration file.
Definition: config.cpp:117
dodo::common::Config::config_dodo_common_logger_console_level
static const Config::KeyPath config_dodo_common_logger_console_level
The dodo.common.logger.console.level node.
Definition: config.hpp:98
dodo::common::Config::config_dodo_common
static const Config::KeyPath config_dodo_common
The dodo.common node.
Definition: config.hpp:74
dodo::common::Config
Singleton interface to a (read-only) deployment configuration, combining data from the deployment con...
Definition: config.hpp:52
dodo::common::Config::config_dodo_common_logger_file_max_file_trail
static const Config::KeyPath config_dodo_common_logger_file_max_file_trail
The dodo.common.logger.file.max-file-trail node.
Definition: config.hpp:113
throw_Exception
#define throw_Exception(what)
Throws an Exception, passes FILE and LINE to constructor.
Definition: exception.hpp:174
dodo::common::Config::path_
static std::string path_
The path to the configuration file.
Definition: config.hpp:243
dodo::common::Config::checkConfig
void checkConfig()
Check for required elements in the config file.
Definition: config.cpp:73
dodo::common
Common and utility interfaces.
Definition: application.hpp:29
dodo::common::Config::config_dodo_common_logger_file_level
static const Config::KeyPath config_dodo_common_logger_file_level
The dodo.common.logger.file.level node.
Definition: config.hpp:104
dodo::common::Config::config_dodo_common_logger_syslog_facility
static const Config::KeyPath config_dodo_common_logger_syslog_facility
The dodo.common.logger.syslog.facility node.
Definition: config.hpp:122
dodo::common::Config::getValue
T getValue(const KeyPath &keypath) const
Get the value at keypath.
Definition: config.hpp:187
exception.hpp
dodo::common::Config::KeyPath
std::list< std::string > KeyPath
Used by getValue, enable use of list initializers as path specification, eg.
Definition: config.hpp:68
dodo::common::Application
Red tape wrapper class for applications, from command line to services.
Definition: application.hpp:61
dodo::common::Config::config_dodo_common_application_secret
static const Config::KeyPath config_dodo_common_application_secret
The dodo.common.application.secret node.
Definition: config.hpp:83
dodo::common::Config::config_dodo_common_application_name
static const Config::KeyPath config_dodo_common_application_name
The dodo.common.application.name node.
Definition: config.hpp:80
dodo::common::Config::initialize
static Config * initialize(const std::string path)
Initialize the singleton.
Definition: config.cpp:62
dodo::common::Config::getConfigPath
std::string getConfigPath() const
Return the path of the configuration file.
Definition: config.hpp:162
dodo::common::Config::config_dodo_common_logger_console
static const Config::KeyPath config_dodo_common_logger_console
The dodo.common.logger.console node.
Definition: config.hpp:95
dodo::common::Config::config_dodo_common_application_secret_env
static const Config::KeyPath config_dodo_common_application_secret_env
The dodo.common.application.secret.env node.
Definition: config.hpp:89
dodo::common::Config::~Config
virtual ~Config()
Destructor.
Definition: config.hpp:228
dodo::common::Config::config_dodo_common_logger_file
static const Config::KeyPath config_dodo_common_logger_file
The dodo.common.logger.file node.
Definition: config.hpp:101
bytes.hpp
dodo::common::Config::flattenKeyPath
static std::string flattenKeyPath(const KeyPath &keypath)
Transform a keypath to a string with ":" as seperator between levels.
Definition: config.cpp:127
mutex.hpp
dodo::common::Config::config_dodo_common_logger_file_max_size_mib
static const Config::KeyPath config_dodo_common_logger_file_max_size_mib
The dodo.common.logger.file.max-size-mib node.
Definition: config.hpp:110
dodo::common::Config::getDecryptedValue
void getDecryptedValue(const KeyPath &keypath, Bytes &decrypted)
Get the decrypted value from KeyPath - decrypted using the secret from getSecret().
Definition: config.cpp:136