Skip to content

Commit

Permalink
Fixes #19943: Change format to call engines in properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaadF committed Sep 10, 2021
1 parent 1e6f022 commit 305f861
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 71 deletions.
Expand Up @@ -454,7 +454,7 @@ class InterpolatedValueCompilerImpl(p: PropertyEngineService) extends Interpolat
case None => ""
}
// should not happen since a non expanded engine property should lead to an error
s"[missing value for: $${engine.${e}[${m.mkString("][")}] ${opt}]"
s"[missing value for: $${data.${e}[${m.mkString("][")}] ${opt}]"
case Property(path, opt) => agent match {
case AgentType.Dsc =>
s"$$($$node.properties[${path.mkString("][")}])"
Expand Down Expand Up @@ -518,18 +518,17 @@ object PropertyParser {
// after "${rudder." there is no backtracking to an "otherProp" or string possible.
def rudderVariable[_: P] : P[Interpolation] = P( IgnoreCase("rudder") ~ space ~ "." ~ space ~/ (rudderNode | parameters | oldParameter) )

def rudderEngine[_: P] : P[Interpolation] = P( IgnoreCase("engine") ~ space ~ "." ~ space ~/ (rudderEngineFormat) )
def rudderEngine[_: P] : P[Interpolation] = P( (IgnoreCase("data") | IgnoreCase("rudder-data")) ~ space ~ "." ~ space ~/ (rudderEngineFormat) )

//a node path looks like: ${rudder.node.HERE.PATH}
def rudderNode[_: P] : P[Interpolation] = P( IgnoreCase("node") ~/ space ~ "." ~ space ~/ variableId.rep(sep = space ~ "." ~ space) ).map { seq => NodeAccessor(seq.toList) }

// ${engine.name[val][val2] | option1 = xxx | option2 = xxx}
// ${data.name[val][val2] | option1 = xxx | option2 = xxx}
// ${rudder-data.name[val][val2] | option1 = xxx | option2 = xxx}
def rudderEngineFormat[_: P] : P[Interpolation] = P(propertyId ~/ arrayNames ~/ engineOption.? ).map{
case (name, methods, opt) => RudderEngine(name, methods, opt)
}

// def rudderEngineArg[_: P] : P[String] = P( space ~ "(" ~/ space ~/ ("\"" | "\"\"\"") ~/ propertyId ~/ space ~/ ("\"" | "\"\"\"") ~ space ~ ")" ~ space)

//a parameter old syntax looks like: ${rudder.param.PARAM_NAME}
def oldParameter[_: P] : P[Interpolation] = P(IgnoreCase("param") ~ space ~ "." ~/ space ~/ variableId).map{ p => Param(p :: Nil) }

Expand Down
Expand Up @@ -274,74 +274,81 @@ class TestNodeAndGlobalParameterLookup extends Specification {
}

"parse a valid engine" in {
test(
all(_)
, """${engine.test[foo]}"""
, List(RudderEngine("test", List("foo"), None))
)
val s = """${data.test[foo]}"""
val s2 = """${rudder-data.test[foo]}"""
val res = RudderEngine("test", List("foo"), None)
test(all(_), s, List(res)) and
test(all(_), s2, List(res))
}

"parse a valid engine with methods" in {
test(
all(_)
, """${engine.test[foo][bar]}"""
, List(RudderEngine("test", List("foo", "bar"), None))
)
val s = """${data.test[foo][bar]}"""
val s2 = """${rudder-data.test[foo][bar]}"""
val res = RudderEngine("test", List("foo", "bar"), None)
test(all(_), s, List(res)) and
test(all(_), s2, List(res))
}

"parse a valid engine with options" in {
test(
all(_)
, """${engine.test[foo] | option1 = boo | option2 = baz}"""
, List(RudderEngine("test", List("foo"), Some(List(EngineOption("option1", "boo"), EngineOption("option2", "baz")))))
)
val s = """${data.test[foo] | option1 = boo | option2 = baz}"""
val s2 = """${rudder-data.test[foo] | option1 = boo | option2 = baz}"""
val res = RudderEngine("test", List("foo"), Some(List(EngineOption("option1", "boo"), EngineOption("option2", "baz"))))
test(all(_), s, List(res)) and
test(all(_), s2, List(res))
}

"parse an engine with space" in {
test(
all(_)
, """${engine . test [ foo ] [ bar] |option1 = tac | option2 = toc }"""
, List(RudderEngine("test", List("foo", "bar"), Some(List(EngineOption("option1", "tac"), EngineOption("option2", "toc")))))
)
val s = """${data . test [ foo ] [ bar] |option1 = tac | option2 = toc }"""
val s2 = """${rudder-data . test [ foo ] [ bar] |option1 = tac | option2 = toc }"""
val res = RudderEngine("test", List("foo", "bar"), Some(List(EngineOption("option1", "tac"), EngineOption("option2", "toc"))))
test(all(_), s, List(res)) and
test(all(_), s2, List(res))
}

"parse an engine with multiple method" in {
test(
all(_)
, """${engine.test[foo][bar][baz]}"""
, List(RudderEngine("test", List("foo", "bar", "baz"), None))
)
val s = """${data.test[foo][bar][baz]}"""
val s2 = """${rudder-data.test[foo][bar][baz]}"""
val res = RudderEngine("test", List("foo", "bar", "baz"), None)
test(all(_), s, List(res)) and
test(all(_), s2, List(res))
}

"parse engine with UTF-8" in {
val s = """${engine.😈tëst😍[emo😄ji-parameter] | 1optionö = emo😄jiOpt1 | 2optionü = emo😄jiOpt2}"""
test(all(_), s, List(
RudderEngine(
"😈tëst😍",
List("emo😄ji-parameter"),
Some(
List(
EngineOption("1optionö", "emo😄jiOpt1"),
EngineOption("2optionü", "emo😄jiOpt2")
)
val s = """${data.😈tëst😍[emo😄ji-parameter] | 1optionö = emo😄jiOpt1 | 2optionü = emo😄jiOpt2}"""
val s2 = """${rudder-data.😈tëst😍[emo😄ji-parameter] | 1optionö = emo😄jiOpt1 | 2optionü = emo😄jiOpt2}"""
val res = RudderEngine(
"😈tëst😍",
List("emo😄ji-parameter"),
Some(
List(
EngineOption("1optionö", "emo😄jiOpt1"),
EngineOption("2optionü", "emo😄jiOpt2")
)
)
))
)
)
test(all(_), s, List(res)) and
test(all(_), s2, List(res))
}

"fails when an engine with empty method between" in {
val s = """${rudder.engine[foo][][bar]("test")}"""
PropertyParser.parse(s) must beLeft
val s = """${data.test[foo][][bar]("test")}"""
val s2 = """${rudder-data.test[foo][][bar]("test")}"""
(PropertyParser.parse(s) must beLeft) and
(PropertyParser.parse(s2) must beLeft)
}

"fails when an engine with empty method at the end" in {
val s = """${rudder.engine[foo][bar][]("test")}"""
PropertyParser.parse(s) must beLeft
val s = """${data.test[foo][bar][]("test")}"""
val s2 = """${rudder-data.test[foo][bar][]("test")}"""
(PropertyParser.parse(s) must beLeft) and
(PropertyParser.parse(s2) must beLeft)
}

"fails when an engine with empty method at the beginning" in {
val s = """${rudder.engine[][foo][bar]("test")}"""
PropertyParser.parse(s) must beLeft
val s = """${data.test[][foo][bar]("test")}"""
val s2 = """${rudder-data.test[][foo][bar]("test")}"""
(PropertyParser.parse(s) must beLeft) and
(PropertyParser.parse(s2) must beLeft)
}


Expand Down Expand Up @@ -752,7 +759,7 @@ class TestNodeAndGlobalParameterLookup extends Specification {
}


//utility class to help run the IORestul
//utility class to help run the IOResult
def runParseJValue(value: JValue, context: InterpolationContext): JValue = {
buildContext.parseJValue(value, context).either.runNow match {
case Left(err) => throw new RuntimeException(s"Error when interpolating '${value}': ${err.fullMsg}")
Expand All @@ -761,34 +768,51 @@ class TestNodeAndGlobalParameterLookup extends Specification {
}

"interpolate engine in JSON" in {
val before = """{"login":"admin", "password":"${engine.fakeEncryptorEngineTesting[password_test] | option1 = foo | option2 = bar}"}"""
val before = """{"login":"admin", "password":"${data.fakeEncryptorEngineTesting[password_test] | option1 = foo | option2 = bar}"}"""
val before2 = """{"login":"admin", "password":"${rudder-data.fakeEncryptorEngineTesting[password_test] | option1 = foo | option2 = bar}"}"""
val after = """{"login":"admin", "password":"encrypted-string-test"}"""
runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))
(runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))) and
(runParseJValue(JsonParser.parse(before2), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after)))
}

"interpolate unknown engine in JSON must raise en error" in {
val before =
"""{
| "login" : "admin",
| "password" : {
| "value" : "${engine.UNKNOWN[test]}"
| "value" : "${data.UNKNOWN[test]}"
| }
|}
|""".stripMargin

buildContext.parseJValue(JsonParser.parse(before), toNodeContext(context, Map())).either.runNow must beLeft
val before2 =
"""{
| "login" : "admin",
| "password" : {
| "value" : "${rudder-data.UNKNOWN[test]}"
| }
|}
|""".stripMargin
(buildContext.parseJValue(JsonParser.parse(before), toNodeContext(context, Map())).either.runNow must beLeft) and
(buildContext.parseJValue(JsonParser.parse(before2), toNodeContext(context, Map())).either.runNow must beLeft)
}

"interpolate engine in nested JSON object" in {
val before =
"""{
| "login" : "admin",
| "password" : {
| "value" : "${engine.fakeEncryptorEngineTesting[password]}"
| "value" : "${data.fakeEncryptorEngineTesting[password]}"
| }
|}
|""".stripMargin
val before2 =
"""{
| "login" : "admin",
| "password" : {
| "value" : "${rudder-data.fakeEncryptorEngineTesting[password]}"
| }
|}
|""".stripMargin

val after =
"""{
| "login" : "admin",
Expand All @@ -798,24 +822,31 @@ class TestNodeAndGlobalParameterLookup extends Specification {
|}
|""".stripMargin

runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))
(runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))) and
(runParseJValue(JsonParser.parse(before2), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after)))
}

