diff --git a/parser/helpers.go b/parser/helpers.go index 15a74f8..d994aca 100644 --- a/parser/helpers.go +++ b/parser/helpers.go @@ -111,9 +111,35 @@ func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error // Sets the value at a specific pathway, but checks if we were looking for a specific // value or not before doing it. func (cfr *ConfigurationFileReplacement) SetAtPathway(c *gabs.Container, path string, value []byte) error { - if cfr.IfValue != nil { - if !c.Exists(path) || (c.Exists(path) && !bytes.Equal(c.Bytes(), []byte(*cfr.IfValue))) { + if cfr.IfValue != "" { + // If this is a regex based matching, we need to get a little more creative since + // we're only going to replacing part of the string, and not the whole thing. + if c.Exists(path) && strings.HasPrefix(cfr.IfValue, "regex:") { + // We're doing some regex here. + r, err := regexp.Compile(strings.TrimPrefix(cfr.IfValue, "regex:")) + if err != nil { + zap.S().Warnw( + "configuration if_value using invalid regexp, cannot do replacement", + zap.String("if_value", strings.TrimPrefix(cfr.IfValue, "regex:")), + zap.Error(err), + ) + return nil + } + + // If the path exists and there is a regex match, go ahead and attempt the replacement + // using the value we got from the key. This will only replace the one match. + v := strings.Trim(string(c.Path(path).Bytes()), "\"") + if r.Match([]byte(v)) { + _, err := c.SetP(r.ReplaceAllString(v, string(value)), path) + + return err + } + return nil + } else { + if !c.Exists(path) || (c.Exists(path) && !bytes.Equal(c.Bytes(), []byte(cfr.IfValue))) { + return nil + } } } @@ -154,7 +180,7 @@ func (f *ConfigurationFile) LookupConfigurationValue(cfr ConfigurationFileReplac return match, errors.WithStack(err) } - zap.S().Warnw( + zap.S().Debugw( "attempted to load a configuration value that does not exist", zap.Strings("path", path), zap.String("filename", f.FileName), @@ -162,7 +188,7 @@ func (f *ConfigurationFile) LookupConfigurationValue(cfr ConfigurationFileReplac // If there is no key, keep the original value intact, that way it is obvious there // is a replace issue at play. - return cfr.ReplaceWith.Value(), nil + return match, nil } else { replaced := []byte(configMatchRegex.ReplaceAllString(cfr.ReplaceWith.String(), string(match))) diff --git a/parser/parser.go b/parser/parser.go index d03c343..61d63cf 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -43,26 +43,34 @@ type ConfigurationFile struct { // Defines a single find/replace instance for a given server configuration file. type ConfigurationFileReplacement struct { Match string `json:"match"` - IfValue *string `json:"if_value"` + IfValue string `json:"if_value"` ReplaceWith ReplaceValue `json:"replace_with"` } // Handles unmarshaling the JSON representation into a struct that provides more useful // data to this functionality. func (cfr *ConfigurationFileReplacement) UnmarshalJSON(data []byte) error { - if m, err := jsonparser.GetString(data, "match"); err != nil { - return err - } else { - cfr.Match = m + m, err := jsonparser.GetString(data, "match") + if err != nil { + return errors.WithStack(err) } + cfr.Match = m - if v, dt, _, err := jsonparser.Get(data, "replace_with"); err != nil { - return err - } else { - cfr.ReplaceWith = ReplaceValue{ - value: v, - valueType: dt, - } + iv, err := jsonparser.GetString(data, "if_value") + // We only check keypath here since match & replace_with should be present on all of + // them, however if_value is optional. + if err != nil && err != jsonparser.KeyPathNotFoundError { + return errors.WithStack(err) + } + cfr.IfValue = iv + + rw, dt, _, err := jsonparser.Get(data, "replace_with") + if err != nil { + return errors.WithStack(err) + } + cfr.ReplaceWith = ReplaceValue{ + value: rw, + valueType: dt, } return nil @@ -370,7 +378,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error { // Don't attempt to replace the value if we're looking for a specific value and // it does not match. If there was no match at all in the file for this key but // we're doing an IfValue match, do nothing. - if replace.IfValue != nil && (!ok || (ok && v != *replace.IfValue)) { + if replace.IfValue != "" && (!ok || (ok && v != replace.IfValue)) { continue }