Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-999076: Easy Logging fixes #1030

Merged
merged 14 commits into from
Jan 26, 2024
83 changes: 70 additions & 13 deletions client_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"fmt"
"os"
"path"
"runtime"
"strings"
)

Expand All @@ -26,21 +27,27 @@
clientConfEnvName = "SF_CLIENT_CONFIG_FILE"
)

func getClientConfig(filePathFromConnectionString string) (*ClientConfig, error) {
configPredefinedFilePaths := clientConfigPredefinedDirs()
filePath := findClientConfigFilePath(filePathFromConnectionString, configPredefinedFilePaths)
func getClientConfig(filePathFromConnectionString string) (*ClientConfig, string, error) {
defaultCfgDir := defaultConfigDirectory()
if defaultCfgDir == "" {
return nil, "", nil
}

Check warning on line 34 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L33-L34

Added lines #L33 - L34 were not covered by tests
filePath := findClientConfigFilePath(filePathFromConnectionString, []string{defaultCfgDir})
if filePath == "" { // we did not find a config file
return nil, nil
return nil, "", nil
}
return parseClientConfiguration(filePath)
config, err := parseClientConfiguration(filePath)
return config, filePath, err
}

func findClientConfigFilePath(filePathFromConnectionString string, configPredefinedDirs []string) string {
if filePathFromConnectionString != "" {
logger.Infof("Using Easy Logging configuration path from a connection string: %s", filePathFromConnectionString)
sfc-gh-pfus marked this conversation as resolved.
Show resolved Hide resolved
return filePathFromConnectionString
}
envConfigFilePath := os.Getenv(clientConfEnvName)
if envConfigFilePath != "" {
logger.Infof("Using Easy Logging configuration path from an environment variable: %s", envConfigFilePath)
return envConfigFilePath
}
return searchForConfigFile(configPredefinedDirs)
Expand All @@ -51,13 +58,15 @@
filePath := path.Join(dir, defaultConfigName)
exists, err := existsFile(filePath)
if err != nil {
logger.Errorf("Error while searching for the client config in %s directory: %s", dir, err)
logger.Debugf("No client config found in directory: %s, err: %s", dir, err)

Check warning on line 61 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L61

Added line #L61 was not covered by tests
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
continue
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
}
if exists {
logger.Infof("Using Easy Logging configuration from a default directory: %s", filePath)
return filePath
}
}
logger.Info("No Easy Logging config file found in default directories")
return ""
}

Expand All @@ -72,13 +81,13 @@
return false, err
}

func clientConfigPredefinedDirs() []string {
func defaultConfigDirectory() string {
homeDir, err := os.UserHomeDir()
if err != nil {
logger.Warnf("Home dir could not be determined: %w", err)
return []string{".", os.TempDir()}
logger.Warnf("Unable to access Home directory for Easy Logging configuration search, err: %v", err)
sfc-gh-pbulawa marked this conversation as resolved.
Show resolved Hide resolved
return ""

Check warning on line 88 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L87-L88

Added lines #L87 - L88 were not covered by tests
}
return []string{".", homeDir, os.TempDir()}
return homeDir
}

// ClientConfig config root
Expand All @@ -100,18 +109,50 @@
if err != nil {
return nil, parsingClientConfigError(err)
}
_, err = isCfgPermValid(filePath)
sfc-gh-pfus marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, parsingClientConfigError(err)
}

Check warning on line 115 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L114-L115

Added lines #L114 - L115 were not covered by tests
var clientConfig ClientConfig
err = json.Unmarshal(fileContents, &clientConfig)
if err != nil {
return nil, parsingClientConfigError(err)
}
unknownValues := getUnknownValues(fileContents)
if len(unknownValues) > 0 {
for val := range unknownValues {
logger.Warnf("Unknown configuration entry: %s with value: %s", val, unknownValues[val])
}

Check warning on line 125 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L123-L125

Added lines #L123 - L125 were not covered by tests
}
err = validateClientConfiguration(&clientConfig)
if err != nil {
return nil, parsingClientConfigError(err)
}
return &clientConfig, nil
}

