Open policy agent 使用rego比较输入列表中的前后值
当我运行以下命令时,我可以比较参数instance_class的值并计算差异数:Open policy agent 使用rego比较输入列表中的前后值,open-policy-agent,rego,Open Policy Agent,Rego,当我运行以下命令时,我可以比较参数instance_class的值并计算差异数: modifies_instance_class[resource_type] = num { some resource_type resource_types[resource_type] all := resources[resource_type] modifies := [res | res:= all[_]; res.change.after.instance_class
modifies_instance_class[resource_type] = num {
some resource_type
resource_types[resource_type]
all := resources[resource_type]
modifies := [res | res:= all[_]; res.change.after.instance_class != res.change.before.instance_class]
num := count(modifies)
}
但是,我希望能够使用相同的代码块来比较列表my_params中包含的不同参数值。我试过以下方法,但不起作用
my_params = {"instance_class", "engine_version", "identifier"}
modifies_instance_class[resource_type] = num {
some resource_type
some parameter
resource_types[resource_type]
my_params[parameter]
all := resources[resource_type]
modifies := [res | res:= all[_]; res.change.after.parameter != res.change.before.parameter]
num := count(modifies)
}
两件事:
第一个问题是以这种方式使用res.change.after.parameter会导致问题。即使用名为parameter的键,而不是变量。您必须在[parameter]之后执行res.change.after之类的操作。这样可以避免第一个错误。。但也暴露了下一个更大的问题:
评估冲突错误:对象键必须唯一
问题在于,在使用my_params[parameter]和计算修改数的情况下,如何组合它们。它将为每个资源类型提供一个与参数不同的num,例如,某些资源类型x的实例类num为0,标识符num为2,这对于将结果构造为资源类型到num的映射的方式来说是很棘手的,因为每个资源类型都可能>1 num
如果你只关心计数,你可以做另一个理解,检查每个资源的每个参数,这可能不是最好的选择。。但这是有效的。该工作的一个例子如下:
请注意,此示例对于提供有关更改内容的任何反馈都不是很好,因此作为帮助者,它可能很有用,但其里程数可能会有所不同。如Patrick East所述,有几个问题。我想我应该把每一个都分解一下,提供更多的细节。以下是我提出的最终版本: 第一个问题:使用参数var查找字段 表达式res.change.after.parameter在res.change.after引用的对象中查找名为parameter的字段。换句话说。表达式foo[bar]从值foo中选择字段栏字符串“bar”。要解决此问题,请将res.change.after.parameter更改为res.change.after[parameter]。现在参数引用变量 修改\u实例\u类\u V1[资源\u类型]=num{ 某些资源类型、参数 资源类型[资源类型] 我的参数[参数] 全部:=资源[资源类型] 修改:=[res | res:=all[|];res.change.在[参数]之后!=res.change.在[参数]之前] num:=countmodifies } 第二个问题:使修改\实例\类为每个键生成一个值 第二个问题是,规则将为modifies_instance_类文档生成冲突的值。形式为p[x]=y{…}的规则生成一个名为p的JSON文档,其中x和y分别是键和值。OPA必须将同一密钥的冲突值视为运行时错误 例如,想象OPA包含以下数据: 资源类型={servers} 资源={ 服务器:[{ 之后:{instance_class:ic1,标识符:id1}, 前:{instance_class:ic2,标识符:id1} }] } 数据表明有一个资源类型服务器和一个服务器。服务器的数据表示实例类字段已更改 OPA计算规则时,将搜索满足规则体中所有表达式的变量赋值: 这是上面的规则体。 某些资源类型、参数 资源类型[资源类型] 我的参数[参数] 全部:=资源[资源类型] 修改:=[res | res:=all[|];res.change.在[参数]之后!=res.change.在[参数]之前] num:=countmodifies 在这种情况下,, OPA查找资源类型、参数、全部、修改和数量的值。暂时忽略所有、修改和u变量 在这种情况下,OPA将找到两组变量分配:
{resource_type: "servers", num: 1}
{资源类型:服务器,参数:实例类,num:1}
{资源类型:服务器,参数:标识符,num:0}
问题是规则生成了从资源类型到num的映射。在本例中,这将生成{servers:1}和{servers:0}。这就是冲突。哪个文件是正确的
为了解决这个问题,我们可以简单地将my_params[parameter]表达式移动到数组体中
修改\u实例\u类\u V2[资源\u类型]=num{
某些资源类型
资源类型[资源类型]
全部:=资源[资源类型]
修改:=[[res,parameter]|注意:这将立即生成一个资源/参数元组数组。
某些参数
我的参数[参数]
res:=全部
res.change.after[参数]!=res.change.before[参数]
]
num:=countmodifies
}
通过此更改,OPA将只找到一组变量分配:
{resource_type: "servers", num: 1}
注意,如果OPA要为resource_type找到其他值,那就好了,因为这些值在modifies_instance_类生成的文档中是不同的键
第三个问题:如果参数字段在之前或之后丢失怎么办?
还有一个问题要处理。在上面的例子中,我们假设
查找参数var引用的字段将始终返回一个值。如果不是这样呢?如果一个before或after对象缺少字段,该怎么办
在这种情况下,[parameter]之后的参考res.change.或[parameter]之前的参考res.change.将是未定义的。如果任一值未定义,表达式res.change.after[parameter]!=[参数]之后的res.change.after也未定义。如果表达式未定义,OPA无法断言它为真,因此结果不包括在结果中,或者在本例中,不包括由表达式计算的数组
根据数据的性质,这可能重要,也可能不重要。为了解决这个问题,我们可以扩展检查来处理字段一侧或两侧未定义的情况
modifies_instance_class_V3[resource_type] = num {
some resource_type
resource_types[resource_type]
all := resources[resource_type]
modifies := [[res, parameter] |
some parameter
my_params[parameter]
res := all[_]
not same_or_both_undefined(res.change.after, res.change.before, parameter)
]
num := count(modifies)
}
same_or_both_undefined(a, b, k) = true {
a[k] == b[k]
}
same_or_both_undefined(a, b, k) = true {
not a[k]
not b[k]
}
注意:在这种情况下,我们必须使用helper函数,因为我们想要表示逻辑OR: