Skip to content

Commit 2eff4fc

Browse files
committed
Use braces syntax instead of Makefile syntax
1 parent d68c2d5 commit 2eff4fc

File tree

4 files changed

+82
-16
lines changed

4 files changed

+82
-16
lines changed

conf/lex.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,18 @@ func (lx *lexer) isVariable() bool {
900900
return false
901901
}
902902

903+
// Check if the unquoted string is a variable reference with braces
904+
func (lx *lexer) isVariableWithBraces() bool {
905+
if lx.start >= len(lx.input) {
906+
return false
907+
}
908+
if len(lx.input) > 3 && lx.input[lx.start:lx.start+2] == "${" {
909+
lx.start += 2
910+
return true
911+
}
912+
return false
913+
}
914+
903915
// lexQuotedString consumes the inner contents of a string. It assumes that the
904916
// beginning '"' has already been consumed and ignored. It will not interpret any
905917
// internal contents.
@@ -964,6 +976,14 @@ func lexString(lx *lexer) stateFn {
964976
lx.emitString()
965977
} else if lx.isBool() {
966978
lx.emit(itemBool)
979+
} else if lx.isVariableWithBraces() {
980+
lx.emit(itemVariable)
981+
982+
// consume the trailing '}'
983+
if lx.pos < len(lx.input) && lx.input[lx.pos] == '}' {
984+
lx.next()
985+
lx.ignore()
986+
}
967987
} else if lx.isVariable() {
968988
lx.emit(itemVariable)
969989
} else {

conf/lex_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,14 @@ func TestVariableValues(t *testing.T) {
531531
}
532532
lx = lex("foo $bar")
533533
expect(t, lx, expectedItems)
534+
535+
expectedItems = []item{
536+
{itemKey, "foo", 1, 0},
537+
{itemVariable, "bar", 1, 8},
538+
{itemEOF, "", 1, 0},
539+
}
540+
lx = lex("foo = ${bar}")
541+
expect(t, lx, expectedItems)
534542
}
535543

536544
func TestArrays(t *testing.T) {
@@ -711,6 +719,22 @@ func TestNestedMaps(t *testing.T) {
711719
expect(t, lx, expectedItems)
712720
}
713721

722+
func TestSimpleMapWithVariable(t *testing.T) {
723+
expectedItems := []item{
724+
{itemKey, "foo", 1, 0},
725+
{itemMapStart, "", 1, 7},
726+
{itemKey, "ip", 1, 7},
727+
{itemVariable, "IP", 1, 12},
728+
{itemKey, "port", 1, 17},
729+
{itemVariable, "PORT", 1, 26},
730+
{itemMapEnd, "", 1, 32},
731+
{itemEOF, "", 1, 0},
732+
}
733+
734+
lx := lex("foo = {ip=${IP}, port = ${PORT}}")
735+
expect(t, lx, expectedItems)
736+
}
737+
714738
func TestQuotedKeys(t *testing.T) {
715739
expectedItems := []item{
716740
{itemKey, "foo", 1, 0},

conf/parse.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,10 @@ func (p *parser) processItem(it item, fp string) error {
288288
setValue(it, p.popContext())
289289
case itemString:
290290
// FIXME(dlc) sanitize string?
291-
p.checkForEmbeddedVariables(&it)
291+
err := p.checkForEmbeddedVariables(&it)
292+
if err != nil {
293+
return err
294+
}
292295
setValue(it, it.val)
293296
case itemInteger:
294297
lastDigit := 0
@@ -433,17 +436,18 @@ const pkey = "pk"
433436
const bcryptPrefix = "2a$"
434437

435438
// To match embedded variables.
436-
var varPat = regexp.MustCompile(`\$\$[^@\s]+`)
439+
var varPat = regexp.MustCompile(`\$\{[^@\s]+\}`)
437440

438441
// checkForEmbeddedVariable will check for embedded variables in an itemString.
439442
// If they are found and we can look them up we will replace them in item, otherwise will error.
440443
func (p *parser) checkForEmbeddedVariables(it *item) error {
441-
if !strings.ContainsAny(it.val, "$$") {
444+
if !strings.ContainsAny(it.val, "${") {
442445
return nil
443446
}
444447
// We have some embedded variables.
445448
for _, m := range varPat.FindAllString(it.val, -1) {
446-
value, found, err := p.lookupVariable(m[2:]) // Strip leading $$ for lookup.
449+
ref := m[2 : len(m)-1] // Strip leading ${ and trailing }
450+
value, found, err := p.lookupVariable(ref)
447451
if err != nil {
448452
return fmt.Errorf("variable reference for '%s' on line %d could not be parsed: %s",
449453
m, it.line, err)

conf/parse_test.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ func TestSimpleVariable(t *testing.T) {
8484
test(t, varSample, ex)
8585
}
8686

87+
var varSampleWithBraces = `
88+
index = 22
89+
foo = ${index}
90+
`
91+
92+
func TestSimpleVariableWithBraces(t *testing.T) {
93+
ex := map[string]any{
94+
"index": int64(22),
95+
"foo": int64(22),
96+
}
97+
test(t, varSampleWithBraces, ex)
98+
}
99+
87100
var varNestedSample = `
88101
index = 22
89102
nest {
@@ -113,6 +126,14 @@ func TestMissingVariable(t *testing.T) {
113126
if !strings.HasPrefix(err.Error(), "variable reference") {
114127
t.Fatalf("Wanted a variable reference err, got %q\n", err)
115128
}
129+
130+
_, err = Parse("foo=${index}")
131+
if err == nil {
132+
t.Fatalf("Expected an error for a missing variable, got none")
133+
}
134+
if !strings.HasPrefix(err.Error(), "variable reference") {
135+
t.Fatalf("Wanted a variable reference err, got %q\n", err)
136+
}
116137
}
117138

118139
func TestEnvVariable(t *testing.T) {
@@ -173,11 +194,9 @@ func TestEnvVariableEmbedded(t *testing.T) {
173194
TOKEN: abc
174195
authorization {
175196
user: user
176-
# normal variable syntax
177-
password: $TOKEN
197+
password: "${TOKEN}"
178198
}
179-
# embedded variable syntax
180-
routes = [ nats://user:[email protected]:6222 ]
199+
routes = [ "nats://user:${TOKEN}@server.example.com:6222" ]
181200
}`
182201
ex := map[string]any{
183202
"cluster": map[string]any{
@@ -211,11 +230,8 @@ func TestEnvVariableEmbeddedMissing(t *testing.T) {
211230
cluster {
212231
authorization {
213232
user: user
214-
# normal variable syntax
215-
password: $TOKEN
233+
password: ${TOKEN}
216234
}
217-
# embedded variable syntax
218-
routes = [ nats://user:[email protected]:6222 ]
219235
}`
220236

221237
_, err := Parse(cluster)
@@ -227,13 +243,15 @@ func TestEnvVariableEmbeddedMissing(t *testing.T) {
227243
func TestEnvVariableEmbeddedOutsideOfQuotes(t *testing.T) {
228244
cluster := `
229245
cluster {
246+
# set the variable token
247+
TOKEN: abc
230248
authorization {
231249
user: user
232-
# invalid embedded variable syntax
233-
password: $$TOKEN
250+
# ok
251+
password: ${TOKEN}
234252
}
235-
# embedded variable syntax
236-
routes = [ nats://user:$$[email protected]:6222 ]
253+
# not ok
254+
routes = [ nats://user:${TOKEN}@server.example.com:6222 ]
237255
}`
238256

239257
_, err := Parse(cluster)

0 commit comments

Comments
 (0)