diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/config.json b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/config.json new file mode 100644 index 00000000000..35c42cadd04 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/config.json @@ -0,0 +1,6 @@ +{ + "showInput": true, + "showData": false, + "showTitles": false, + "titleSize": 4 +} diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/data.json b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/data.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/data.json @@ -0,0 +1 @@ +{} diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/input.json b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/input.json new file mode 100644 index 00000000000..ee356a68b3a --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/input.json @@ -0,0 +1,8 @@ +{ + "metadata": { + "labels": { + "app": "web", + "owner": "platform-team" + } + } +} diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/intro.md b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/intro.md new file mode 100644 index 00000000000..62da42e160a --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/intro.md @@ -0,0 +1,5 @@ + + +`array.concat` joins two arrays in order. A common use is building a complete +validation list by merging a shared base set of rules with environment-specific +additions, then iterating the result in a single `deny` rule. diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/output.json b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/output.json new file mode 100644 index 00000000000..bf155b76567 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/output.json @@ -0,0 +1,20 @@ +{ + "base_required_labels": [ + "app", + "owner" + ], + "deny": [ + "missing required label: \"cost-center\"", + "missing required label: \"environment\"" + ], + "env_required_labels": [ + "environment", + "cost-center" + ], + "required_labels": [ + "app", + "owner", + "environment", + "cost-center" + ] +} diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/policy.rego b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/policy.rego new file mode 100644 index 00000000000..28a043b6b18 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/policy.rego @@ -0,0 +1,15 @@ +package play + +# Merge base required labels with environment-specific ones. +base_required_labels := ["app", "owner"] + +env_required_labels := ["environment", "cost-center"] + +required_labels := array.concat(base_required_labels, env_required_labels) + +# Deny a resource whose metadata is missing any required label. +deny contains msg if { + some label in required_labels + not input.metadata.labels[label] + msg := sprintf("missing required label: %q", [label]) +} diff --git a/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/title.txt b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/title.txt new file mode 100644 index 00000000000..6bcc15e4e40 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/concat/merging-label-requirements/title.txt @@ -0,0 +1 @@ +Merging base and environment label requirements \ No newline at end of file diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/config.json b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/config.json new file mode 100644 index 00000000000..35c42cadd04 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/config.json @@ -0,0 +1,6 @@ +{ + "showInput": true, + "showData": false, + "showTitles": false, + "titleSize": 4 +} diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/data.json b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/data.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/data.json @@ -0,0 +1 @@ +{} diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/input.json b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/input.json new file mode 100644 index 00000000000..a52d71d09c1 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/input.json @@ -0,0 +1,3 @@ +{ + "path": "/api/v2/users/123" +} diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/intro.md b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/intro.md new file mode 100644 index 00000000000..7c98837b40e --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/intro.md @@ -0,0 +1,6 @@ + + +`array.slice` returns the sub-array from index `start` (inclusive) to `stop` +(exclusive). A common use is extracting a fixed-length prefix from a +variable-length path after splitting it into segments, so the routing logic +stays independent of how deep the path goes. diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/output.json b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/output.json new file mode 100644 index 00000000000..f2df4380ffd --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/output.json @@ -0,0 +1,16 @@ +{ + "api_version": "v2", + "deny": [ + "unsupported API version \"v2\"; only v1 is allowed" + ], + "path_segments": [ + "api", + "v2", + "users", + "123" + ], + "route_prefix": [ + "api", + "v2" + ] +} diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/policy.rego b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/policy.rego new file mode 100644 index 00000000000..a348d2b14c6 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/policy.rego @@ -0,0 +1,17 @@ +package play + +# Split a request path into segments. +# e.g. "/api/v1/users/123" → ["api", "v1", "users", "123"] +path_segments := split(trim_left(input.path, "/"), "/") + +# The API version is always the second segment (index 1). +api_version := path_segments[1] + +# The first two segments identify the route, regardless of how long the path is. +route_prefix := array.slice(path_segments, 0, 2) + +# Deny requests that do not target a supported API version. +deny contains msg if { + api_version != "v1" + msg := sprintf("unsupported API version %q; only v1 is allowed", [api_version]) +} diff --git a/docs/docs/policy-reference/_examples/array/slice/api-version-routing/title.txt b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/title.txt new file mode 100644 index 00000000000..70b797977a2 --- /dev/null +++ b/docs/docs/policy-reference/_examples/array/slice/api-version-routing/title.txt @@ -0,0 +1 @@ +Extracting a route prefix from a request path \ No newline at end of file diff --git a/docs/docs/policy-reference/builtins/array.mdx b/docs/docs/policy-reference/builtins/array.mdx index 5ac1e02a679..07ffdaaf296 100644 --- a/docs/docs/policy-reference/builtins/array.mdx +++ b/docs/docs/policy-reference/builtins/array.mdx @@ -2,3 +2,19 @@ title: Arrays --- + +## Examples + +### `array.concat` + +`array.concat` joins two arrays in order, producing a new array that contains +all elements of the first array followed by all elements of the second. + + + +### `array.slice` + +`array.slice` returns the sub-array from index `start` (inclusive) up to +index `stop` (exclusive). Indices follow standard zero-based array indexing. + +