55 *
66 * The MIT License
77 *
8- * @copyright Copyright (c) 2017-2023 TileDB, Inc.
8+ * @copyright Copyright (c) 2017-2024 TileDB, Inc.
99 *
1010 * Permission is hereby granted, free of charge, to any person obtaining a copy
1111 * of this software and associated documentation files (the "Software"), to deal
3030 * This file implements class Config.
3131 */
3232
33+ #include < filesystem>
3334#include < fstream>
3435#include < iostream>
3536#include < sstream>
3637
3738#include " config.h"
39+ #include " external/include/nlohmann/json.hpp"
3840#include " tiledb/common/logger.h"
3941#include " tiledb/sm/enums/serialization_type.h"
4042#include " tiledb/sm/misc/constants.h"
4143#include " tiledb/sm/misc/parse_argument.h"
4244
45+ using json = nlohmann::json;
46+
4347using namespace tiledb ::common;
4448
4549namespace {
@@ -60,14 +64,12 @@ bool ignore_default_via_env(const std::string& param) {
6064
6165namespace tiledb ::sm {
6266
63- /* * Return a Config error class Status with a given message **/
64- inline Status Status_ConfigError (const std::string& msg) {
65- return {" [TileDB::Config] Error" , msg};
66- }
67-
68- void throw_config_exception (const std::string& msg) {
69- throw StatusException (Status_ConfigError (msg));
70- }
67+ class ConfigException : public StatusException {
68+ public:
69+ explicit ConfigException (const std::string& msg)
70+ : StatusException(" Config" , msg) {
71+ }
72+ };
7173
7274/* ****************************** */
7375/* CONFIG DEFAULTS */
@@ -561,17 +563,55 @@ Config::~Config() = default;
561563/* API */
562564/* ****************************** */
563565
566+ void Config::login () {
567+ // Retrieve $HOME path
568+ std::string home_dir;
569+ #ifdef _WIN32
570+ home_dir = std::string (std::getenv (" HOMEDRIVE" ) + getenv (" HOMEPATH" ));
571+ #else
572+ home_dir = std::string (std::getenv (" HOME" ));
573+ #endif
574+
575+ // For library versions 22 and older, simply parse the local .json file
576+ if (constants::format_version <= 22 ) {
577+ // Find and parse the cloud.json file
578+ std::string file = home_dir + " /.tiledb/cloud.json" ;
579+ if (!std::filesystem::exists (file)) {
580+ throw ConfigException (" Cannot login; cloud.json file does not exist." );
581+ }
582+ json data = json::parse (std::ifstream (file));
583+
584+ // Set the config values that have been saved to the file
585+ if (data.contains (" api_key" ) &&
586+ data[" api_key" ].contains (" X-TILEDB-REST-API-KEY" )) {
587+ throw_if_not_ok (
588+ set (" rest.token" , data[" api_key" ][" X-TILEDB-REST-API-KEY" ]));
589+ }
590+ if (data.contains (" host" )) {
591+ throw_if_not_ok (set (" rest.server_address" , data[" host" ]));
592+ }
593+ if (data.contains (" password" )) {
594+ throw_if_not_ok (set (" rest.password" , data[" password" ]));
595+ }
596+ if (data.contains (" username" )) {
597+ throw_if_not_ok (set (" rest.username" , data[" username" ]));
598+ }
599+ if (data.contains (" verify_ssl" )) {
600+ throw_if_not_ok (
601+ set (" vfs.s3.verify_ssl" , data[" verify_ssl" ] ? " true" : " false" ));
602+ }
603+ }
604+ }
605+
564606Status Config::load_from_file (const std::string& filename) {
565607 // Do nothing if filename is empty
566- if (filename.empty ())
567- return LOG_STATUS (
568- Status_ConfigError ( " Cannot load from file; Invalid filename " ));
608+ if (filename.empty ()) {
609+ throw ConfigException ( " Cannot load from file; Invalid filename " );
610+ }
569611
570612 std::ifstream ifs (filename);
571613 if (!ifs.is_open ()) {
572- std::stringstream msg;
573- msg << " Failed to open config file '" << filename << " '" ;
574- return LOG_STATUS (Status_ConfigError (msg.str ()));
614+ throw ConfigException (" Failed to open config file '" + filename + " '" );
575615 }
576616
577617 size_t linenum = 0 ;
@@ -592,7 +632,7 @@ Status Config::load_from_file(const std::string& filename) {
592632 std::stringstream msg;
593633 msg << " Failed to parse config file '" << filename << " '; " ;
594634 msg << " Missing parameter value (line: " << linenum << " )" ;
595- return LOG_STATUS ( Status_ConfigError ( msg.str () ));
635+ throw ConfigException ( msg.str ());
596636 }
597637
598638 // Parse extra
@@ -601,7 +641,7 @@ Status Config::load_from_file(const std::string& filename) {
601641 std::stringstream msg;
602642 msg << " Failed to parse config file '" << filename << " '; " ;
603643 msg << " Invalid line format (line: " << linenum << " )" ;
604- return LOG_STATUS ( Status_ConfigError ( msg.str () ));
644+ throw ConfigException ( msg.str ());
605645 }
606646
607647 // Set param-value pair
@@ -614,15 +654,14 @@ Status Config::load_from_file(const std::string& filename) {
614654
615655Status Config::save_to_file (const std::string& filename) {
616656 // Do nothing if filename is empty
617- if (filename.empty ())
618- return LOG_STATUS (
619- Status_ConfigError ( " Cannot save to file; Invalid filename " ));
657+ if (filename.empty ()) {
658+ throw ConfigException ( " Cannot save to file; Invalid filename " );
659+ }
620660
621661 std::ofstream ofs (filename);
622662 if (!ofs.is_open ()) {
623- std::stringstream msg;
624- msg << " Failed to open config file '" << filename << " ' for writing" ;
625- return LOG_STATUS (Status_ConfigError (msg.str ()));
663+ throw ConfigException (
664+ " Failed to open config file '" + filename + " ' for writing" );
626665 }
627666 for (auto & pv : param_values_) {
628667 if (unserialized_params_.count (pv.first ) != 0 )
@@ -664,7 +703,7 @@ Status Config::get(const std::string& param, T* value, bool* found) const {
664703 // Parameter found, retrieve value
665704 auto status = utils::parse::convert (val, value);
666705 if (!status.ok ()) {
667- return Status_ConfigError (
706+ throw ConfigException (
668707 std::string (" Failed to parse config value '" ) + std::string (val) +
669708 std::string (" ' for key '" ) + param + " ' due to: " + status.to_string ());
670709 }
@@ -751,8 +790,7 @@ Status Config::sanity_check(
751790 RETURN_NOT_OK (utils::parse::convert (value, &v32));
752791 } else if (param == " config.logging_format" ) {
753792 if (value != " DEFAULT" && value != " JSON" )
754- return LOG_STATUS (
755- Status_ConfigError (" Invalid logging format parameter value" ));
793+ throw ConfigException (" Invalid logging format parameter value" );
756794 } else if (param == " sm.allow_separate_attribute_writes" ) {
757795 RETURN_NOT_OK (utils::parse::convert (value, &v));
758796 } else if (param == " sm.allow_updates_experimental" ) {
@@ -799,8 +837,7 @@ Status Config::sanity_check(
799837 RETURN_NOT_OK (utils::parse::convert (value, &v));
800838 } else if (param == " sm.var_offsets.mode" ) {
801839 if (value != " bytes" && value != " elements" )
802- return LOG_STATUS (
803- Status_ConfigError (" Invalid offsets format parameter value" ));
840+ throw ConfigException (" Invalid offsets format parameter value" );
804841 } else if (param == " sm.fragment_info.preload_mbrs" ) {
805842 RETURN_NOT_OK (utils::parse::convert (value, &v));
806843 } else if (param == " ssl.verify" ) {
@@ -825,8 +862,7 @@ Status Config::sanity_check(
825862 RETURN_NOT_OK (utils::parse::convert (value, &v32));
826863 } else if (param == " vfs.s3.scheme" ) {
827864 if (value != " http" && value != " https" )
828- return LOG_STATUS (
829- Status_ConfigError (" Invalid S3 scheme parameter value" ));
865+ throw ConfigException (" Invalid S3 scheme parameter value" );
830866 } else if (param == " vfs.s3.use_virtual_addressing" ) {
831867 RETURN_NOT_OK (utils::parse::convert (value, &v));
832868 } else if (param == " vfs.s3.skit_init" ) {
@@ -866,7 +902,7 @@ Status Config::sanity_check(
866902 (value == " bucket_owner_full_control" ))))) {
867903 std::stringstream msg;
868904 msg << " value " << param << " invalid canned acl for " << param;
869- return Status_Error (msg.str ());
905+ throw ConfigException (msg.str ());
870906 }
871907 }
872908
@@ -970,7 +1006,7 @@ optional<T> Config::get_internal(const std::string& key) const {
9701006 if (status.ok ()) {
9711007 return {converted_value};
9721008 }
973- throw_config_exception (
1009+ throw ConfigException (
9741010 " Failed to parse config value '" + std::string (value.value ()) +
9751011 " ' for key '" + key + " '. Reason: " + status.to_string ());
9761012 }
@@ -988,7 +1024,7 @@ optional<std::string> Config::get_internal_string(
9881024 }
9891025
9901026 if constexpr (must_find_) {
991- throw_config_exception (" Failed to get config value for key: " + key);
1027+ throw ConfigException (" Failed to get config value for key: " + key);
9921028 }
9931029 return {nullopt };
9941030}
0 commit comments