Skip to content

Commit a33f997

Browse files
Snow 1634717 configuration layer (#892)
1 parent b608860 commit a33f997

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

lib/configuration/client_configuration.js

+46-8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ function getDefaultDirectories() {
2424
const directories = [];
2525

2626
const driverDirectory = getDriverDirectory();
27+
Logger.getInstance().debug(`Detected driver directory: ${driverDirectory}`);
2728

2829
if (driverDirectory) {
2930
directories.push(
@@ -37,6 +38,7 @@ function getDefaultDirectories() {
3738
}
3839

3940
const homedir = os.homedir();
41+
Logger.getInstance().debug(`Detected home directory: ${homedir}`);
4042

4143
if (exists(homedir)) {
4244
directories.push(
@@ -46,9 +48,10 @@ function getDefaultDirectories() {
4648
}
4749
);
4850
} else {
49-
Logger.getInstance().warn('Home directory of the user is not present');
51+
Logger.getInstance().warn('Home directory of the user is not defined');
5052
}
5153

54+
Logger.getInstance().debug(`Detected default directories: ${driverDirectory}`);
5255
return directories;
5356
}
5457

@@ -91,6 +94,8 @@ class ConfigurationError extends Error {
9194
function levelFromString(value) {
9295
const level = value.toUpperCase();
9396
if (!allLevels.includes(level)) {
97+
98+
Logger.getInstance().error(`Tried to create unsupported log level from string: ${value}`);
9499
throw new Error('Unknown log level: ' + value);
95100
}
96101
return level;
@@ -110,46 +115,69 @@ function ConfigurationUtil(fsPromisesModule, processModule) {
110115
* @return {Promise<ClientConfig>} Client configuration.
111116
*/
112117
this.getClientConfig = async function (configFilePath) {
118+
Logger.getInstance().debug('Retrieving client config');
119+
113120
const path = await findConfig(configFilePath);
114121
if (!exists(path) || path === '') {
122+
Logger.getInstance().info('No config file path found. Client config will not be used.');
115123
return null;
116124
}
117125

118126
const isFileOk = await isFileNotWritableByGroupOrOthers(path, fsPromises).catch(err => {
127+
Logger.getInstance().warn('Failed to inspect config file path permissions. Client config will not be used.');
119128
throw new ConfigurationError('Finding client configuration failed', err);
120129
});
121130

122131
if (!isFileOk) {
132+
Logger.getInstance().warn(`Config file path permissions are invalid. File: ${path} can be modified by group or others. Client config will not be used.`);
123133
throw new ConfigurationError(`Configuration file: ${path} can be modified by group or others`, 'IncorrectPerms');
124134
}
135+
Logger.getInstance().debug(`Config file path permissions are valid. Path: ${path}`);
125136

126137
const configFileContents = await readFileConfig(path);
138+
Logger.getInstance().info('Using client configuration from path: %s', path);
139+
127140
return configFileContents == null ? null : parseConfigFile(path, configFileContents);
128141
};
129142

130143
function readFileConfig(filePath) {
144+
Logger.getInstance().debug(`Reading config file. Path: ${filePath}`);
145+
131146
if (!filePath) {
147+
Logger.getInstance().trace(`Path of config file is not specified. Nothing to read. Path: ${filePath}`);
132148
return Promise.resolve(null);
133149
}
134150
return fsPromises.readFile(filePath, { encoding: 'utf8' })
135151
.catch(err => {
152+
Logger.getInstance().debug(`Reading configuration from the file failed. Path: ${filePath}`);
136153
throw new ConfigurationError('Finding client configuration failed', err);
137154
});
138155
}
139156

140157
function parseConfigFile(path, configurationJson) {
158+
Logger.getInstance().debug('Parsing config file: %s', path);
141159
try {
142160
const parsedConfiguration = JSON.parse(configurationJson);
161+
Logger.getInstance().trace('Config file contains correct JSON structure. Validating the input.');
162+
143163
checkUnknownEntries(parsedConfiguration);
144164
validate(parsedConfiguration);
145-
return new ClientConfig(
165+
166+
Logger.getInstance().debug('Config file contains valid configuration input.');
167+
168+
const clientConfig = new ClientConfig(
146169
path,
147170
new ClientLoggingConfig(
148171
getLogLevel(parsedConfiguration),
149172
getLogPath(parsedConfiguration)
150173
)
151174
);
175+
176+
Logger.getInstance().info('Client Configuration created with Log Level: %s and Log Path: %s', clientConfig.loggingConfig.logLevel, clientConfig.loggingConfig.logPath);
177+
return clientConfig;
178+
152179
} catch (err) {
180+
Logger.getInstance().error('Parsing client configuration failed. Used config file from path: %s', path);
153181
throw new ConfigurationError('Parsing client configuration failed', err);
154182
}
155183
}
@@ -170,21 +198,27 @@ function ConfigurationUtil(fsPromisesModule, processModule) {
170198
function validateLogLevel(configuration) {
171199
const logLevel = getLogLevel(configuration);
172200
if (logLevel == null) {
201+
Logger.getInstance().debug('Log level is not specified.');
173202
return;
174203
}
175204
if (!isString(logLevel)) {
176-
throw new Error('Log level is not a string');
205+
const errorMessage = 'Log level is not a string.';
206+
Logger.getInstance().error(errorMessage);
207+
throw new Error(errorMessage);
177208
}
178209
levelFromString(logLevel);
179210
}
180211

181212
function validateLogPath(configuration) {
182213
const logPath = getLogPath(configuration);
183214
if (logPath == null) {
215+
Logger.getInstance().debug('Log path is not specified');
184216
return;
185217
}
186218
if (!isString(logPath)) {
187-
throw new Error('Log path is not a string');
219+
const errorMessage = 'Log path is not a string.';
220+
Logger.getInstance().error(errorMessage);
221+
throw new Error(errorMessage);
188222
}
189223
}
190224

@@ -197,21 +231,22 @@ function ConfigurationUtil(fsPromisesModule, processModule) {
197231
}
198232

199233
async function findConfig(filePathFromConnectionString) {
234+
Logger.getInstance().trace(`findConfig() called with param: ${filePathFromConnectionString}`);
200235
if (exists(filePathFromConnectionString)) {
201-
Logger.getInstance().info('Using client configuration path from a connection string: %s', filePathFromConnectionString);
236+
Logger.getInstance().info('Found client configuration path in a connection string. Path: %s', filePathFromConnectionString);
202237
return filePathFromConnectionString;
203238
}
204239
const filePathFromEnvVariable = await getFilePathFromEnvironmentVariable();
205240
if (exists(filePathFromEnvVariable)) {
206-
Logger.getInstance().info('Using client configuration path from an environment variable: %s', filePathFromEnvVariable);
241+
Logger.getInstance().info('Found client configuration path in an environment variable. Path: %s', filePathFromEnvVariable);
207242
return filePathFromEnvVariable;
208243
}
209244
const fileFromDefDirs = await searchForConfigInDefaultDirectories();
210245
if (exists(fileFromDefDirs)) {
211-
Logger.getInstance().info('Using client configuration path from %s directory: %s', fileFromDefDirs.dirDescription, fileFromDefDirs.configPath);
246+
Logger.getInstance().info('Found client configuration path in %s directory. Path: %s', fileFromDefDirs.dirDescription, fileFromDefDirs.configPath);
212247
return fileFromDefDirs.configPath;
213248
}
214-
Logger.getInstance().info('No client config file found in default directories');
249+
Logger.getInstance().info('No client config detected.');
215250
return null;
216251
}
217252

@@ -224,12 +259,15 @@ function ConfigurationUtil(fsPromisesModule, processModule) {
224259
}
225260

226261
async function searchForConfigInDefaultDirectories() {
262+
Logger.getInstance().debug(`Searching for config in default directories: ${defaultDirectories}`);
227263
for (const directory of defaultDirectories) {
228264
const configPath = await searchForConfigInDictionary(directory.dir, directory.dirDescription);
229265
if (exists(configPath)) {
266+
Logger.getInstance().debug(`Config found in the default directory: ${directory.dir}. Path: ${configPath}`);
230267
return { configPath: configPath, dirDescription: directory.dirDescription };
231268
}
232269
}
270+
Logger.getInstance().debug('Unable to find config in any default directory.');
233271
return null;
234272
}
235273

lib/configuration/connection_configuration.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,45 @@ function readTokenFromFile(fixedConfiguration) {
3232
validateOnlyUserReadWritePermission(resolvedPath);
3333
fixedConfiguration.token = fs.readFileSync(resolvedPath, 'utf-8').trim();
3434
if (!fixedConfiguration.token) {
35+
Logger.getInstance().error('The token does not exist or has empty value.');
3536
throw new Error('The token does not exist or has empty value');
3637
}
3738
const tokenChecksum = generateChecksum(fixedConfiguration.token);
3839
Logger.getInstance().info('Token used in connection has been read from file: %s. Checksum: %s', resolvedPath, tokenChecksum);
3940
}
4041

4142
function loadConnectionConfiguration() {
43+
Logger.getInstance().trace('Loading connection configuration from the local files...');
4244
const snowflakeConfigDir = defaultIfNotSet(process.env.SNOWFLAKE_HOME, path.join(os.homedir(), '.snowflake'));
45+
Logger.getInstance().trace('Looking for connection file in directory %s', snowflakeConfigDir);
4346
const filePath = path.join(snowflakeConfigDir, 'connections.toml');
4447
const resolvedPath = fs.realpathSync(filePath);
48+
Logger.getInstance().trace('Connection configuration file found under the path %s. Validating file access.', resolvedPath);
49+
4550
validateOnlyUserReadWritePermission(resolvedPath);
4651
const str = fs.readFileSync(resolvedPath, { encoding: 'utf8' });
4752
const configurationChecksum = generateChecksum(str);
48-
Logger.getInstance().info('Connection configuration file is read from file: %s. Checksum: %s', resolvedPath, configurationChecksum);
53+
Logger.getInstance().info('Connection configuration file is read from path: %s. Checksum: %s', resolvedPath, configurationChecksum);
54+
Logger.getInstance().trace('Trying to parse the config file');
4955
const parsingResult = toml.parse(str);
56+
5057
const configurationName = defaultIfNotSet(process.env.SNOWFLAKE_DEFAULT_CONNECTION_NAME, 'default');
5158

5259
if (parsingResult[configurationName] !== undefined) {
5360
const fixedConfiguration = fixUserKey(parsingResult[configurationName]);
5461
if (shouldReadTokenFromFile(fixedConfiguration)) {
62+
Logger.getInstance().info('Trying to read token from config file.');
5563
readTokenFromFile(fixedConfiguration);
5664
}
5765
return fixedConfiguration;
5866
} else {
67+
Logger.getInstance().error('Connection configuration with name %s does not exist in the file %s', configurationName, resolvedPath);
5968
throw new Error(`Connection configuration with name ${configurationName} does not exist`);
6069
}
6170
}
6271

6372
function fixUserKey(parsingResult) {
73+
Logger.getInstance().trace('Empty Username field will be filled with \'User\' field value.');
6474
if (parsingResult['username'] === undefined && parsingResult['user'] !== undefined){
6575
parsingResult['username'] = parsingResult['user'];
6676
}

0 commit comments

Comments
 (0)