Skip to content

docs: add examples for numbers, types, and uuid builtins - #9042

Open
VedantMadane wants to merge 3 commits into
open-policy-agent:mainfrom
VedantMadane:docs/builtin-examples-numbers-types-uuid
Open

docs: add examples for numbers, types, and uuid builtins#9042
VedantMadane wants to merge 3 commits into
open-policy-agent:mainfrom
VedantMadane:docs/builtin-examples-numbers-types-uuid

Conversation

@VedantMadane

Copy link
Copy Markdown

Adds interactive policy-reference examples for numbers (abs, ceil/floor/round, min/max), types (type_name, is_string), and uuid.rfc4122.

Fixes #3786

@netlify

netlify Bot commented Aug 18, 2026

Copy link
Copy Markdown

Deploy Preview for openpolicyagent ready!

Name Link
🔨 Latest commit 473a96e
🔍 Latest deploy log https://app.netlify.com/projects/openpolicyagent/deploys/6a89a1e69be436000823feed
😎 Deploy Preview https://deploy-preview-9042--openpolicyagent.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@charlieegan3 charlieegan3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi, thanks for this, please review the comments and push changes as new commits. Please avoid rebasing to aid reviewing.

@@ -0,0 +1,5 @@
{
"cpu_units": 250,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This one is a bit strange.

free_gib := floor(input.free_bytes / (1024 * 1024 * 1024))

# Nearest whole percent for a utilization gauge.
util_pct := round(input.used / input.total * 100)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤨 input.used / input.total * 100 is still 70

@@ -0,0 +1,5 @@
<!-- markdownlint-disable MD041 -->

`ceil`, `floor`, and `round` convert fractional values to whole numbers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Generally examples are for a single built in.

package play

# Clamp requested replicas into [min_allowed, max_allowed].
clamped := min([input.max_allowed, max([input.min_allowed, input.requested])])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please review how your examples appear in the UI, this line is too long really.


deny contains msg if {
type_name(input.replicas) != "number"
msg := sprintf("replicas must be a number, got %s", [type_name(input.replicas)])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should use string interpolation in head


`type_name` returns the Rego type of a value as a string (`"string"`,
`"number"`, `"object"`, and so on). It is useful when input may arrive with
the wrong JSON type and you want a clear deny message.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Might be nice to link to schema validation functions too here.

@@ -0,0 +1,5 @@
<!-- markdownlint-disable MD041 -->

`is_string` (and the related `is_*` helpers) test a value's type and return a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same, a link to schema validation functions is a good idea.

@@ -0,0 +1,3 @@
package play

request_id := uuid.rfc4122(sprintf("%s/%s", [input.tenant, input.name]))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please visually check line lengths in UI, run make dev in docs

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Shortened lines across policy definitions to ensure clean rendering without horizontal scrollbars in the playground UI.


`uuid.rfc4122` generates a random RFC 4122 UUID. The string argument is a
**cache key** within a single policy evaluation: the same key returns the same
UUID for the duration of that decision, which is useful for synthetic request

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the same key returns the same UUID for the duration of that decision

I think we need an example that shows that

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated the example policy to explicitly demonstrate that calling uuid.rfc4122 with the same key returns the exact same UUID within the evaluation (same_key_match == true), while different keys yield distinct UUIDs.

Comment thread docs/docs/policy-reference/builtins/uuid.mdx Outdated
Add interactive policy-reference examples for abs, ceil/floor/round,
min/max, type_name, is_string, and uuid.rfc4122.

Skip golden output for non-deterministic uuid.rfc4122. Address review:
fix description (same key within a single evaluation), update example
policy for same-key caching vs distinct keys, shorten playground lines,
remove UTF-8 BOM from MDX files.

Fixes open-policy-agent#3786

Signed-off-by: Vedant Madane <6527493+VedantMadane@users.noreply.github.com>
@VedantMadane
VedantMadane force-pushed the docs/builtin-examples-numbers-types-uuid branch from 7309b2b to e5e17f1 Compare August 20, 2026 07:18
@charlieegan3

Copy link
Copy Markdown
Contributor

Hi there, please can we avoid force pushing while I review? it makes my life harder as I need to review the entire diff again each time.

@@ -0,0 +1,3 @@
{
"request_id": "7f1aa7a5-4d88-4ab5-aa0b-2c48e9ff07cc"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Outdated, please update.


# Different key returns a different UUID:
other_id := uuid.rfc4122("req-2")
diff_key_match := req_id1 == other_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This example would be better if it showed a real use case like returning a request ID in a real policy decision in. The policy can still be trivial, but it should be more than just "here is some rego that runs the function".

These examples are meant to highlight good use cases for functions and show pseudo realistic examples to help guide users when selecting functions to use in their policies.

deny contains msg if {
type_name(input.replicas) != "number"
got := type_name(input.replicas)
msg := sprintf("replicas must be a number, got %s", [got])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please see

#9042 (comment)

let's avoid calling type_name twice in the same rule too.

@@ -0,0 +1,5 @@
<!-- markdownlint-disable MD041 -->

`is_string` (and the related `is_*` helpers) test a value's type and return a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is_ functions are not "helpers", they are built in functions.

@@ -0,0 +1,6 @@
{
"labels": {
"app": "checkout",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this example would be more 'real' if it looked a bit like a k8s resource but and the labels/annotations were bools, and not strings.

I'd use label/annnot like public-egress: true or similar boolean key/value.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated to a realistic Kubernetes resource example where an unquoted boolean annotation (public-egress: true) is flagged by is_string.

package play

# Clamp requested replicas between minimum and maximum bounds.
clamped := min([

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is another example it'd be nice to have as more of a policy rather than some rego that just runs the function. can you think of a policy use case that involves clamping?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated to a policy that clamps requested replicas between high-availability minimums (min_replicas := 2) and cost limits (max_replicas := 10).

{
"expected": 100,
"observed": 97,
"tolerance": 5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

tolerance should likely be in the policy, not the input, otherwise this example is mostly ok.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Moved olerance := 5 into the policy rule body.

- Update is_string example to validate Kubernetes annotations with boolean values
- Update min/max example to clamp replicas within policy bounds
- Move tolerance threshold into policy body for abs example

Signed-off-by: Vedant Madane <6527493+VedantMadane@users.noreply.github.com>
@VedantMadane

Copy link
Copy Markdown
Author

Thanks for the feedback @charlieegan3! I have addressed all review comments in an incremental commit (no force pushing/rebasing). Ready for another look.

@VedantMadane
VedantMadane force-pushed the docs/builtin-examples-numbers-types-uuid branch from b7fc32e to 473a96e Compare August 22, 2026 13:19
`abs` returns the absolute value of a number. Policies often use it when a
delta may be negative but only the magnitude matters for a threshold check.
`abs` returns the absolute value of a number. Policies often use it when
comparing an observed metric against an expected baseline where deviation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd rather the term 'value', not metric here.

@@ -1,5 +1,4 @@
{
"expected": 100,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it still seems strange to me that the expected is part of the input here, exp and tolerance seem to me like part of the policy.

@@ -1 +1 @@
Normalize a signed delta with abs
Enforce measurement tolerance with abs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Enforce measurement tolerance with abs

This is quite... abstract. These examples are meant to be grounded in real use cases to aid understanding.

@@ -1 +1 @@
Clamp a replica count with min and max
Clamp replica limits with min and max

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Min and Max are actually not in the numbers group, they are in aggregates

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

e.g.

package play

example := min(["z", "2", "a", "1"])

deny contains msg if {
some key, val in input.metadata.annotations
not is_string(val)
msg := sprintf("annotation %q must be a string value", [key])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please use string interpolation.

@charlieegan3

Copy link
Copy Markdown
Contributor

Hi there, I have left some more comments on the new edits.

I have addressed all review comments in an incremental commit

There are still ~10 comments I'd hoped for a response or input on. Please have another look.

@charlieegan3

Copy link
Copy Markdown
Contributor

We are up to 33 comments here and 3 rounds of review. Let's try and make the next one the final one as this ought to be a relatively simple change. 🙏

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(policy-reference): add more examples for existing built-in functions

2 participants