OPA Regoで配列ループ

1 min read読了の目安(約1100字

OpenPolicyAgentのDSLであるRegoにはforやwhileという文法は存在しません。
その代わりに、配列の要素参照に未定義の変数を書くと、その変数をインデックスとしたイテレーションが実行されます

具体例

具体例で説明します。

deployments[name] {
    resources := input[i]
    resources[j].kind == "Deployment"
    name := resources[j].metadata.name
}

↑の記述をGoに変換すると↓のような意味になります。

func getDeploymetNames(input []interface{}) (names []string) {
	for i, _ := range input {
		resources := input[i]
		for j, _ := range resources {
			if resources[j].kind == "Deployment" {
				names = names.append(resources[j].metadata.name)
			}
		}
	}
}

deployments := getDeploymetNames(input)

また、未定義変数の代わりに_と書くと変数定義なしでループを回すことができます。
インデックス変数を使わない場合はこちらが便利です。

deny[msg] {
    input.kind == ["LimitRange", "ResourceQuota"][_]
    msg = sprintf("Creating %s is not allowed", [input.kind])
}

まとめ

まあ正直いうと公式ドキュメントのLanguage Referenceを読めば書いてある話なのですが、
なぜか誰も日本語でこの話を書いていないようなので説明しました。

JavascriptのArray.prototype.mapみたいな使用感ですね。
見た目はどうみても配列の要素参照なので、初めて見た時は面食らうかと思います。

ところでこういう記法の言語って他にあるんでしょうか?
もしご存知であれば教えて下さい。