func getUnknownValues(fileContents []byte) map[string]interface{} {
var values map[string]interface{}
err := json.Unmarshal(fileContents, &values)
if err != nil {
return nil
}
if values["common"] == nil {
return nil
}
commonValues := values["common"].(map[string]interface{})
lowercaseCommonValues := make(map[string]interface{}, len(commonValues))
for k, v := range commonValues {
lowercaseCommonValues[strings.ToLower(k)] = v
}
delete(lowercaseCommonValues, "log_level")
delete(lowercaseCommonValues, "log_path")
if len(lowercaseCommonValues) == 0 {
sfc-gh-pfus marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
return lowercaseCommonValues
}

func parsingClientConfigError(err error) error {
return fmt.Errorf("parsing client config failed: %w", err)
}
Expand All @@ -129,14 +170,30 @@
func validateLogLevel(clientConfig ClientConfig) error {
var logLevel = clientConfig.Common.LogLevel
if logLevel != "" {
_, error := toLogLevel(logLevel)
if error != nil {
return error
_, err := toLogLevel(logLevel)
if err != nil {
return err
}
}
return nil
}

func isCfgPermValid(filePath string) (bool, error) {
if runtime.GOOS == "windows" {
return true, nil
}
stat, err := os.Stat(filePath)
if err != nil {
return false, err
}

Check warning on line 188 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L187-L188

Added lines #L187 - L188 were not covered by tests
perm := stat.Mode()
// Check if group (5th LSB) or others (2nd LSB) have a write permission to the file
if perm&(1<<4) != 0 || perm&(1<<1) != 0 {
return false, fmt.Errorf("configuration file: %s can be modified by group or others", filePath)
}

Check warning on line 193 in client_configuration.go

View check run for this annotation

Codecov / codecov/patch

client_configuration.go#L192-L193

Added lines #L192 - L193 were not covered by tests
return true, nil
}

func toLogLevel(logLevelString string) (string, error) {
var logLevel = strings.ToUpper(logLevelString)
switch logLevel {
Expand Down
85 changes: 76 additions & 9 deletions client_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,9 @@ func TestCreatePredefinedDirs(t *testing.T) {
homeDir, err := os.UserHomeDir()
assertNilF(t, err, "get home dir error")

locations := clientConfigPredefinedDirs()
location := defaultConfigDirectory()

assertEqualF(t, len(locations), 3, "size")
assertEqualE(t, locations[0], ".", "driver directory")
assertEqualE(t, locations[1], homeDir, "home directory")
assertEqualE(t, locations[2], os.TempDir(), "temp directory")
assertEqualE(t, location, homeDir, "home directory")
}

func TestGetClientConfig(t *testing.T) {
Expand All @@ -84,7 +81,7 @@ func TestGetClientConfig(t *testing.T) {
createFile(t, fileName, configContents, dir)
filePath := path.Join(dir, fileName)

clientConfigFilePath, err := getClientConfig(filePath)
clientConfigFilePath, _, err := getClientConfig(filePath)

assertNilF(t, err)
assertNotNilF(t, clientConfigFilePath)
Expand All @@ -93,7 +90,7 @@ func TestGetClientConfig(t *testing.T) {
}

func TestNoResultForGetClientConfigWhenNoFileFound(t *testing.T) {
clientConfigFilePath, err := getClientConfig("")
clientConfigFilePath, _, err := getClientConfig("")

assertNilF(t, err)
assertNilF(t, clientConfigFilePath)
Expand Down Expand Up @@ -223,6 +220,76 @@ func TestParseConfigurationFails(t *testing.T) {
}
}

func TestUnknownValues(t *testing.T) {
testCases := []struct {
testName string
inputString string
expectedOutput map[string]string
}{
{
testName: "EmptyCommon",
inputString: `{
"common": {}
}`,
expectedOutput: nil,
},
{
testName: "CommonMissing",
inputString: `{
}`,
expectedOutput: nil,
},
{
testName: "UnknownProperty",
inputString: `{
"common": {
"unknown_key": "unknown_value"
}
}`,
expectedOutput: map[string]string{
"unknown_key": "unknown_value",
},
},
{
testName: "KnownAndUnknownProperty",
inputString: `{
"common": {
"lOg_level": "level",
"log_PATH": "path",
"unknown_key": "unknown_value"
}
}`,
expectedOutput: map[string]string{
"unknown_key": "unknown_value",
},
},
{
testName: "KnownProperties",
inputString: `{
"common": {
"log_level": "level",
"log_path": "path"
}
}`,
expectedOutput: nil,
},

{
testName: "EmptyInput",
inputString: "",
expectedOutput: nil,
},
}

for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
inputBytes := []byte(tc.inputString)
result := getUnknownValues(inputBytes)
assertEqualE(t, fmt.Sprint(result), fmt.Sprint(tc.expectedOutput))
})
}
}

func createFile(t *testing.T, fileName string, fileContents string, directory string) string {
fullFileName := path.Join(directory, fileName)
err := os.WriteFile(fullFileName, []byte(fileContents), 0644)
Expand All @@ -237,10 +304,10 @@ func createTestDirectories(t *testing.T) struct {
} {
dir := t.TempDir()
predefinedDir1 := path.Join(dir, "dir1")
err := os.Mkdir(predefinedDir1, 0755)
err := os.Mkdir(predefinedDir1, 0700)
assertNilF(t, err, "predefined dir1 error")
predefinedDir2 := path.Join(dir, "dir2")
err = os.Mkdir(predefinedDir2, 0755)
err = os.Mkdir(predefinedDir2, 0700)
assertNilF(t, err, "predefined dir2 error")
return struct {
dir string
Expand Down
9 changes: 4 additions & 5 deletions connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,11 +757,10 @@ func buildSnowflakeConn(ctx context.Context, config Config) (*snowflakeConn, err
queryContextCache: (&queryContextCache{}).init(),
currentTimeProvider: defaultTimeProvider,
}
// Easy logging is temporarily disabled
//err := initEasyLogging(config.ClientConfigFile)
//if err != nil {
// return nil, err
//}
err := initEasyLogging(config.ClientConfigFile)
if err != nil {
return nil, err
}
var st http.RoundTripper = SnowflakeTransport
if sc.cfg.Transporter == nil {
if sc.cfg.InsecureMode {
Expand Down
Loading
Loading