MySQL 9.0.0
Source Code Documentation
router_app.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2015, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef ROUTER_MYSQL_ROUTER_INCLUDED
27#define ROUTER_MYSQL_ROUTER_INCLUDED
28
30
31/** @file
32 * @brief Defining the main class MySQLRouter
33 *
34 * This file defines the main class `MySQLRouter`.
35 *
36 */
37
43
44#include <cstdint>
45#include <iostream>
46#include <stdexcept>
47#include <vector>
48
49static const size_t kHelpScreenWidth = 72;
50static const size_t kHelpScreenIndent = 8;
51
52static const std::string kSystemRouterName = "system";
53static const std::string kDefaultSystemUserName = "";
54
55class ConfigFiles;
56
57/** @class MySQLRouter
58 * @brief Manage the MySQL Router application.
59 *
60 * The class MySQLRouter manages the MySQL Router application. It handles the
61 * command arguments, finds valid configuration files, and starts all plugins.
62 *
63 * Since MySQL Router requires at least 1 configuration file to be available
64 * for reading, if no default configuration file location could be read and no
65 * explicit location was given, the application exits.
66 *
67 * The class depends on MySQL Harness to, among other things, load the
68 * configuration and initialize all request plugins.
69 *
70 * Example usage:
71 *
72 * int main(int argc, char** argv) {
73 * MySQLRouter router(argc, argv);
74 * router.start();
75 * }
76 *
77 */
79 public:
80 /** @brief Default constructor
81 *
82 * Default constructor of MySQL Router which will not initialize.
83 *
84 * Usage:
85 *
86 * MySQLRouter router;
87 * router.start();
88 *
89 */
91 : can_start_(false),
92 showing_info_(false),
93 out_stream_(std::cout),
94 err_stream_(std::cerr)
95#ifndef _WIN32
96 ,
97 sys_user_operations_(mysqlrouter::SysUserOperations::instance())
98#endif
99 {
100 }
101
102 /** @brief Constructor with command line arguments as vector
103 *
104 * Constructor of MySQL Router which will start with the given command
105 * line arguments as a vector of strings.
106 *
107 * Example usage:
108 *
109 * MySQLRouter router(argv[0],
110 * vector<string>({argv + 1, argv + argc}));
111 * router.start();
112 *
113 * @param program_name path of the started executable
114 * @param arguments a vector of strings
115 * @param out_stream output stream representing "stdout"
116 * @param err_stream output stream representing "stderr"
117 */
118#ifndef _WIN32
119 /// @param sys_user_operations system operations which provide chown, ...
120#endif
121 MySQLRouter(const std::string &program_name,
122 const std::vector<std::string> &arguments,
123 std::ostream &out_stream = std::cout,
124 std::ostream &err_stream = std::cerr
125#ifndef _WIN32
126 ,
127 mysqlrouter::SysUserOperationsBase *sys_user_operations =
129#endif
130 );
131
132 /** @brief Constructor with command line arguments
133 *
134 * Constructor of MySQL Router which will start with the given command
135 * line arguments given as the arguments argc and argv. Typically, argc
136 * and argv are passed on from the global main function.
137 *
138 * Example usage:
139 *
140 * int main(int argc, char** argv) {
141 * MySQLRouter router(argc, argv);
142 * router.start();
143 * }
144 *
145 * @param argc number of arguments
146 * @param argv pointer to first command line argument
147 * @param out_stream output stream representing "stdout"
148 * @param err_stream output stream representing "stderr"
149 */
150#ifndef _WIN32
151 /// @param sys_user_operations system operations which provide chown, ...
152#endif
153 MySQLRouter(const int argc, char **argv, std::ostream &out_stream,
154 std::ostream &err_stream
155#ifndef _WIN32
156 ,
157 mysqlrouter::SysUserOperationsBase *sys_user_operations =
159#endif
160 );
161
162 virtual ~MySQLRouter() = default;
163
164 /** @brief Initialize main logger
165 *
166 * Initializes main logger, according to options in the configuration.
167 *
168 * @param config Configuration to be used to initialize logger
169 * @param raw_mode If true, all messages are logged raw; if false, messages
170 * are subject formatting
171 * @param use_os_log If true, Windows EventLog will be used instead of STDERR;
172 * Currently this option is only meaningful on Windows
173 *
174 * @throws std::runtime_error on:
175 * - failure to initialize file or OS logger
176 * - bad configuration
177 *
178 * @note This function is static and public, because unlike
179 * create_plugin_loggers(), it's also meant to be called very early during
180 * startup, close to main().
181 */
183 bool raw_mode = false, bool use_os_log = false);
184
185 // Information member function
186 std::string get_package_name() noexcept;
187
188 /** @brief Returns the MySQL Router version as string
189 *
190 * Returns the MySQL Router as a string. The string is a concatenation
191 * of version's major, minor and patch parts, for example `1.0.2`.
192 *
193 * @return string containing the version
194 */
195 std::string get_version() noexcept;
196
197 /** @brief Returns string version details.
198 *
199 * Returns string with name and version details, including:
200 *
201 * * name of the application,
202 * * version,
203 * * platform and architecture,
204 * * edition,
205 * * and a special part-of-clause.
206 *
207 * The architecture is either 32-bit or 64-bit. Edition is usually used to
208 * denote whether release is either GPLv2 license or commercial.
209 *
210 * The part-of clause is used to show which product family MySQL Router
211 * belongs to.
212 *
213 * @internal
214 * Most information can be defined while configuring using CMake and will
215 * become available through the router_config.h file (generated from
216 * router_config.h.in).
217 * @endinternal
218 *
219 * @return a string containing version details
220 */
221 std::string get_version_line() noexcept;
222
223 /** @brief Starts the MySQL Router application
224 *
225 * Starts the MySQL Router application, reading the configuration file(s) and
226 * loading and starting all plugins.
227 *
228 * Example:
229 *
230 * MySQLRouter router;
231 * router.start();
232 *
233 * Throws std::runtime_error on configuration or plugin errors.
234 *
235 * @internal
236 * We are using MySQL Harness to load and start the plugins. We give Harness
237 * a configuration files and it will parse it. Not that at this moment,
238 * Harness only accept one configuration file.
239 * @endinternal
240 */
241 void start();
242
243 /** @brief Stop and cleanup the MySQL Router application
244 *
245 * Cleanup to perform when the MySQL Router application shuts down.
246 *
247 * Example:
248 *
249 * MySQLRouter router;
250 * router.start();
251 * ...
252 * router.stop();
253 *
254 * Throws std::runtime_error on errors during cleanup.
255 *
256 * @internal
257 * We ensure that the Harness pidfile is removed if present.
258 * @endinternal
259 */
260 void stop();
261
262 /** @brief Gets list of default configuration files
263 *
264 * Returns a list of configuration files which will be read (if available)
265 * by default.
266 *
267 * @return std::vector<string>
268 */
269 const std::vector<std::string> &get_default_config_files() const noexcept {
271 }
272
273 /** @brief Gets list of configuration files passed using command line
274 *
275 * Returns a list of configuration files which were passed through command
276 * line options.
277 *
278 * @return std::vector<string>
279 */
280 const std::vector<std::string> &get_config_files() const noexcept {
281 return config_files_;
282 }
283
284 /** @brief Gets list of extra configuration files passed using command line
285 *
286 * Returns a list of extra configuration files which were passed through
287 * command line options.
288 *
289 * @return std::vector<string>
290 */
291 const std::vector<std::string> &get_extra_config_files() const noexcept {
292 return extra_config_files_;
293 }
294
295#if !defined(_MSC_VER) && !defined(UNIT_TESTS)
296 // MSVC produces different symbols for private vs public methods, which mean
297 // the #define private public trick for unit-testing private methods doesn't
298 // work. Thus, we turn private methods public in Windows.
299 private:
300#endif
301
302 /** @brief Initializes the MySQL Router application
303 *
304 * Initialized the MySQL Router application by
305 *
306 * * setting the default configuration files,
307 * * loading the command line options,
308 * * processing the given command line arguments,
309 * * and finding all the usable configuration files.
310 *
311 * The command line options are passed using the `arguments`
312 * argument. It should be a vector of strings. For example, to start
313 * MySQL Router using the `main()` functions `argc` and `argv`
314 * arguments:
315 *
316 * MySQLRouter router(vector<string>({argv + 1, argv + argc}));
317 * router.start();
318 *
319 * @internal
320 * We do not need the first command line argument, argv[0] since we do not
321 * use it.
322 * @endinternal
323 *
324 * @param program_name path to the executable.
325 * @param arguments command line arguments as vector of strings
326 */
327 virtual void init(const std::string &program_name,
328 const std::vector<std::string> &arguments);
329
330 /** @brief Prepares a command line option
331 *
332 * Prepares command line options for the MySQL Router `mysqlrouter`
333 * application.
334 *
335 * @internal
336 * Currently, to add options to the command line, you need to add it to the
337 * `prepare_command_options`-method using `CmdArgHandler::add_option()`.
338 * @endinternal
339 */
340 void prepare_command_options() noexcept;
341
342 /** @brief Process command line options
343 *
344 * Processes command line options for the MySQL Router `mysqlrouter`
345 * application.
346 */
348 const std::vector<std::string> &arguments); // throws std::runtime_error
349
350 /** @brief Finds all valid configuration files
351 *
352 * Finds all valid configuration files from the list of default
353 * configuration file locations.
354 *
355 * An exception of type `std::runtime_error` is thrown when no valid
356 * configuration file was found.
357 *
358 * @return returns a list of valid configuration file locations
359 *
360 */
361 std::vector<std::string> check_config_files();
362
363 /** @brief Shows the help screen on the console
364 *
365 * Shows the help screen on the console including
366 *
367 * * copyright and trademark notice,
368 * * command line usage,
369 * * default configuration file locations,
370 * * and options with their descriptions.
371 *
372 * Users would use the command line option `--help`:
373 *
374 * shell> mysqlrouter --help
375 */
376 void show_help();
377
378 /** @brief Saves the selected command line option in the internal options
379 * array after verifying it's value not empty and the router is doing
380 * bootstrap.
381 *
382 * Throws: std::runtime_error
383 */
384 void save_bootstrap_option_not_empty(const std::string &option_name,
385 const std::string &save_name,
386 const std::string &option_value);
387
388 /**
389 * @brief verify that bootstrap option (--bootstrap or -B) was given by user.
390 *
391 * @throw std::runtime_error if called in non-bootstrap mode.
392 */
393 void assert_bootstrap_mode(const std::string &option_name) const;
394
395 /**
396 * @brief verify that option given by user is not used with bootstrap option
397 * (--bootstrap or -B).
398 *
399 * @throw std::runtime_error if called in bootstrap mode.
400 */
401 void assert_not_bootstrap_mode(const std::string &option_name) const;
402
403 /**
404 * @brief verify that option given by user is an integer value in the given
405 * range.
406 *
407 * @throw std::out_of_range - option not in [min, max] range
408 * @throw std::invalid_argument - not a valid integer
409 */
410 void assert_option_value_in_range(const std::string &option_value,
411 const int min, const int max) const;
412
413 /** @brief Shows command line usage and option description
414 *
415 * Shows command line usage and all available options together with their
416 * description. It is possible to prevent the option listing by setting the
417 * argument `include_options` to `false`.
418 *
419 * @internal
420 * This method is used by the `MySQLRouter::show_help()`. We keep a separate
421 * method so we could potentionally show the usage in other places or using
422 * different option combinations, for example after an error.
423 * @endinternal
424 *
425 * @param include_options bool whether we show the options and descriptions
426 */
427 void show_usage(bool include_options) noexcept;
428
429 /* @overload */
430 void show_usage() noexcept;
431
432 /** @brief Sets default configuration file locations
433 *
434 * Sets the default configuration file locations based on information
435 * found in the locations argument. The locations should be provided
436 * as a semicolon separated list.
437 *
438 * The previous loaded locations are first removed. If not new locations
439 * were provider (if locations argument is empty), then no configuration
440 * files will be available.
441 *
442 * Locations can include environment variable placeholders. These
443 * placeholders are replaced using the provided name. For example, user Jane
444 * executing MySQL Router:
445 *
446 * /opt/ENV{USER}/etc becomes /opt/jane/etc
447 *
448 * If the environment variable is not available, for example if
449 * MYSQL_ROUTER_HOME was not set before starting MySQL Router, every location
450 * using this environment variable will be ignored.
451 *
452 * @param locations a char* with semicolon separated file locations
453 */
454 void set_default_config_files(const char *locations) noexcept;
455
456 void bootstrap(const std::string &program_name,
457 const std::string &metadata_server_uri,
458 const std::string &plugin_folder = "");
459
460 /*
461 * @brief returns id of the router.
462 *
463 * @throw bad_section
464 */
465 uint32_t get_router_id(mysql_harness::Config &config);
466
467 void init_keyring(mysql_harness::Config &config);
468
469 void init_dynamic_state(mysql_harness::Config &config);
470
471 /**
472 * @brief Initializes keyring using master-key-reader and master-key-writer.
473 *
474 * @throw MasterKeyReadError
475 */
477
478 /**
479 * @brief Initializes keyring using master key file.
480 *
481 * @throw std::runtime_error
482 */
484
485 /**
486 * @brief Initializes keyring using password read from STDIN.
487 *
488 * @throw std::runtime_error
489 */
491
492 // throws std::runtime_error
493 void init_loader(mysql_harness::LoaderConfig &config);
494
495 // throws std::runtime_error
496 mysql_harness::LoaderConfig *make_config(
497 const std::map<std::string, std::string> params,
498 const std::vector<std::string> &config_files);
499
500 std::map<std::string, std::string> get_default_paths() const;
501
502 /** @brief Tuple describing the MySQL Router version, with major, minor and
503 * patch level **/
504 std::tuple<const uint8_t, const uint8_t, const uint8_t> version_;
505
506 /** @brief Vector with default configuration file locations as strings **/
508 /** @brief Vector with extra configuration file locations as strings **/
510 /** @brief Vector with configuration files passed through command line
511 * arguments **/
513 /** @brief PID file location **/
515 bool pid_file_created_{false};
516
517 /** @brief CmdArgHandler object handling command line arguments **/
519 /** @brief Harness loader **/
520 std::unique_ptr<mysql_harness::Loader> loader_;
521 /** @brief Whether the MySQLRouter can start or not **/
523 /** @brief Whether we are showing information on command line, for example,
524 * using --help or --version **/
526 /**
527 * @brief Value of the argument passed to the -B or --bootstrap
528 * command line option for bootstrapping.
529 */
530 std::string bootstrap_uri_;
531 /**
532 * @brief Valueof the argument passed to the --directory command line option
533 */
535 /**
536 * @brief key/value map of additional configuration options for bootstrap
537 */
538 std::map<std::string, std::string> bootstrap_options_;
539
540 /**
541 * @brief key/list-of-values map of additional configuration options for
542 * bootstrap
543 */
544 std::map<std::string, std::vector<std::string>> bootstrap_multivalue_options_;
545
546 /**
547 * Path to origin of executable.
548 *
549 * This variable contain the directory that the executable is
550 * running from.
551 */
553
555
556 std::ostream &out_stream_;
557 std::ostream &err_stream_;
558
559 bool core_file_{false};
560
561#ifndef _WIN32
562 /** @brief Value of the --user parameter given on the command line if router
563 * is launched in bootstrap mode **/
564 std::string user_cmd_line_;
565
566 /** @brief Value of the --user parameter given on the command line. It is used
567 *to buffer the value of --user parameter till all command line parameters are
568 *parsed. If router is launched in bootstrap mode, then username_ is copied to
569 *user_cmd_line_, otherwise it is copied to bootstrap_options_["user"]
570 **/
571 std::string username_;
572
573 /** @brief Pointer to the object to be used to perform system specific
574 * user-related operations **/
576#endif
577
579
580#ifdef FRIEND_TEST
581 FRIEND_TEST(Bug24909259, PasswordPrompt_plain);
582 FRIEND_TEST(Bug24909259, PasswordPrompt_keyed);
583#endif
584};
585
586class silent_exception : public std::exception {
587 public:
588 silent_exception() : std::exception() {}
589};
590
591/** @brief Expose the configured application-level options (the ones
592 * from [DEFAULT] section that are not specific to any particular plugin and are
593 * relevant from the Cluster metadata perspective) **/
594void expose_router_configuration(const bool initial,
595 const mysql_harness::ConfigSection &section);
596
597#endif // ROUTER_MYSQL_ROUTER_INCLUDED
Defining the commandline argument handler class CmdArgHandler.
Handles command line arguments.
Definition: arg_handler.h:141
KeyringInfo class encapsulates loading and storing master key using master-key-reader and master-key-...
Definition: keyring_info.h:76
Manage the MySQL Router application.
Definition: router_app.h:78
std::ostream & out_stream_
Definition: router_app.h:556
void assert_not_bootstrap_mode(const std::string &option_name) const
verify that option given by user is not used with bootstrap option (–bootstrap or -B).
Definition: router_app.cc:898
void stop()
Stop and cleanup the MySQL Router application.
Definition: router_app.cc:801
void init_dynamic_state(mysql_harness::Config &config)
Definition: router_app.cc:371
const std::vector< std::string > & get_extra_config_files() const noexcept
Gets list of extra configuration files passed using command line.
Definition: router_app.h:291
bool showing_info_
Whether we are showing information on command line, for example, using –help or –version.
Definition: router_app.h:525
void prepare_command_options() noexcept
Prepares a command line option.
Definition: router_app.cc:961
uint32_t get_router_id(mysql_harness::Config &config)
Definition: router_app.cc:329
std::vector< std::string > check_config_files()
Finds all valid configuration files.
Definition: router_app.cc:839
std::string get_package_name() noexcept
void show_help()
Shows the help screen on the console.
Definition: router_app.cc:1961
bool core_file_
Definition: router_app.h:559
std::string bootstrap_uri_
Value of the argument passed to the -B or –bootstrap command line option for bootstrapping.
Definition: router_app.h:530
std::map< std::string, std::vector< std::string > > bootstrap_multivalue_options_
key/list-of-values map of additional configuration options for bootstrap
Definition: router_app.h:544
void parse_command_options(const std::vector< std::string > &arguments)
Process command line options.
Definition: router_app.cc:228
std::string user_cmd_line_
Value of the –user parameter given on the command line if router is launched in bootstrap mode.
Definition: router_app.h:564
std::string username_
Value of the –user parameter given on the command line.
Definition: router_app.h:571
std::vector< std::string > extra_config_files_
Vector with extra configuration file locations as strings.
Definition: router_app.h:509
virtual void init(const std::string &program_name, const std::vector< std::string > &arguments)
Initializes the MySQL Router application.
Definition: router_app.cc:240
void init_keyring(mysql_harness::Config &config)
Definition: router_app.cc:345
mysql_harness::LoaderConfig * make_config(const std::map< std::string, std::string > params, const std::vector< std::string > &config_files)
Definition: router_app.cc:504
void assert_option_value_in_range(const std::string &option_value, const int min, const int max) const
verify that option given by user is an integer value in the given range.
Definition: router_app.cc:905
bool pid_file_created_
Definition: router_app.h:515
std::map< std::string, std::string > bootstrap_options_
key/value map of additional configuration options for bootstrap
Definition: router_app.h:538
std::map< std::string, std::string > get_default_paths() const
Definition: router_app.cc:431
void init_keyring_using_external_facility(mysql_harness::Config &config)
Initializes keyring using master-key-reader and master-key-writer.
Definition: router_app.cc:385
KeyringInfo keyring_info_
Definition: router_app.h:554
void save_bootstrap_option_not_empty(const std::string &option_name, const std::string &save_name, const std::string &option_value)
Saves the selected command line option in the internal options array after verifying it's value not e...
Definition: router_app.cc:882
const std::vector< std::string > & get_default_config_files() const noexcept
Gets list of default configuration files.
Definition: router_app.h:269
std::unique_ptr< mysql_harness::Loader > loader_
Harness loader.
Definition: router_app.h:520
std::string pid_file_path_
PID file location.
Definition: router_app.h:514
void init_keyring_using_prompted_password()
Initializes keyring using password read from STDIN.
Definition: router_app.cc:403
CmdArgHandler arg_handler_
CmdArgHandler object handling command line arguments.
Definition: router_app.h:518
std::string get_version() noexcept
Returns the MySQL Router version as string.
Definition: router_app.cc:830
mysql_harness::Path origin_
Path to origin of executable.
Definition: router_app.h:552
mysql_harness::SignalHandler signal_handler_
Definition: router_app.h:578
void assert_bootstrap_mode(const std::string &option_name) const
verify that bootstrap option (–bootstrap or -B) was given by user.
Definition: router_app.cc:892
std::vector< std::string > default_config_files_
Vector with default configuration file locations as strings.
Definition: router_app.h:507
const std::vector< std::string > & get_config_files() const noexcept
Gets list of configuration files passed using command line.
Definition: router_app.h:280
void init_keyring_using_master_key_file()
Initializes keyring using master key file.
Definition: router_app.cc:398
std::string bootstrap_directory_
Valueof the argument passed to the –directory command line option.
Definition: router_app.h:534
void start()
Starts the MySQL Router application.
Definition: router_app.cc:543
MySQLRouter()
Default constructor.
Definition: router_app.h:90
std::vector< std::string > config_files_
Vector with configuration files passed through command line arguments.
Definition: router_app.h:512
virtual ~MySQLRouter()=default
void show_usage() noexcept
Definition: router_app.cc:2146
static void init_main_logger(mysql_harness::LoaderConfig &config, bool raw_mode=false, bool use_os_log=false)
Initialize main logger.
Definition: router_app.cc:437
std::ostream & err_stream_
Definition: router_app.h:557
void set_default_config_files(const char *locations) noexcept
Sets default configuration file locations.
Definition: router_app.cc:812
mysqlrouter::SysUserOperationsBase * sys_user_operations_
Pointer to the object to be used to perform system specific user-related operations.
Definition: router_app.h:575
void init_loader(mysql_harness::LoaderConfig &config)
Definition: router_app.cc:530
bool can_start_
Whether the MySQLRouter can start or not.
Definition: router_app.h:522
std::tuple< const uint8_t, const uint8_t, const uint8_t > version_
Tuple describing the MySQL Router version, with major, minor and patch level.
Definition: router_app.h:504
std::string get_version_line() noexcept
Returns string version details.
Definition: router_app.cc:832
Configuration section.
Definition: config_parser.h:141
Configuration file handler for the loader.
Definition: loader_config.h:46
Class representing a path in a file system.
Definition: filesystem.h:63
Definition: signal_handler.h:41
Base class to allow multiple SysUserOperations implementations.
Definition: sys_user_operations.h:45
static SysUserOperations * instance()
Definition: sys_user_operations.cc:49
Definition: router_app.h:586
silent_exception()
Definition: router_app.h:588
Definition: bootstrap.cc:71
Definition: common.h:42
Definition: dim.h:358
Definition: gcs_xcom_synode.h:64
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2875
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2893
static const size_t kHelpScreenWidth
Definition: router_app.h:49
static const std::string kDefaultSystemUserName
Definition: router_app.h:53
static const std::string kSystemRouterName
Definition: router_app.h:52
static const size_t kHelpScreenIndent
Definition: router_app.h:50
void expose_router_configuration(const bool initial, const mysql_harness::ConfigSection &section)
Expose the configured application-level options (the ones from [DEFAULT] section that are not specifi...
Definition: router_app.cc:2205