From 747fbfcb1bb004af521bc01f1549dc06eb4dd148 Mon Sep 17 00:00:00 2001 From: Vadim Stepanov Date: Thu, 16 Mar 2023 10:18:49 +0000 Subject: [PATCH] Add regex_match Jinja filter (#1556) # What this PR does Adds a new `regex_match` filter to Jinja environment. ## Which issue(s) this PR fixes This should be useful on its own, and also helpful for https://github.com/grafana/oncall/pull/1555. ## Checklist - [x] Tests updated - [x] Documentation added - [x] `CHANGELOG.md` updated --- CHANGELOG.md | 4 ++++ docs/sources/alert-behavior/alert-templates/index.md | 1 + engine/common/jinja_templater/filters.py | 7 +++++++ engine/common/jinja_templater/jinja_template_env.py | 3 ++- engine/common/tests/test_apply_jinja_template.py | 12 ++++++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7562498..1172a2d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Add `regex_match` Jinja filter ([1556](https://github.com/grafana/oncall/pull/1556)) + ### Changed - Allow passing `null` as a value for `escalation_chain` when creating routes via the public API ([1557](https://github.com/grafana/oncall/pull/1557)) diff --git a/docs/sources/alert-behavior/alert-templates/index.md b/docs/sources/alert-behavior/alert-templates/index.md index 0269dfc8..3cbfbf38 100644 --- a/docs/sources/alert-behavior/alert-templates/index.md +++ b/docs/sources/alert-behavior/alert-templates/index.md @@ -176,3 +176,4 @@ Built-in functions: - `iso8601_to_time` - converts time from iso8601 (`2015-02-17T18:30:20.000Z`) to datetime - `datetimeformat` - converts time from datetime to the given format (`%H:%M / %d-%m-%Y` by default) - `regex_replace` - performs a regex find and replace +- `regex_match` - performs a regex match, returns `True` or `False`. Usage example: `{{ payload.ruleName | regex_match(".*") }}` diff --git a/engine/common/jinja_templater/filters.py b/engine/common/jinja_templater/filters.py index 07557fca..1264aa68 100644 --- a/engine/common/jinja_templater/filters.py +++ b/engine/common/jinja_templater/filters.py @@ -30,3 +30,10 @@ def regex_replace(value, find, replace): return re.sub(find, replace, value) except (ValueError, AttributeError, TypeError): return None + + +def regex_match(pattern, value): + try: + return bool(re.match(value, pattern)) + except (ValueError, AttributeError, TypeError): + return None diff --git a/engine/common/jinja_templater/jinja_template_env.py b/engine/common/jinja_templater/jinja_template_env.py index 747b010b..32ceda6b 100644 --- a/engine/common/jinja_templater/jinja_template_env.py +++ b/engine/common/jinja_templater/jinja_template_env.py @@ -3,7 +3,7 @@ from jinja2 import BaseLoader from jinja2.exceptions import SecurityError from jinja2.sandbox import SandboxedEnvironment -from .filters import datetimeformat, iso8601_to_time, regex_replace, to_pretty_json +from .filters import datetimeformat, iso8601_to_time, regex_match, regex_replace, to_pretty_json def raise_security_exception(name): @@ -18,3 +18,4 @@ jinja_template_env.filters["tojson_pretty"] = to_pretty_json jinja_template_env.globals["time"] = timezone.now jinja_template_env.globals["range"] = lambda *args: raise_security_exception("range") jinja_template_env.filters["regex_replace"] = regex_replace +jinja_template_env.filters["regex_match"] = regex_match diff --git a/engine/common/tests/test_apply_jinja_template.py b/engine/common/tests/test_apply_jinja_template.py index aed42af1..632f5026 100644 --- a/engine/common/tests/test_apply_jinja_template.py +++ b/engine/common/tests/test_apply_jinja_template.py @@ -14,6 +14,18 @@ def test_apply_jinja_template(): assert payload == result +def test_apply_jinja_template_regex_match(): + payload = {"name": "test"} + + assert apply_jinja_template("{{ payload.name | regex_match('.*') }}", payload) == "True" + assert apply_jinja_template("{{ payload.name | regex_match('tes') }}", payload) == "True" + assert apply_jinja_template("{{ payload.name | regex_match('test1') }}", payload) == "False" + + # Check that exception is raised when regex is invalid + with pytest.raises(JinjaTemplateError): + apply_jinja_template("{{ payload.name | regex_match('*') }}", payload) + + def test_apply_jinja_template_bad_syntax_error(): with pytest.raises(JinjaTemplateError): apply_jinja_template("{{%", payload={})