Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 24 additions & 27 deletions parser/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,7 @@ func (cfr *ConfigurationFileReplacement) setValueWithSjson(jsonStr string, path
}
setValue = value
default:
if v, err := strconv.Atoi(value); err == nil {
setValue = v
} else {
setValue = value
}
setValue = value
Comment thread
gOOvER marked this conversation as resolved.
}
}

Expand All @@ -208,29 +204,30 @@ func (f *ConfigurationFile) LookupConfigurationValue(cfr ConfigurationFileReplac
// If there is a match, lookup the value in the configuration for the Daemon. If no key
// is found, just return the string representation, otherwise use the value from the
// daemon configuration here.
huntPath := configMatchRegex.ReplaceAllString(
configMatchRegex.FindString(cfr.ReplaceWith.String()), "$1",
)

var path []string
for _, value := range strings.Split(huntPath, ".") {
path = append(path, strcase.ToSnake(value))
}

// Look for the key in the configuration file, and if found return that value to the
// calling function.
match, _, _, err := jsonparser.Get(f.configuration, path...)
if err != nil {
if err != jsonparser.KeyPathNotFoundError {
return string(match), err
var lookupErr error
result := configMatchRegex.ReplaceAllStringFunc(cfr.ReplaceWith.String(), func(placeholder string) string {
if lookupErr != nil {
return placeholder
}
keyPath := configMatchRegex.ReplaceAllString(placeholder, "$1")

log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist")
var path []string
for _, part := range strings.Split(keyPath, ".") {
path = append(path, strcase.ToSnake(part))
}

// If there is no key, keep the original value intact, that way it is obvious there
// is a replace issue at play.
return string(match), nil
} else {
return configMatchRegex.ReplaceAllString(cfr.ReplaceWith.String(), string(match)), nil
}
// Look for the key in the Wings configuration and substitute the placeholder.
match, _, _, err := jsonparser.Get(f.configuration, path...)
if err != nil {
if err != jsonparser.KeyPathNotFoundError {
lookupErr = err
return placeholder
}
log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist")
// Leave placeholder intact so the misconfiguration is visible.
return placeholder
}
return string(match)
})
return result, lookupErr
}
72 changes: 65 additions & 7 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,27 @@ func (f *ConfigurationFile) UnmarshalJSON(data []byte) error {
return err
}

if err := json.Unmarshal(*m["file"], &f.FileName); err != nil {
fileRaw, ok := m["file"]
if !ok || fileRaw == nil {
return errors.New("parser: configuration file missing required 'file' key")
}
if err := json.Unmarshal(*fileRaw, &f.FileName); err != nil {
return err
}

if err := json.Unmarshal(*m["parser"], &f.Parser); err != nil {
parserRaw, ok := m["parser"]
if !ok || parserRaw == nil {
return errors.New("parser: configuration file missing required 'parser' key")
}
if err := json.Unmarshal(*parserRaw, &f.Parser); err != nil {
return err
}

if err := json.Unmarshal(*m["replace"], &f.Replace); err != nil {
log.WithField("file", f.FileName).WithField("error", err).Warn("failed to unmarshal configuration file replacement")

f.Replace = []ConfigurationFileReplacement{}
f.Replace = []ConfigurationFileReplacement{}
if replaceRaw, ok := m["replace"]; ok && replaceRaw != nil {
if err := json.Unmarshal(*replaceRaw, &f.Replace); err != nil {
log.WithField("file", f.FileName).WithField("error", err).Warn("failed to unmarshal configuration file replacement")
}
}

// test if "create_file" exists, if not just assume true
Expand Down Expand Up @@ -292,6 +301,7 @@ func (f *ConfigurationFile) parseXmlFile(file ufs.File) error {
k := xmlValueMatchRegex.ReplaceAllString(value, "$1")
v := xmlValueMatchRegex.ReplaceAllString(value, "$2")

element.RemoveAttr(k)
element.CreateAttr(k, v)
Comment thread
gOOvER marked this conversation as resolved.
} else {
element.SetText(value)
Expand Down Expand Up @@ -462,9 +472,12 @@ func (f *ConfigurationFile) parseYamlFile(file ufs.File) error {
}

var jsonData interface{}
if err := json.Unmarshal(data, &jsonData); err != nil {
yamlDecoder := json.NewDecoder(bytes.NewReader(data))
yamlDecoder.UseNumber()
if err := yamlDecoder.Decode(&jsonData); err != nil {
return err
}
jsonData = normalizeYamlTypes(jsonData)

marshaled, err := yaml.Marshal(jsonData)
if err != nil {
Expand Down Expand Up @@ -536,6 +549,43 @@ func (f *ConfigurationFile) parseTomlFile(file ufs.File) error {
return nil
}

// normalizeYamlTypes converts json.Number values (produced by UseNumber()) into
// proper Go numeric types so that yaml.Marshal writes integers as plain integers
// instead of float64 scientific notation (e.g. 1.5e+18 for large Snowflake IDs).
func normalizeYamlTypes(value interface{}) interface{} {
switch typed := value.(type) {
case map[string]interface{}:
for key, item := range typed {
typed[key] = normalizeYamlTypes(item)
}
return typed
case []interface{}:
for i := range typed {
typed[i] = normalizeYamlTypes(typed[i])
}
return typed
case json.Number:
s := typed.String()
// Preserve float representation: if the number contains '.', 'e' or 'E'
// it was originally a float and must not be coerced to int64.
if strings.ContainsAny(s, ".eE") {
if floatVal, err := typed.Float64(); err == nil {
return floatVal
}
return s
}
if intVal, err := typed.Int64(); err == nil {
return intVal
}
if floatVal, err := typed.Float64(); err == nil {
return floatVal
}
return s
default:
return value
}
}

func normalizeTomlTypes(value interface{}) interface{} {
switch typed := value.(type) {
case map[string]interface{}:
Expand Down Expand Up @@ -585,6 +635,14 @@ func (f *ConfigurationFile) parseTextFile(file ufs.File) error {
if !bytes.HasPrefix(line, []byte(replace.Match)) {
continue
}
// If an if_value is set, only replace when the remainder of the line matches.
// Trim trailing \r\n so Windows line endings do not break the comparison.
if replace.IfValue != "" {
remainder := bytes.TrimRight(bytes.TrimPrefix(line, []byte(replace.Match)), "\r\n")
if string(remainder) != replace.IfValue {
continue
}
}
b.Write(replace.ReplaceWith.Bytes())
replaced = true
}
Expand Down
Loading