"interpolate engine in JSON array" in {
val before =
"""{
| "login" : "admin",
| "data" : ["foo", "${engine.fakeEncryptorEngineTesting[password]}", "bar"]
| "data" : ["foo", "${data.fakeEncryptorEngineTesting[password]}", "bar"]
|}
|""".stripMargin
val before2 =
"""{
| "login" : "admin",
| "data" : ["foo", "${rudder-data.fakeEncryptorEngineTesting[password]}", "bar"]
|}
|""".stripMargin

val after =
"""{
| "login" : "admin",
| "data" : ["foo", "encrypted-string-test", "bar"]
|}
|""".stripMargin
runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))
(runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))) and
(runParseJValue(JsonParser.parse(before2), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after)))
}

"interpolate engine in nested JSON array" in {
Expand All @@ -828,12 +859,25 @@ class TestNodeAndGlobalParameterLookup extends Specification {
| },
| "xzy",
| {
| "shouldBeInterpolated" : "${engine.fakeEncryptorEngineTesting[password]}"
| "shouldBeInterpolated" : "${data.fakeEncryptorEngineTesting[password]}"
| }
| ]
|}
|""".stripMargin
val before2 =
"""{
| "login" : "admin",
| "data" : [
| {
| "foo" : "bar"
| },
| "xzy",
| {
| "shouldBeInterpolated" : "${rudder-data.fakeEncryptorEngineTesting[password]}"
| }
| ]
|}
|""".stripMargin

val after =
"""{
| "login" : "admin",
Expand All @@ -848,32 +892,53 @@ class TestNodeAndGlobalParameterLookup extends Specification {
| ]
|}
|""".stripMargin
runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))
(runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))) and
(runParseJValue(JsonParser.parse(before2), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after)))
}

"interpolate engine multiple time" in {
val before =
"""{
| "login" : "${engine.fakeEncryptorEngineTesting[password]}",
| "login" : "${data.fakeEncryptorEngineTesting[password]}",
| "data" : [
| {
| "foo" : "${engine.fakeEncryptorEngineTesting[password]}"
| "foo" : "${data.fakeEncryptorEngineTesting[password]}"
| },
| "${engine.fakeEncryptorEngineTesting[password]}",
| "${engine.fakeEncryptorEngineTesting[password]}",
| "${data.fakeEncryptorEngineTesting[password]}",
| "${data.fakeEncryptorEngineTesting[password]}",
| {
| "shouldBeInterpolated" : "${engine.fakeEncryptorEngineTesting[password]}"
| "shouldBeInterpolated" : "${data.fakeEncryptorEngineTesting[password]}"
| }
| ]
| "moreData" : {
| "nestedStruct" : {
| "array" : [{"value":"${engine.fakeEncryptorEngineTesting[password]}"}]
| "array" : [{"value":"${data.fakeEncryptorEngineTesting[password]}"}]
| }
| }
|
|}
|""".stripMargin
val before2 =
"""{
| "login" : "${rudder-data.fakeEncryptorEngineTesting[password]}",
| "data" : [
| {
| "foo" : "${rudder-data.fakeEncryptorEngineTesting[password]}"
| },
| "${rudder-data.fakeEncryptorEngineTesting[password]}",
| "${rudder-data.fakeEncryptorEngineTesting[password]}",
| {
| "shouldBeInterpolated" : "${rudder-data.fakeEncryptorEngineTesting[password]}"
| }
| ]
| "moreData" : {
| "nestedStruct" : {
| "array" : [{"value":"${rudder-data.fakeEncryptorEngineTesting[password]}"}]
| }
| }
|
|}
|""".stripMargin

val after =
"""{
| "login" : "encrypted-string-test",
Expand All @@ -895,7 +960,8 @@ class TestNodeAndGlobalParameterLookup extends Specification {
|}
|""".stripMargin

runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))
(runParseJValue(JsonParser.parse(before), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after))) and
(runParseJValue(JsonParser.parse(before2), toNodeContext(context, Map())) must beEqualTo(JsonParser.parse(after)))
}
}

Expand Down

0 comments on commit 305f861

Please sign in to comment.