From 392fa4c52cfe3003ca74179e5b65a8550b8acba3 Mon Sep 17 00:00:00 2001 From: Dominik Broj Date: Wed, 4 Sep 2024 16:27:39 +0200 Subject: [PATCH 1/5] fix: support running install-frontend-dependency from subdirectory (#4980) # What this PR does - support running install-frontend-dependency from subdirectory (used by oncall-private) ## Which issue(s) this PR closes https://raintank-corp.slack.com/archives/C06K1MQ07GS/p1725445756941869 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- .../install-frontend-dependencies/action.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/actions/install-frontend-dependencies/action.yml b/.github/actions/install-frontend-dependencies/action.yml index feab064e..4639fd32 100644 --- a/.github/actions/install-frontend-dependencies/action.yml +++ b/.github/actions/install-frontend-dependencies/action.yml @@ -1,5 +1,10 @@ name: Install frontend dependencies description: Setup node/pnpm + install frontend dependencies +inputs: + oncall-directory: + description: "Relative path to oncall directory" + required: false + default: "." runs: using: composite steps: @@ -7,12 +12,22 @@ runs: uses: pnpm/action-setup@v4 with: version: 9.1.4 + - name: Determine grafana-plugin directory location + id: grafana-plugin-directory + shell: bash + run: echo "grafana-plugin-directory=${{ inputs.oncall-directory }}/grafana-plugin" >> $GITHUB_OUTPUT + - name: Determine pnpm-lock.yaml location + id: pnpm-lock-location + shell: bash + # yamllint disable rule:line-length + run: echo "pnpm-lock-location=${{ steps.grafana-plugin-directory.outputs.grafana-plugin-directory }}/pnpm-lock.yaml" >> $GITHUB_OUTPUT + # yamllint enable rule:line-length - uses: actions/setup-node@v4 with: node-version: 20.15.1 cache: pnpm - cache-dependency-path: grafana-plugin/pnpm-lock.yaml + cache-dependency-path: ${{ steps.pnpm-lock-location.outputs.pnpm-lock-location }} - name: Install frontend dependencies shell: bash - working-directory: grafana-plugin + working-directory: ${{ steps.grafana-plugin-directory.outputs.grafana-plugin-directory }} run: pnpm install --frozen-lockfile --prefer-offline From bb2113db583da5e0eac343d4d7b034a75e9efee1 Mon Sep 17 00:00:00 2001 From: Vadim Stepanov Date: Wed, 4 Sep 2024 15:46:52 +0100 Subject: [PATCH 2/5] Make cloud email domain configurable (#4982) # What this PR does Fixes https://github.com/grafana/oncall-private/issues/2889 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- engine/apps/email/tasks.py | 2 +- engine/settings/base.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/apps/email/tasks.py b/engine/apps/email/tasks.py index 64587eb2..85719404 100644 --- a/engine/apps/email/tasks.py +++ b/engine/apps/email/tasks.py @@ -21,7 +21,7 @@ def get_from_email(user): return live_settings.EMAIL_FROM_ADDRESS if settings.LICENSE == settings.CLOUD_LICENSE_NAME: - return "oncall@{}.grafana.net".format(user.organization.stack_slug) + return "oncall@{}.{}".format(user.organization.stack_slug, settings.EMAIL_FROM_DOMAIN) return live_settings.EMAIL_HOST_USER diff --git a/engine/settings/base.py b/engine/settings/base.py index b516bec6..2957c2ab 100644 --- a/engine/settings/base.py +++ b/engine/settings/base.py @@ -844,6 +844,7 @@ EMAIL_PORT = getenv_integer("EMAIL_PORT", 587) EMAIL_USE_TLS = getenv_boolean("EMAIL_USE_TLS", True) EMAIL_USE_SSL = getenv_boolean("EMAIL_USE_SSL", False) EMAIL_FROM_ADDRESS = os.getenv("EMAIL_FROM_ADDRESS") +EMAIL_FROM_DOMAIN = os.getenv("EMAIL_FROM_DOMAIN", "grafana.net") EMAIL_NOTIFICATIONS_LIMIT = getenv_integer("EMAIL_NOTIFICATIONS_LIMIT", 200) EMAIL_BACKEND_INTERNAL_ID = 8 From 0ff98c141c5ddaa68bc06ca2e98671b31c5c7156 Mon Sep 17 00:00:00 2001 From: Michael Derynck Date: Wed, 4 Sep 2024 10:54:40 -0600 Subject: [PATCH 3/5] Update cryptography dependency to 43.0.1 (#4984) # What this PR does ## Which issue(s) this PR closes Related to [issue link here] ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [ ] Documentation added (or `pr:no public docs` PR label added if not required) - [ ] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- engine/requirements.in | 2 +- engine/requirements.txt | 134 ++++++++++++++++++++-------------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/engine/requirements.in b/engine/requirements.in index 4cdd8166..e172c8de 100644 --- a/engine/requirements.in +++ b/engine/requirements.in @@ -1,7 +1,7 @@ babel==2.12.1 beautifulsoup4==4.12.2 celery[redis]==5.3.1 -cryptography==42.0.8 +cryptography==43.0.1 django==4.2.15 django-add-default-value==0.10.0 django-amazon-ses==4.0.1 diff --git a/engine/requirements.txt b/engine/requirements.txt index 67be3280..858a0ced 100644 --- a/engine/requirements.txt +++ b/engine/requirements.txt @@ -1,5 +1,5 @@ # This file was autogenerated by uv via the following command: -# uv pip compile requirements.in -o requirements.txt +# uv pip compile engine/requirements.in -o engine/requirements.txt amqp==5.2.0 # via kombu appdirs==1.4.4 @@ -15,9 +15,9 @@ attrs==23.2.0 autopep8==2.0.4 # via django-silk babel==2.12.1 - # via -r requirements.in + # via -r engine/requirements.in beautifulsoup4==4.12.2 - # via -r requirements.in + # via -r engine/requirements.in billiard==4.2.0 # via celery blinker==1.7.0 @@ -35,7 +35,7 @@ cachetools==4.2.2 # google-auth # python-telegram-bot celery==5.3.1 - # via -r requirements.in + # via -r engine/requirements.in certifi==2024.7.4 # via # python-telegram-bot @@ -60,9 +60,9 @@ click-plugins==1.1.1 # via celery click-repl==0.3.0 # via celery -cryptography==42.0.8 +cryptography==43.0.1 # via - # -r requirements.in + # -r engine/requirements.in # django-mirage-field # pyopenssl # social-auth-core @@ -77,7 +77,7 @@ deprecated==1.2.14 # opentelemetry-semantic-conventions django==4.2.15 # via - # -r requirements.in + # -r engine/requirements.in # django-add-default-value # django-amazon-ses # django-anymail @@ -98,62 +98,62 @@ django==4.2.15 # fcm-django # social-auth-app-django django-add-default-value==0.10.0 - # via -r requirements.in + # via -r engine/requirements.in django-amazon-ses==4.0.1 - # via -r requirements.in + # via -r engine/requirements.in django-anymail==11.1 - # via -r requirements.in + # via -r engine/requirements.in django-cors-headers==3.7.0 - # via -r requirements.in + # via -r engine/requirements.in django-dbconn-retry==0.1.7 - # via -r requirements.in + # via -r engine/requirements.in django-debug-toolbar==4.1.0 - # via -r requirements.in + # via -r engine/requirements.in django-deprecate-fields==0.1.1 - # via -r requirements.in + # via -r engine/requirements.in django-filter==2.4.0 - # via -r requirements.in + # via -r engine/requirements.in django-ipware==4.0.2 - # via -r requirements.in + # via -r engine/requirements.in django-log-request-id==1.6.0 - # via -r requirements.in + # via -r engine/requirements.in django-migration-linter==4.1.0 - # via -r requirements.in + # via -r engine/requirements.in django-mirage-field==1.3.0 - # via -r requirements.in + # via -r engine/requirements.in django-mysql==4.6.0 - # via -r requirements.in + # via -r engine/requirements.in django-polymorphic==3.1.0 # via - # -r requirements.in + # -r engine/requirements.in # django-rest-polymorphic django-ratelimit==2.0.0 - # via -r requirements.in + # via -r engine/requirements.in django-redis==5.4.0 - # via -r requirements.in + # via -r engine/requirements.in django-rest-polymorphic==0.1.10 - # via -r requirements.in + # via -r engine/requirements.in django-silk==5.0.3 - # via -r requirements.in + # via -r engine/requirements.in django-sns-view==0.1.2 - # via -r requirements.in + # via -r engine/requirements.in djangorestframework==3.15.2 # via - # -r requirements.in + # -r engine/requirements.in # django-rest-polymorphic # drf-spectacular drf-spectacular==0.26.5 - # via -r requirements.in + # via -r engine/requirements.in emoji==2.4.0 # via - # -r requirements.in + # -r engine/requirements.in # slack-export-viewer factory-boy==2.12.0 - # via -r requirements.in + # via -r engine/requirements.in faker==23.1.0 # via factory-boy fcm-django @ https://github.com/grafana/fcm-django/archive/refs/tags/v1.0.12r1.tar.gz#sha256=7ec7cd9d353fc9edf19a4acd4fa14090a31d83d02ac986c5e5e081dea29f564f - # via -r requirements.in + # via -r engine/requirements.in firebase-admin==5.4.0 # via fcm-django flask==3.0.2 @@ -167,7 +167,7 @@ google-api-core==2.17.0 # google-cloud-storage google-api-python-client==2.122.0 # via - # -r requirements.in + # -r engine/requirements.in # firebase-admin google-auth==2.27.0 # via @@ -179,10 +179,10 @@ google-auth==2.27.0 # google-cloud-storage google-auth-httplib2==0.2.0 # via - # -r requirements.in + # -r engine/requirements.in # google-api-python-client google-auth-oauthlib==1.2.0 - # via -r requirements.in + # via -r engine/requirements.in google-cloud-core==2.4.1 # via # google-cloud-firestore @@ -206,28 +206,28 @@ gprof2dot==2022.7.29 # via django-silk grpcio==1.64.1 # via - # -r requirements.in + # -r engine/requirements.in # google-api-core # grpcio-status # opentelemetry-exporter-otlp-proto-grpc grpcio-status==1.57.0 # via google-api-core hiredis==2.2.3 - # via -r requirements.in + # via -r engine/requirements.in httplib2==0.22.0 # via # google-api-python-client # google-auth-httplib2 humanize==4.10.0 - # via -r requirements.in + # via -r engine/requirements.in icalendar==5.0.10 # via - # -r requirements.in + # -r engine/requirements.in # recurring-ical-events # x-wr-timezone idna==3.7 # via - # -r requirements.in + # -r engine/requirements.in # requests importlib-metadata==6.11.0 # via opentelemetry-api @@ -248,12 +248,12 @@ jsonschema-specifications==2023.12.1 kombu==5.3.5 # via celery lxml==5.2.2 - # via -r requirements.in + # via -r engine/requirements.in markdown==3.5.2 # via pymdown-extensions markdown2==2.4.10 # via - # -r requirements.in + # -r engine/requirements.in # slack-export-viewer markupsafe==2.1.5 # via @@ -267,7 +267,7 @@ oauthlib==3.2.2 # social-auth-core opentelemetry-api==1.26.0 # via - # -r requirements.in + # -r engine/requirements.in # opentelemetry-exporter-otlp-proto-grpc # opentelemetry-instrumentation # opentelemetry-instrumentation-django @@ -279,7 +279,7 @@ opentelemetry-api==1.26.0 opentelemetry-exporter-otlp-proto-common==1.26.0 # via opentelemetry-exporter-otlp-proto-grpc opentelemetry-exporter-otlp-proto-grpc==1.26.0 - # via -r requirements.in + # via -r engine/requirements.in opentelemetry-instrumentation==0.47b0 # via # opentelemetry-instrumentation-django @@ -287,14 +287,14 @@ opentelemetry-instrumentation==0.47b0 # opentelemetry-instrumentation-requests # opentelemetry-instrumentation-wsgi opentelemetry-instrumentation-django==0.47b0 - # via -r requirements.in + # via -r engine/requirements.in opentelemetry-instrumentation-logging==0.47b0 - # via -r requirements.in + # via -r engine/requirements.in opentelemetry-instrumentation-requests==0.47b0 - # via -r requirements.in + # via -r engine/requirements.in opentelemetry-instrumentation-wsgi==0.47b0 # via - # -r requirements.in + # -r engine/requirements.in # opentelemetry-instrumentation-django opentelemetry-proto==1.26.0 # via @@ -302,7 +302,7 @@ opentelemetry-proto==1.26.0 # opentelemetry-exporter-otlp-proto-grpc opentelemetry-sdk==1.26.0 # via - # -r requirements.in + # -r engine/requirements.in # opentelemetry-exporter-otlp-proto-grpc opentelemetry-semantic-conventions==0.47b0 # via @@ -318,9 +318,9 @@ opentelemetry-util-http==0.47b0 pem==23.1.0 # via django-sns-view phonenumbers==8.10.0 - # via -r requirements.in + # via -r engine/requirements.in prometheus-client==0.16.0 - # via -r requirements.in + # via -r engine/requirements.in prompt-toolkit==3.0.43 # via click-repl proto-plus==1.23.0 @@ -334,9 +334,9 @@ protobuf==4.25.2 # opentelemetry-proto # proto-plus psutil==5.9.4 - # via -r requirements.in + # via -r engine/requirements.in psycopg2==2.9.3 - # via -r requirements.in + # via -r engine/requirements.in pyasn1==0.5.1 # via # pyasn1-modules @@ -352,10 +352,10 @@ pyjwt==2.8.0 # social-auth-core # twilio pymdown-extensions==10.0 - # via -r requirements.in + # via -r engine/requirements.in pymysql==1.1.1 - # via -r requirements.in -pyopenssl==24.1.0 + # via -r engine/requirements.in +pyopenssl==24.2.1 # via django-sns-view pyparsing==3.1.1 # via httplib2 @@ -367,7 +367,7 @@ python-dateutil==2.8.2 # icalendar # recurring-ical-events python-telegram-bot==13.13 - # via -r requirements.in + # via -r engine/requirements.in python3-openid==3.2.0 # via social-auth-core pytz==2024.1 @@ -383,10 +383,10 @@ pyyaml==6.0.1 # drf-spectacular # pymdown-extensions recurring-ical-events==2.1.0 - # via -r requirements.in + # via -r engine/requirements.in redis==5.0.1 # via - # -r requirements.in + # -r engine/requirements.in # celery # django-redis referencing==0.33.0 @@ -394,10 +394,10 @@ referencing==0.33.0 # jsonschema # jsonschema-specifications regex==2021.11.2 - # via -r requirements.in + # via -r engine/requirements.in requests==2.32.3 # via - # -r requirements.in + # -r engine/requirements.in # cachecontrol # django-anymail # django-sns-view @@ -429,11 +429,11 @@ six==1.16.0 # python-dateutil # twilio slack-export-viewer==1.1.4 - # via -r requirements.in + # via -r engine/requirements.in slack-sdk==3.21.3 - # via -r requirements.in + # via -r engine/requirements.in social-auth-app-django==5.4.1 - # via -r requirements.in + # via -r engine/requirements.in social-auth-core==4.5.2 # via social-auth-app-django soupsieve==2.5 @@ -450,7 +450,7 @@ tornado==6.4.1 tqdm==4.66.3 # via django-mirage-field twilio==6.37.0 - # via -r requirements.in + # via -r engine/requirements.in typing-extensions==4.9.0 # via opentelemetry-sdk tzdata==2024.1 @@ -463,12 +463,12 @@ uritemplate==4.1.1 # google-api-python-client urllib3==1.26.19 # via - # -r requirements.in + # -r engine/requirements.in # botocore # django-anymail # requests uwsgi==2.0.26 - # via -r requirements.in + # via -r engine/requirements.in vine==5.1.0 # via # amqp @@ -479,7 +479,7 @@ wcwidth==0.2.13 werkzeug==3.0.3 # via flask whitenoise==5.3.0 - # via -r requirements.in + # via -r engine/requirements.in wrapt==1.16.0 # via # deprecated From de40bbbc6ac31c5e2ea9ef29aa663d10f8a61b5e Mon Sep 17 00:00:00 2001 From: Michael Derynck Date: Wed, 4 Sep 2024 11:45:41 -0600 Subject: [PATCH 4/5] Add missing permission to call machine learning plugin (#4983) # What this PR does - Permission necessary for OnCall to make webhook call to Machine Learning was missing, this PR adds it. ## Which issue(s) this PR closes Related to [issue link here] ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- grafana-plugin/src/plugin.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/grafana-plugin/src/plugin.json b/grafana-plugin/src/plugin.json index ab6f6e46..b87a72ac 100644 --- a/grafana-plugin/src/plugin.json +++ b/grafana-plugin/src/plugin.json @@ -616,6 +616,10 @@ "action": "plugins.app:access", "scope": "plugins:id:grafana-labels-app" }, + { + "action": "plugins.app:access", + "scope": "plugins:id:grafana-ml-app" + }, { "action": "plugins:write", "scope": "plugins:id:grafana-oncall-app" From 0fa3522db76e173533d4ca1b9a83317a71a08d18 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Wed, 4 Sep 2024 14:47:09 -0300 Subject: [PATCH 5/5] Add doc references to `regex_search` jinja filter (#4973) This filter wasn't listed in cheatsheet or docs, but it is usually more flexible/simpler than `regex_match` if trying to search for a substring in payload. Also setup a [timeout](https://github.com/mrabarnett/mrab-regex?tab=readme-ov-file#timeout) when regex searching/matching/replacing. Related to [this issue](https://docs.google.com/document/d/1gESMLdbJSnLnSnK7Nhp7DvJ7f10qZXsEm5GrgBc5RqQ/edit) --- .../advanced-templates/index.md | 2 + engine/common/jinja_templater/filters.py | 16 ++--- .../common/tests/test_apply_jinja_template.py | 60 ++++++++++++++++++- engine/pyproject.toml | 1 + engine/requirements.in | 2 +- engine/requirements.txt | 2 +- .../CheatSheet/CheatSheet.config.ts | 6 +- 7 files changed, 75 insertions(+), 14 deletions(-) diff --git a/docs/sources/configure/jinja2-templating/advanced-templates/index.md b/docs/sources/configure/jinja2-templating/advanced-templates/index.md index 492170b1..a92f43af 100644 --- a/docs/sources/configure/jinja2-templating/advanced-templates/index.md +++ b/docs/sources/configure/jinja2-templating/advanced-templates/index.md @@ -95,6 +95,8 @@ Grafana OnCall enhances Jinja with additional functions: - `regex_replace`: Performs a regex find and replace - `regex_match`: Performs a regex match, returns `True` or `False` - Usage example: `{{ payload.ruleName | regex_match(".*") }}` +- `regex_search`: Performs a regex search, returns `True` or `False` + - Usage example: `{{ payload.message | regex_search("Severity: (High|Critical)") }}` - `b64decode`: Performs a base64 string decode - Usage example: `{{ payload.data | b64decode }}` - `parse_json`:Parses a JSON string to an object diff --git a/engine/common/jinja_templater/filters.py b/engine/common/jinja_templater/filters.py index c8ffc12a..43096730 100644 --- a/engine/common/jinja_templater/filters.py +++ b/engine/common/jinja_templater/filters.py @@ -1,11 +1,13 @@ import base64 import json -import re from datetime import datetime +import regex from django.utils.dateparse import parse_datetime from pytz import timezone +REGEX_TIMEOUT = 2 + def datetimeparse(value, format="%H:%M / %d-%m-%Y"): try: @@ -52,22 +54,22 @@ def json_dumps(value): def regex_replace(value, find, replace): try: - return re.sub(find, replace, value) - except (ValueError, AttributeError, TypeError): + return regex.sub(find, replace, value, timeout=REGEX_TIMEOUT) + except (ValueError, AttributeError, TypeError, TimeoutError): return None def regex_match(pattern, value): try: - return bool(re.match(value, pattern)) - except (ValueError, AttributeError, TypeError): + return bool(regex.match(value, pattern, timeout=REGEX_TIMEOUT)) + except (ValueError, AttributeError, TypeError, TimeoutError): return None def regex_search(pattern, value): try: - return bool(re.search(value, pattern)) - except (ValueError, AttributeError, TypeError): + return bool(regex.search(value, pattern, timeout=REGEX_TIMEOUT)) + except (ValueError, AttributeError, TypeError, TimeoutError): return None diff --git a/engine/common/tests/test_apply_jinja_template.py b/engine/common/tests/test_apply_jinja_template.py index ca947236..3694ffa9 100644 --- a/engine/common/tests/test_apply_jinja_template.py +++ b/engine/common/tests/test_apply_jinja_template.py @@ -15,6 +15,38 @@ from common.jinja_templater.apply_jinja_template import ( templated_value_is_truthy, ) +EMAIL_SAMPLE_PAYLOAD = { + "subject": "[Reminder] Review GKE getServerConfig API permission changes", + "message": "Hello Google Kubernetes Customer,\r\n" + "\r\n" + "We’re writing to remind you that starting October 22, 2024, " + "the \r\n" + "getServerConfig API for Google Kubernetes Engine (GKE) will " + "enforce \r\n" + "Identity and Access Management (IAM) container.clusters.list " + "checks. This \r\n" + "change follows a series of security improvements as IAM \r\n" + "container.clusters.list permissions are being enforced across " + "the \r\n" + "getServerConfig API.\r\n" + "\r\n" + "We’ve provided additional information below to guide you through " + "this \r\n" + "change.\r\n" + "\r\n" + "What you need to know\r\n" + "\r\n" + "The current implementation doesn’t apply a specific permissions " + "check via \r\n" + "getServerConfig API. After this change goes into effect for the " + "Google \r\n" + "Kubernetes Engine API getServerConfig, only authorized users with " + "the \r\n" + "container.clusters.list permissions will be able to call the \r\n" + "GetServerConfig.\r\n", + "sender": "someone@somewhere.dev", +} + def test_apply_jinja_template(): payload = {"name": "test"} @@ -127,25 +159,49 @@ def test_apply_jinja_template_json_dumps(): assert result == expected +@pytest.mark.filterwarnings("ignore:::jinja2.*") # ignore regex escape sequence warning def test_apply_jinja_template_regex_match(): - payload = {"name": "test"} + payload = { + "name": "test", + "message": json.dumps(EMAIL_SAMPLE_PAYLOAD), + } 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 for timeouts + with patch("common.jinja_templater.filters.REGEX_TIMEOUT", 1): + assert ( + apply_jinja_template( + "{{ payload.message | regex_match('(.|\\s)+Severity(.|\\s){2}High(.|\\s)+') }}", payload + ) + == "False" + ) # Check that exception is raised when regex is invalid with pytest.raises(JinjaTemplateError): apply_jinja_template("{{ payload.name | regex_match('*') }}", payload) +@pytest.mark.filterwarnings("ignore:::jinja2.*") # ignore regex escape sequence warning def test_apply_jinja_template_regex_search(): - payload = {"name": "test"} + payload = { + "name": "test", + "message": json.dumps(EMAIL_SAMPLE_PAYLOAD), + } assert apply_jinja_template("{{ payload.name | regex_search('.*') }}", payload) == "True" assert apply_jinja_template("{{ payload.name | regex_search('tes') }}", payload) == "True" assert apply_jinja_template("{{ payload.name | regex_search('est') }}", payload) == "True" assert apply_jinja_template("{{ payload.name | regex_search('test1') }}", payload) == "False" + # check for timeouts + with patch("common.jinja_templater.filters.REGEX_TIMEOUT", 1): + assert ( + apply_jinja_template( + "{{ payload.message | regex_search('(.|\\s)+Severity(.|\\s){2}High(.|\\s)+') }}", payload + ) + == "False" + ) # Check that exception is raised when regex is invalid with pytest.raises(JinjaTemplateError): diff --git a/engine/pyproject.toml b/engine/pyproject.toml index e6708a8e..acb325e2 100644 --- a/engine/pyproject.toml +++ b/engine/pyproject.toml @@ -71,6 +71,7 @@ module = [ "polymorphic.*", "pyroscope.*", "ratelimit.*", + "regex.*", "recurring_ical_events.*", "rest_polymorphic.*", "slackclient.*", diff --git a/engine/requirements.in b/engine/requirements.in index e172c8de..323847ab 100644 --- a/engine/requirements.in +++ b/engine/requirements.in @@ -52,7 +52,7 @@ PyMySQL==1.1.1 python-telegram-bot==13.13 recurring-ical-events==2.1.0 redis==5.0.1 -regex==2021.11.2 +regex==2024.7.24 requests==2.32.3 slack-export-viewer==1.1.4 slack_sdk==3.21.3 diff --git a/engine/requirements.txt b/engine/requirements.txt index 858a0ced..ce4d1e6b 100644 --- a/engine/requirements.txt +++ b/engine/requirements.txt @@ -393,7 +393,7 @@ referencing==0.33.0 # via # jsonschema # jsonschema-specifications -regex==2021.11.2 +regex==2024.7.24 # via -r engine/requirements.in requests==2.32.3 # via diff --git a/grafana-plugin/src/components/CheatSheet/CheatSheet.config.ts b/grafana-plugin/src/components/CheatSheet/CheatSheet.config.ts index 523b1dad..66846368 100644 --- a/grafana-plugin/src/components/CheatSheet/CheatSheet.config.ts +++ b/grafana-plugin/src/components/CheatSheet/CheatSheet.config.ts @@ -21,7 +21,7 @@ export const groupingTemplateCheatSheet: CheatSheetInterface = { name: 'Additional variables and functions', listItems: [ { listItemName: 'time(), datetimeformat, iso8601_to_time' }, - { listItemName: 'regex_replace, regex_match' }, + { listItemName: 'regex_replace, regex_match, regex_search' }, ], }, { @@ -86,7 +86,7 @@ export const genericTemplateCheatSheet: CheatSheetInterface = { { listItemName: 'payload, grafana_oncall_link, grafana_oncall_incident_id, integration_name, source_link' }, { listItemName: 'time(), datetimeformat, datetimeformat_as_timezone, datetimeparse, iso8601_to_time' }, { listItemName: 'to_pretty_json' }, - { listItemName: 'regex_replace, regex_match' }, + { listItemName: 'regex_replace, regex_match, regex_search' }, { listItemName: 'b64decode' }, ], }, @@ -143,7 +143,7 @@ export const slackMessageTemplateCheatSheet: CheatSheetInterface = { { listItemName: 'payload, grafana_oncall_link, grafana_oncall_incident_id, integration_name, source_link' }, { listItemName: 'time(), datetimeformat, iso8601_to_time' }, { listItemName: 'to_pretty_json' }, - { listItemName: 'regex_replace, regex_match' }, + { listItemName: 'regex_replace, regex_match, regex_search' }, ], }, {