Skip to content

[DRAFT] Add PostgreSQL utility functions for metrics-utility#16458

Open
cshiels-ie wants to merge 2 commits into
ansible:develfrom
cshiels-ie:metrics-utility-db-functions
Open

[DRAFT] Add PostgreSQL utility functions for metrics-utility#16458
cshiels-ie wants to merge 2 commits into
ansible:develfrom
cshiels-ie:metrics-utility-db-functions

Conversation

@cshiels-ie

@cshiels-ie cshiels-ie commented May 21, 2026

Copy link
Copy Markdown
SUMMARY

Adds a new migration (0206) that creates two plpgsql helper functions in the AWX controller database used by metrics-utility when querying via a read-only connection:

  • metrics_utility_parse_yaml_field(str text, field text) — extracts a named field from YAML-encoded text using a regex match; the field name is escaped before interpolation to prevent regex metacharacter injection
  • metrics_utility_is_valid_json(p_json text) — validates whether a text value is parseable as JSON, catching only invalid_text_representation (SQLSTATE 22P02)

Grants EXECUTE TO PUBLIC so any database user (including the ms_awx_readonly metrics read-only user) can call the functions without an explicit per-user grant. The metrics read user is customer-configurable, so a specific role name cannot be hardcoded.

Uses dbawaremigrations.RunSQL with sqlite_sql=noop so unit and functional tests (which use SQLite) are unaffected.

ISSUE TYPE
  • Bug, Docs Fix or other nominal change
COMPONENT NAME
  • API
STEPS TO REPRODUCE AND EXTRA INFO

Test plan:

  • make test passes (SQLite path, noop)
  • make test_migrations passes
  • On a PostgreSQL instance: awx-manage migrate creates both functions (\df metrics_utility*)
  • SELECT metrics_utility_is_valid_json('{"a":1}'); returns true
  • SELECT metrics_utility_parse_yaml_field('name: tower', 'name'); returns tower
  • ms_awx_readonly user can execute both functions

AI Assistance

This change was developed with assistance from Claude Code (Claude Sonnet 4.6).
All generated code was reviewed, tested, and validated before merging.

Creates two plpgsql functions used by metrics-utility when querying the
AWX controller database via a read-only connection:
- metrics_utility_parse_yaml_field: extracts a named field from YAML-encoded text
- metrics_utility_is_valid_json: validates whether a text value is valid JSON

GRANT EXECUTE TO PUBLIC so any database user (including ms_awx_readonly)
can call the functions without requiring an explicit per-user grant.

The migration is a no-op on SQLite so unit and functional tests are unaffected.

Assisted-by: Claude Code (claude-sonnet-4-6)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Ciaran Shiels <cas.ireland@Gmail.com>
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces a single Django database migration that creates two PostgreSQL PL/pgSQL utility functions for metrics processing. The functions extract YAML field values and validate JSON input, with PUBLIC execute grants for accessibility. The migration includes rollback SQL to drop both functions if reversed and treats SQLite as a no-op.

Changes

Metrics Utility Database Functions

Layer / File(s) Summary
PostgreSQL metrics utility functions
awx/main/migrations/0206_create_metrics_utility_functions.py
Migration creates metrics_utility_parse_yaml_field(str, field) to extract and trim YAML-like field values using generated regex, and metrics_utility_is_valid_json(p_json) to validate JSON input with exception handling. Both functions are granted PUBLIC execute permission. Rollback SQL explicitly drops both functions; SQLite forward and reverse operations are configured as no-ops.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding PostgreSQL utility functions for the metrics-utility feature through a migration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
awx/main/migrations/0206_create_metrics_utility_functions.py (1)

29-31: ⚡ Quick win

Narrow exception handling in JSON validation.

