Skip to content

Commit d63ec27

Browse files
SNOW-999076: Easy Logging fixes (#1030)
1 parent 7b3319d commit d63ec27

7 files changed

+330
-65
lines changed

client_configuration.go

+73-19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"os"
1010
"path"
11+
"runtime"
1112
"strings"
1213
)
1314

@@ -26,39 +27,47 @@ const (
2627
clientConfEnvName = "SF_CLIENT_CONFIG_FILE"
2728
)
2829

29-
func getClientConfig(filePathFromConnectionString string) (*ClientConfig, error) {
30-
configPredefinedFilePaths := clientConfigPredefinedDirs()
31-
filePath := findClientConfigFilePath(filePathFromConnectionString, configPredefinedFilePaths)
30+
func getClientConfig(filePathFromConnectionString string) (*ClientConfig, string, error) {
31+
configPredefinedDirPaths := clientConfigPredefinedDirs()
32+
filePath, err := findClientConfigFilePath(filePathFromConnectionString, configPredefinedDirPaths)
33+
if err != nil {
34+
return nil, "", err
35+
}
3236
if filePath == "" { // we did not find a config file
33-
return nil, nil
37+
return nil, "", nil
3438
}
35-
return parseClientConfiguration(filePath)
39+
config, err := parseClientConfiguration(filePath)
40+
return config, filePath, err
3641
}
3742

38-
func findClientConfigFilePath(filePathFromConnectionString string, configPredefinedDirs []string) string {
43+
func findClientConfigFilePath(filePathFromConnectionString string, configPredefinedDirs []string) (string, error) {
3944
if filePathFromConnectionString != "" {
40-
return filePathFromConnectionString
45+
logger.Infof("Using client configuration path from a connection string: %s", filePathFromConnectionString)
46+
return filePathFromConnectionString, nil
4147
}
4248
envConfigFilePath := os.Getenv(clientConfEnvName)
4349
if envConfigFilePath != "" {
44-
return envConfigFilePath
50+
logger.Infof("Using client configuration path from an environment variable: %s", envConfigFilePath)
51+
return envConfigFilePath, nil
4552
}
4653
return searchForConfigFile(configPredefinedDirs)
4754
}
4855

49-
func searchForConfigFile(directories []string) string {
56+
func searchForConfigFile(directories []string) (string, error) {
5057
for _, dir := range directories {
5158
filePath := path.Join(dir, defaultConfigName)
5259
exists, err := existsFile(filePath)
5360
if err != nil {
54-
logger.Errorf("Error while searching for the client config in %s directory: %s", dir, err)
55-
continue
61+
return "", fmt.Errorf("error while searching for client config in directory: %s, err: %s", dir, err)
5662
}
5763
if exists {
58-
return filePath
64+
logger.Infof("Using client configuration from a default directory: %s", filePath)
65+
return filePath, nil
5966
}
67+
logger.Debugf("No client config found in directory: %s", dir)
6068
}
61-
return ""
69+
logger.Info("No client config file found in default directories")
70+
return "", nil
6271
}
6372

6473
func existsFile(filePath string) (bool, error) {
@@ -75,10 +84,10 @@ func existsFile(filePath string) (bool, error) {
7584
func clientConfigPredefinedDirs() []string {
7685
homeDir, err := os.UserHomeDir()
7786
if err != nil {
78-
logger.Warnf("Home dir could not be determined: %w", err)
79-
return []string{".", os.TempDir()}
87+
logger.Warnf("Unable to access Home directory for client configuration search, err: %v", err)
88+
return []string{"."}
8089
}
81-
return []string{".", homeDir, os.TempDir()}
90+
return []string{".", homeDir}
8291
}
8392

8493
// ClientConfig config root
@@ -100,18 +109,47 @@ func parseClientConfiguration(filePath string) (*ClientConfig, error) {
100109
if err != nil {
101110
return nil, parsingClientConfigError(err)
102111
}
112+
err = validateCfgPerm(filePath)
113+
if err != nil {
114+
return nil, parsingClientConfigError(err)
115+
}
103116
var clientConfig ClientConfig
104117
err = json.Unmarshal(fileContents, &clientConfig)
105118
if err != nil {
106119
return nil, parsingClientConfigError(err)
107120
}
121+
unknownValues := getUnknownValues(fileContents)
122+
if len(unknownValues) > 0 {
123+
for val := range unknownValues {
124+
logger.Warnf("Unknown configuration entry: %s with value: %s", val, unknownValues[val])
125+
}
126+
}
108127
err = validateClientConfiguration(&clientConfig)
109128
if err != nil {
110129
return nil, parsingClientConfigError(err)
111130
}
112131
return &clientConfig, nil
113132
}
114133

134+
func getUnknownValues(fileContents []byte) map[string]interface{} {
135+
var values map[string]interface{}
136+
err := json.Unmarshal(fileContents, &values)
137+
if err != nil {
138+
return nil
139+
}
140+
if values["common"] == nil {
141+
return nil
142+
}
143+
commonValues := values["common"].(map[string]interface{})
144+
lowercaseCommonValues := make(map[string]interface{}, len(commonValues))
145+
for k, v := range commonValues {
146+
lowercaseCommonValues[strings.ToLower(k)] = v
147+
}
148+
delete(lowercaseCommonValues, "log_level")
149+
delete(lowercaseCommonValues, "log_path")
150+
return lowercaseCommonValues
151+
}
152+
115153
func parsingClientConfigError(err error) error {
116154
return fmt.Errorf("parsing client config failed: %w", err)
117155
}
@@ -129,14 +167,30 @@ func validateClientConfiguration(clientConfig *ClientConfig) error {
129167
func validateLogLevel(clientConfig ClientConfig) error {
130168
var logLevel = clientConfig.Common.LogLevel
131169
if logLevel != "" {
132-
_, error := toLogLevel(logLevel)
133-
if error != nil {
134-
return error
170+
_, err := toLogLevel(logLevel)
171+
if err != nil {
172+
return err
135173
}
136174
}
137175
return nil
138176
}
139177

178+
func validateCfgPerm(filePath string) error {
179+
if runtime.GOOS == "windows" {
180+
return nil
181+
}
182+
stat, err := os.Stat(filePath)
183+
if err != nil {
184+
return err
185+
}
186+
perm := stat.Mode()
187+
// Check if group (5th LSB) or others (2nd LSB) have a write permission to the file
188+
if perm&(1<<4) != 0 || perm&(1<<1) != 0 {
189+
return fmt.Errorf("configuration file: %s can be modified by group or others", filePath)
190+
}
191+
return nil
192+
}
193+
140194
func toLogLevel(logLevelString string) (string, error) {
141195
var logLevel = strings.ToUpper(logLevelString)
142196
switch logLevel {

client_configuration_test.go

+85-11
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ func TestFindConfigFileFromConnectionParameters(t *testing.T) {
1818
createFile(t, defaultConfigName, "random content", dirs.predefinedDir1)
1919
createFile(t, defaultConfigName, "random content", dirs.predefinedDir2)
2020

21-
clientConfigFilePath := findClientConfigFilePath(connParameterConfigPath, predefinedTestDirs(dirs))
21+
clientConfigFilePath, err := findClientConfigFilePath(connParameterConfigPath, predefinedTestDirs(dirs))
2222

23+
assertEqualE(t, err, nil)
2324
assertEqualE(t, clientConfigFilePath, connParameterConfigPath, "config file path")
2425
}
2526

@@ -30,8 +31,9 @@ func TestFindConfigFileFromEnvVariable(t *testing.T) {
3031
createFile(t, defaultConfigName, "random content", dirs.predefinedDir1)
3132
createFile(t, defaultConfigName, "random content", dirs.predefinedDir2)
3233

33-
clientConfigFilePath := findClientConfigFilePath("", predefinedTestDirs(dirs))
34+
clientConfigFilePath, err := findClientConfigFilePath("", predefinedTestDirs(dirs))
3435

36+
assertEqualE(t, err, nil)
3537
assertEqualE(t, clientConfigFilePath, envConfigPath, "config file path")
3638
}
3739

@@ -40,8 +42,9 @@ func TestFindConfigFileFromFirstPredefinedDir(t *testing.T) {
4042
configPath := createFile(t, defaultConfigName, "random content", dirs.predefinedDir1)
4143
createFile(t, defaultConfigName, "random content", dirs.predefinedDir2)
4244

43-
clientConfigFilePath := findClientConfigFilePath("", predefinedTestDirs(dirs))
45+
clientConfigFilePath, err := findClientConfigFilePath("", predefinedTestDirs(dirs))
4446

47+
assertEqualE(t, err, nil)
4548
assertEqualE(t, clientConfigFilePath, configPath, "config file path")
4649
}
4750

@@ -50,8 +53,9 @@ func TestFindConfigFileFromSubsequentDirectoryIfNotFoundInPreviousOne(t *testing
5053
createFile(t, "wrong_file_name.json", "random content", dirs.predefinedDir1)
5154
configPath := createFile(t, defaultConfigName, "random content", dirs.predefinedDir2)
5255

53-
clientConfigFilePath := findClientConfigFilePath("", predefinedTestDirs(dirs))
56+
clientConfigFilePath, err := findClientConfigFilePath("", predefinedTestDirs(dirs))
5457

58+
assertEqualE(t, err, nil)
5559
assertEqualE(t, clientConfigFilePath, configPath, "config file path")
5660
}
5761

@@ -60,8 +64,9 @@ func TestNotFindConfigFileWhenNotDefined(t *testing.T) {
6064
createFile(t, "wrong_file_name.json", "random content", dirs.predefinedDir1)
6165
createFile(t, "wrong_file_name.json", "random content", dirs.predefinedDir2)
6266

63-
clientConfigFilePath := findClientConfigFilePath("", predefinedTestDirs(dirs))
67+
clientConfigFilePath, err := findClientConfigFilePath("", predefinedTestDirs(dirs))
6468

69+
assertEqualE(t, err, nil)
6570
assertEqualE(t, clientConfigFilePath, "", "config file path")
6671
}
6772

@@ -71,10 +76,9 @@ func TestCreatePredefinedDirs(t *testing.T) {
7176

7277
locations := clientConfigPredefinedDirs()
7378

74-
assertEqualF(t, len(locations), 3, "size")
79+
assertEqualF(t, len(locations), 2, "size")
7580
assertEqualE(t, locations[0], ".", "driver directory")
7681
assertEqualE(t, locations[1], homeDir, "home directory")
77-
assertEqualE(t, locations[2], os.TempDir(), "temp directory")
7882
}
7983

8084
func TestGetClientConfig(t *testing.T) {
@@ -84,7 +88,7 @@ func TestGetClientConfig(t *testing.T) {
8488
createFile(t, fileName, configContents, dir)
8589
filePath := path.Join(dir, fileName)
8690

87-
clientConfigFilePath, err := getClientConfig(filePath)
91+
clientConfigFilePath, _, err := getClientConfig(filePath)
8892

8993
assertNilF(t, err)
9094
assertNotNilF(t, clientConfigFilePath)
@@ -93,7 +97,7 @@ func TestGetClientConfig(t *testing.T) {
9397
}
9498

9599
func TestNoResultForGetClientConfigWhenNoFileFound(t *testing.T) {
96-
clientConfigFilePath, err := getClientConfig("")
100+
clientConfigFilePath, _, err := getClientConfig("")
97101

98102
assertNilF(t, err)
99103
assertNilF(t, clientConfigFilePath)
@@ -223,6 +227,76 @@ func TestParseConfigurationFails(t *testing.T) {
223227
}
224228
}
225229

230+
func TestUnknownValues(t *testing.T) {
231+
testCases := []struct {
232+
testName string
233+
inputString string
234+
expectedOutput map[string]string
235+
}{
236+
{
237+
testName: "EmptyCommon",
238+
inputString: `{
239+
"common": {}
240+
}`,
241+
expectedOutput: map[string]string{},
242+
},
243+
{
244+
testName: "CommonMissing",
245+
inputString: `{
246+
}`,
247+
expectedOutput: map[string]string{},
248+
},
249+
{
250+
testName: "UnknownProperty",
251+
inputString: `{
252+
"common": {
253+
"unknown_key": "unknown_value"
254+
}
255+
}`,
256+
expectedOutput: map[string]string{
257+
"unknown_key": "unknown_value",
258+
},
259+
},
260+
{
261+
testName: "KnownAndUnknownProperty",
262+
inputString: `{
263+
"common": {
264+
"lOg_level": "level",
265+
"log_PATH": "path",
266+
"unknown_key": "unknown_value"
267+
}
268+
}`,
269+
expectedOutput: map[string]string{
270+
"unknown_key": "unknown_value",
271+
},
272+
},
273+
{
274+
testName: "KnownProperties",
275+
inputString: `{
276+
"common": {
277+
"log_level": "level",
278+
"log_path": "path"
279+
}
280+
}`,
281+
expectedOutput: map[string]string{},
282+
},
283+
284+
{
285+
testName: "EmptyInput",
286+
inputString: "",
287+
expectedOutput: map[string]string{},
288+
},
289+
}
290+
291+
for _, tc := range testCases {
292+
t.Run(tc.testName, func(t *testing.T) {
293+
inputBytes := []byte(tc.inputString)
294+
result := getUnknownValues(inputBytes)
295+
assertEqualE(t, fmt.Sprint(result), fmt.Sprint(tc.expectedOutput))
296+
})
297+
}
298+
}
299+
226300
func createFile(t *testing.T, fileName string, fileContents string, directory string) string {
227301
fullFileName := path.Join(directory, fileName)
228302
err := os.WriteFile(fullFileName, []byte(fileContents), 0644)
@@ -237,10 +311,10 @@ func createTestDirectories(t *testing.T) struct {
237311
} {
238312
dir := t.TempDir()
239313
predefinedDir1 := path.Join(dir, "dir1")
240-
err := os.Mkdir(predefinedDir1, 0755)
314+
err := os.Mkdir(predefinedDir1, 0700)
241315
assertNilF(t, err, "predefined dir1 error")
242316
predefinedDir2 := path.Join(dir, "dir2")
243-
err = os.Mkdir(predefinedDir2, 0755)
317+
err = os.Mkdir(predefinedDir2, 0700)
244318
assertNilF(t, err, "predefined dir2 error")
245319
return struct {
246320
dir string

connection.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -757,11 +757,10 @@ func buildSnowflakeConn(ctx context.Context, config Config) (*snowflakeConn, err
757757
queryContextCache: (&queryContextCache{}).init(),
758758
currentTimeProvider: defaultTimeProvider,
759759
}
760-
// Easy logging is temporarily disabled
761-
//err := initEasyLogging(config.ClientConfigFile)
762-
//if err != nil {
763-
// return nil, err
764-
//}
760+
err := initEasyLogging(config.ClientConfigFile)
761+
if err != nil {
762+
return nil, err
763+
}
765764
var st http.RoundTripper = SnowflakeTransport
766765
if sc.cfg.Transporter == nil {
767766
if sc.cfg.InsecureMode {

0 commit comments

Comments
 (0)