很抱歉我的新手问题。我已经编写了一个rego规则来检查ASV的名称,现在我想为这个规则编写一个测试用例。我看过样本测试用例,但是我的策略没有成功(贴在下面)。我想知道如何才能得到以下规则的肯定和失败案例。
asv_list = {"ASVONE","ASVXYZ"}
check_asv := { resources[i]: Reason |
resources:=[resource | data[j] ;
list := {x| x:=asv_list[_]}
not(list[data[j].ASV])
resource:=data[j].Name]
Reason := sprintf("THE ASV - %v being used is not a valid ASV", [data[j].ASV])
}
data = {resource |
doc = input[i];
key_ids := [k | doc[k]; startswith(k, "tag."); k != "tag.#"; endswith(k, ".key")]
resource := {
doc[k] : doc[replace(k, ".key", ".value")] | key_ids[_] == k
}
}发布于 2020-09-17 14:25:01
如果您试图测试check_asv,您的阳性测试用例和阴性测试用例将类似:
check_asv等于使用测试输入计算的期望值。
例如:
test_check_asv_positive {
expected := {"r1": "..."}
fake_input := [{"Name": "foo", ...}]
check_asv == expected with input as fake_input
}不过,在开始为您的规则编写测试之前,我认为您应该澄清您试图表达的逻辑,因为有一些危险信号会跳出。我试图分解我在下面的政策中看到的问题。最后,我编写了一些示例测试用例。
格式化文件,使其易于阅读。
首先,只需格式化Rego,这样就更容易阅读了。我将示例粘贴到一个文件中,添加了一个package (使其成为一个有效的.rego文件),然后运行opa fmt file.rego
asv_list = {"ASVONE", "ASVXYZ"}
check_asv := {resources[i]: Reason |
resources := [resource |
data[j]
list := {x | x := asv_list[_]}
not list[data[j].ASV]
resource := data[j].Name
]
Reason := sprintf("THE ASV - %v being used is not a valid ASV", [data[j].ASV])
}
data = {resource |
doc = input[i]
key_ids := [k |
doc[k]
startswith(k, "tag.")
k != "tag.#"
endswith(k, ".key")
]
resource := {doc[k]: doc[replace(k, ".key", ".value")] |
key_ids[_] == k
}
}这有点容易读懂。
不要命名规则data
我建议不要将该规则命名为data。Rego中的data是一个特殊的全局变量,它引用策略引擎中缓存的状态。来自OPA外部的任何数据或由OPA内部的规则生成的任何数据都可以在data下访问。定义一个名为data的规则是允许的,但它令人困惑。将data重命名为域中有意义的内容。例如,如果这些是虚拟机资源,您可以将它们命名为vm_resources。在本例中,我没有什么可做的,所以我将它重命名为input_docs,因为doc被用作变量名:
check_asv := {resources[i]: Reason |
resources := [resource |
input_docs[j]
list := {x | x := asv_list[_]}
not list[input_docs[j].ASV]
resource := input_docs[j].Name
]
Reason := sprintf("THE ASV - %v being used is not a valid ASV", [input_docs[j].ASV])
}
input_docs = {resource |
doc = input[i]
key_ids := [k |
doc[k]
startswith(k, "tag.")
k != "tag.#"
endswith(k, ".key")
]
resource := {doc[k]: doc[replace(k, ".key", ".value")] |
key_ids[_] == k
}
}简化input_docs助手规则(在最初的规则中称为data )
乍一看,这个规则做了很多工作,但实际上并非如此。第一行(doc = input[i])只对input中的每个元素进行迭代。规则的其余部分基于input中的每个元素。第二个表达式key_ids := [...从元素中计算一个对象键数组。第三个表达式resources := {doc[k]: ...通过映射元素来构造一个新的对象。
第一个表达式不能简化太多,但是,最好使用:=而不是=,而且由于i在其他任何地方都没有引用,所以我们只能使用_。第一个表达式是:
doc := input[_]第二个表达式计算一个键数组,但过滤有点多余:k不能等于tag.#并以.key结尾,因此可以删除!=表达式:
key_ids := [k |
some k
doc[k]
startswith(k, "tag.")
endswith(k, ".key")
]此时,我们可以停止,但是值得注意的是,规则中的第二个和第三个表达式都只是迭代doc对象。这里没有理由使用两个单独的表达式。为了简化这条规则,我们可以将它们结合起来:
input_docs = {resource |
doc := input[_]
resource := {v: x |
some k
v := doc[k]
startswith(k, "tag.")
endswith(k, ".key")
x := doc[replace(k, ".key", ".value")]
}
}简化check_asv规则
现在我们已经有了一个input_docs规则的简化版本,它生成了一组映射的资源,现在我们可以关注check_asv规则了。check_asv规则可以简化很多:
规则主体( one.
j)中的i和j)中应该只有无效资源列表的i是过于复杂的。该规则可以简化如下:
check_asv := {name: reason |
r := input_docs[_]
not asv_list[r.ASV]
name := r.Name
reason := sprintf("THE ASV - %v being used is not a valid ASV", [r.ASV])
}incorrect.)
input_docs上迭代两次(实际上,这将是需要一个嵌套的asv_list构造一个集合,它已经是一个集合了。把所有的东西都放在一起
此时,该政策如下所示:
asv_list = {"ASVONE", "ASVXYZ"}
check_asv := {name: reason |
r := input_docs[_]
not asv_list[r.ASV]
name := r.Name
reason := sprintf("THE ASV - %v being used is not a valid ASV", [r.ASV])
}
input_docs = {resource |
doc := input[_]
resource := {v: x |
some k
v := doc[k]
startswith(k, "tag.")
endswith(k, ".key")
x := doc[replace(k, ".key", ".value")]
}
}为了测试这个策略,我们可以轻松地编写一些测试用例:
test_check_asv_positive {
exp := {
"dog": "THE ASV - ASVBAD being used is not a valid ASV"
}
inp := [
{
"tag.foo.key": "Name",
"tag.foo.value": "dog",
"tag.bar.key": "ASV",
"tag.bar.value": "ASVBAD"
}
]
check_asv == exp with input as inp
}
test_check_asv_positive_multiple_resources {
exp := {
"dog": "THE ASV - ASVBAD being used is not a valid ASV",
"horse": "THE ASV - ASVBAD2 being used is not a valid ASV"
}
inp := [
{
"tag.foo.key": "Name",
"tag.foo.value": "dog",
"tag.bar.key": "ASV",
"tag.bar.value": "ASVBAD"
},
{
"tag.foo.key": "Name",
"tag.foo.value": "horse",
"tag.bar.key": "ASV",
"tag.bar.value": "ASVBAD2"
}
]
check_asv == exp with input as inp
}
test_check_asv_positive_multiple_resources_mixed {
exp := {
"horse": "THE ASV - ASVBAD2 being used is not a valid ASV"
}
inp := [
{
"tag.foo.key": "Name",
"tag.foo.value": "cat",
"tag.bar.key": "ASV",
"tag.bar.value": "ASVONE"
},
{
"tag.foo.key": "Name",
"tag.foo.value": "horse",
"tag.bar.key": "ASV",
"tag.bar.value": "ASVBAD2"
}
]
check_asv == exp with input as inp
}
test_check_asv_negative {
exp := {}
inp := [
{
"tag.foo.key": "Name",
"tag.foo.value": "cat",
"tag.bar.key": "ASV",
"tag.bar.value": "ASVONE"
}
]
check_asv == exp with input as inp
}下面链接到操场上的完整策略:https://play.openpolicyagent.org/p/6w7aC9xWYH
https://stackoverflow.com/questions/63931908
复制相似问题