WHEN others THEN RETURN false hides every runtime error, not just invalid JSON input, making operational debugging harder and masking unexpected failures. Catch only the JSON-cast exception(s) expected for invalid input.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@awx/main/migrations/0206_create_metrics_utility_functions.py` around lines 29
- 31, Replace the broad "EXCEPTION WHEN others THEN RETURN false;" with a narrow
handler that only catches the JSON parse error (SQLSTATE 22P02) so other runtime
errors still surface; i.e., change the EXCEPTION block to "WHEN SQLSTATE '22P02'
THEN RETURN false;" (or include any additional specific JSON-related SQLSTATE
codes you expect) so only invalid JSON returns false and all other exceptions
propagate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@awx/main/migrations/0206_create_metrics_utility_functions.py`:
- Around line 16-18: The regex injection risk is in the construction of line_re
using the unescaped variable field (variables field_re and line_re and the
substring(str from line_re) call) — escape or regexp-quote field before
concatenating so meta-characters in field cannot alter the regex; replace the
broad EXCEPTION WHEN others THEN RETURN false in the JSON-cast helper with a
targeted exception handler that catches the specific
JSON/invalid_text_representation error only; and remove the blanket GRANT
EXECUTE TO PUBLIC, granting the helper functions only to the specific role(s)
that actually need them (update the GRANT statements accordingly).
- Around line 36-37: Replace the broad "GRANT EXECUTE ... TO PUBLIC" for the
functions metrics_utility_parse_yaml_field(text, text) and
metrics_utility_is_valid_json(text) with grants targeted to the AWX metrics
role(s) that actually run metrics queries (e.g., the read-only metrics role);
update the two GRANT lines so they grant EXECUTE only to that role (and remove
or revert the TO PUBLIC grants), ensuring the migrations call GRANT EXECUTE ON
FUNCTION metrics_utility_parse_yaml_field(text, text) TO <metrics_readonly_role>
and GRANT EXECUTE ON FUNCTION metrics_utility_is_valid_json(text) TO
<metrics_readonly_role> (use the project’s canonical metrics role name).

---

Nitpick comments:
In `@awx/main/migrations/0206_create_metrics_utility_functions.py`:
- Around line 29-31: Replace the broad "EXCEPTION WHEN others THEN RETURN
false;" with a narrow handler that only catches the JSON parse error (SQLSTATE
22P02) so other runtime errors still surface; i.e., change the EXCEPTION block
to "WHEN SQLSTATE '22P02' THEN RETURN false;" (or include any additional
specific JSON-related SQLSTATE codes you expect) so only invalid JSON returns
false and all other exceptions propagate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: acf97d71-be94-4d74-be58-ca0fa4d69793

📥 Commits

Reviewing files that changed from the base of the PR and between 5eeb854 and 0415838.

📒 Files selected for processing (1)
  • awx/main/migrations/0206_create_metrics_utility_functions.py

Comment thread awx/main/migrations/0206_create_metrics_utility_functions.py
Comment thread awx/main/migrations/0206_create_metrics_utility_functions.py
@cshiels-ie cshiels-ie changed the title Add PostgreSQL utility functions for metrics-utility [DRAFT] Add PostgreSQL utility functions for metrics-utility May 25, 2026
- Escape `field` parameter before interpolating into regex pattern using
  regexp_replace with the whole-match `&` reference rather than bare
  concatenation; prevents regex metacharacters in the field name from
  altering match semantics
- Narrow `EXCEPTION WHEN others` to `WHEN invalid_text_representation`
  (SQLSTATE 22P02) in metrics_utility_is_valid_json so only the expected
  JSON-cast failure is swallowed and unexpected runtime errors propagate

Assisted-by: Claude Code (claude-sonnet-4-6)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Ciaran Shiels <cshiels@redhat.com>
@himdel

himdel commented May 26, 2026

Copy link
Copy Markdown

The main_jobevent collector is also having to do SELECT replace(main_jobevent.event_data, '\\u', '\\u005cu')::jsonb AS event_data to get the field to a state readable by these functions.

That could be a historical artifact now .. or not :). We'll need to test what happens when the saved json actually uses the \u12345 notation somewhere, and how it gets handled.

Anyway it might be something to incorporate into these functions directly, if it's still a problem.
Otherwise lgtm :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants