Repository: stolostron/rhacm-docs
Pull request #7848: Add `toYaml`/`fromYaml` policy template functions
Author: login: dhaiducek
Created: 2025-05-20T14:58:19Z | Merged: 2025-05-22T19:06:28Z

Also adds template features to "What's New".

ref: https://issues.redhat.com/browse/ACM-20914


Diff:
diff --git a/governance/template_functions.adoc b/governance/template_functions.adoc
index 44cae6c927..3eb62472d8 100644
--- a/governance/template_functions.adoc
+++ b/governance/template_functions.adoc
@@ -21,8 +21,10 @@ Continue reading to view the descriptions and examples for some of the custom te
 * <<autoindent-function,_autoindent_>>
 * <<toInt-function,_toInt_>>
 * <<toBool-function,_toBool_>>
+* <<fromYaml-function,_fromYaml_>>
+* <<toYaml-function,_toYaml_>>
 * <<protect-function,_protect_>>
-* <<toliteral-function,_toLiteral_>>
+* <<toLiteral-function,_toLiteral_>>
 * <<copysecretdata-function,_copySecretData_>>
 * <<copyConfigMapData,_copyConfigMapData_>>
 * <<getNodes,_getNodesWithExactRoles_>>
@@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a `ConfigMap` resource that has a YAML string value.
+
+[source,yaml]
+----
+apiVersion: policy.open-cluster-management.io/v1
+kind: ConfigurationPolicy
+metadata:
+  name: demo-template-function
+spec:
+  object-templates:
+  - objectDefinition:
+      ...
+      spec:
+        replicas: >-
+          {{ (fromConfigMap "default" "app-config" "config.yaml") | fromYaml | index "replicas" }}
+----
+
+[#toYaml-function]
+=== _toYaml_
+
+The `toYaml`, or `toYAML`, function parses a Golang object into a YAML string. For a multiline result to be properly indented, you must pass the output to either the `autoindent` or `indent` function.
+
+[source,yaml]
+----
+apiVersion: policy.open-cluster-management.io/v1
+kind: ConfigurationPolicy
+metadata:
+  name: demo-template-function
+spec:
+  object-templates:
+  - objectDefinition:
+      ...
+      data:
+        config.yaml: |
+          {{ dict "key1" "value1" "key2" "value2" | toYaml | autoindent }}
+----
+
 [#protect-function]
 === _protect_
 
@@ -352,7 +394,7 @@ This ensures that your decrypted value is to never be stored in the policy on th
 
 To force an immediate rotation, delete the `policy.open-cluster-management.io/last-rotated` annotation on the `policy-encryption-key` Secret in the managed cluster namespace on the hub cluster. Policies are then reprocessed to use the new encryption key. 
 
-[#toliteral-function]
+[#toLiteral-function]
 === _toLiteral_
 
 The `toLiteral` function removes any quotation marks around the template string after it is processed. You can use this function to convert a JSON string from a config map field to a JSON value in the manifest. Run the following function to remove quotation marks from the `key` parameter value:
diff --git a/release_notes/acm_whats_new.adoc b/release_notes/acm_whats_new.adoc
index e5daf804e9..ddd918de70 100644
--- a/release_notes/acm_whats_new.adoc
+++ b/release_notes/acm_whats_new.adoc
@@ -3,7 +3,7 @@
 
 {acm} provides visibility of your entire Kubernetes domain with built-in governance, cluster lifecycle management, and application lifecycle management, along with observability. 
 
-{acm-short} version 2.14 is released with the {mce-short} version 2.9 for Cluster lifecyle management. See the link:../clusters/release_notes/mce_release_notes.adoc#mce-release-notes[Release notes for Cluster lifecycle with {mce-short}].
+{acm-short} version 2.14 is released with the {mce-short} version 2.9 for Cluster lifecycle management. See the link:../clusters/release_notes/mce_release_notes.adoc#mce-release-notes[Release notes for Cluster lifecycle with {mce-short}].
 
 Access the link:https://access.redhat.com/articles/7099672[{acm-short} Support matrix] to learn about hub cluster and managed cluster requirements and support for each component. For lifecycle information, see link:https://access.redhat.com/support/policy/updates/openshift[{ocp} Life Cycle policy].
 
@@ -71,6 +71,8 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in the `ConfigurationPolicy` resource to convert YAML strings. You also have more Sprig functions in the list of available functions.
+
 See link:../governance/grc_intro.adoc#governance[Governance] to learn more about the dashboard and the policy framework.
 
 [#bus-continuity-whats-new]


Reviews:
user: login: jc-berger
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T15:27:27Z
user: login: dhaiducek
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T19:35:12Z
user: login: dhaiducek
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T19:36:21Z
user: login: dhaiducek
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T00:25:37Z
user: login: dhaiducek
body: LGTM!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T19:43:29Z
user: login: swopebe
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T12:52:55Z
user: login: swopebe
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T12:55:50Z
user: login: swopebe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T13:00:28Z
user: login: swopebe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T13:01:13Z
user: login: swopebe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T18:57:32Z
user: login: swopebe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T18:57:49Z
user: login: swopebe
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T18:58:15Z
user: login: drkho
state: COMMENTED
author_association: NONE
submitted_at: 2025-06-02T21:17:43Z
user: login: drkho
state: COMMENTED
author_association: NONE
submitted_at: 2025-06-02T21:17:50Z
user: login: dhaiducek
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-06-02T23:59:13Z

Review comments:
diff_hunk: @@ -71,6 +71,9 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to parse YAML strings. More
path: release_notes/acm_whats_new.adoc
user: login: jc-berger
body: ```suggestion
- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to organize YAML strings. 
```
created_at: 2025-05-20T15:26:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -71,6 +71,9 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to parse YAML strings. More
+Sprig functions are also added to the list of available functions.
path: release_notes/acm_whats_new.adoc
user: login: jc-berger
body: ```suggestion
You also have more Sprig functions in the list of available functions. 
```
created_at: 2025-05-20T15:27:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -71,6 +71,9 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to parse YAML strings. More
path: release_notes/acm_whats_new.adoc
user: login: dhaiducek
body: The `toYaml`/`fromYaml` convert YAML between strings and objects. Would "convert" be a better word?

~And we already have Sprig functions, but we expanded the list of what's available from the Sprig library.~
created_at: 2025-05-20T19:35:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -71,6 +71,9 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to parse YAML strings. More
path: release_notes/acm_whats_new.adoc
user: login: dhaiducek
body: Oh sorry, that second comment isn't relevant--I hadn't read the second review comment yet! 😅 
created_at: 2025-05-20T19:36:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -71,6 +71,8 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to organize YAML strings. You also have more Sprig functions in the list of available functions.
path: release_notes/acm_whats_new.adoc
user: login: dhaiducek
body: Rather than "organize", `fromYaml`/`toYaml` perform conversions between strings and objects. Would "convert" be a more appropriate verb?
created_at: 2025-05-21T00:25:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml` (or `fromYAML`) function parses a YAML string into a Golang object. This is particularly useful if a configuration has been provided inside the key of a `ConfigMap`.
path: governance/template_functions.adoc
user: login: swopebe
body: please rewrite without parentheses here. And rewrite for conciseness: This is particularly useful (not needed), also write for correct tense and active voice. 
created_at: 2025-05-22T12:52:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml` (or `fromYAML`) function parses a YAML string into a Golang object. This is particularly useful if a configuration has been provided inside the key of a `ConfigMap`.
+
+[source,yaml]
+----
+apiVersion: policy.open-cluster-management.io/v1
+kind: ConfigurationPolicy
+metadata:
+  name: demo-template-function
+spec:
+  object-templates:
+  - objectDefinition:
+      ...
+      spec:
+        replicas: >-
+          {{ (fromConfigMap "default" "app-config" "config.yaml") | fromYaml | index "replicas" }}
+----
+
+[#toYaml-function]
+=== _toYaml_
+
+The `toYaml` (or `toYAML`) function parses a Golang object into a YAML string. In order for a multiline result to be properly indented, the output must be passed to either the `autoindent` or `indent` function.
path: governance/template_functions.adoc
user: login: swopebe
body: Similar feedback, remove unnecessary words, rewrite to remove ().
created_at: 2025-05-22T12:53:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -71,6 +71,8 @@ See link:../observability/observe_environments_intro.adoc#observing-environments
 [#governance-whats-new]
 == Governance
 
+- You can now use the `fromYaml` and `toYaml` Go template functions in `ConfigurationPolicy` to convert YAML strings. You also have more Sprig functions in the list of available functions.
path: release_notes/acm_whats_new.adoc
user: login: swopebe
body: always:

in the `ConfigurationPolicy` resource (or something similar...we don't use the coded `kind` as the noun.
created_at: 2025-05-22T12:55:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml` (or `fromYAML`) function parses a YAML string into a Golang object. This is particularly useful if a configuration has been provided inside the key of a `ConfigMap`.
path: governance/template_functions.adoc
user: login: swopebe
body: The `fromYaml`, or `fromYAML`, 

See some guidance and examples here: https://www.ibm.com/docs/en/ibm-style?topic=punctuation-parentheses
created_at: 2025-05-22T13:00:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml` (or `fromYAML`) function parses a YAML string into a Golang object. This is particularly useful if a configuration has been provided inside the key of a `ConfigMap`.
+
+[source,yaml]
+----
+apiVersion: policy.open-cluster-management.io/v1
+kind: ConfigurationPolicy
+metadata:
+  name: demo-template-function
+spec:
+  object-templates:
+  - objectDefinition:
+      ...
+      spec:
+        replicas: >-
+          {{ (fromConfigMap "default" "app-config" "config.yaml") | fromYaml | index "replicas" }}
+----
+
+[#toYaml-function]
+=== _toYaml_
+
+The `toYaml` (or `toYAML`) function parses a Golang object into a YAML string. In order for a multiline result to be properly indented, the output must be passed to either the `autoindent` or `indent` function.
path: governance/template_functions.adoc
user: login: swopebe
body: In order for a multiline result to be properly indented

changes to

For a multiline result...
created_at: 2025-05-22T13:01:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a ConfigMap resource that has a YAML string value.
+
path: governance/template_functions.adoc
user: login: swopebe
body: I missed this one, but will comment for future:

https://redhat-internal.slack.com/archives/CUHCCV19P/p1725635208472399

created_at: 2025-05-22T18:57:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a ConfigMap resource that has a YAML string value.
path: governance/template_functions.adoc
user: login: swopebe
body: ```suggestion
The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a `ConfigMap` resource that has a YAML string value.
```
created_at: 2025-05-22T18:57:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a ConfigMap resource that has a YAML string value.
+
path: governance/template_functions.adoc
user: login: drkho
body: I think that _ConfigMap_ is meant to be an example here. As far as i understand, the function is not only limited to _ConfigMap_ resource. Should we change the second sentence? (cc: @dhaiducek )

>  For example, you can use this function with a `ConfigMap` resource that has a YAML string value.
created_at: 2025-06-02T21:17:42Z
author_association: NONE
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a `ConfigMap` resource that has a YAML string value.
+
+[source,yaml]
+----
+apiVersion: policy.open-cluster-management.io/v1
+kind: ConfigurationPolicy
+metadata:
+  name: demo-template-function
+spec:
+  object-templates:
+  - objectDefinition:
+      ...
+      spec:
+        replicas: >-
+          {{ (fromConfigMap "default" "app-config" "config.yaml") | fromYaml | index "replicas" }}
+----
+
+[#toYaml-function]
+=== _toYaml_
+
+The `toYaml`, or `toYAML`, function parses a Golang object into a YAML string. For a multiline result to be properly indented, you must pass the output to either the `autoindent` or `indent` function.
+
path: governance/template_functions.adoc
user: login: drkho
body: Just try to be consistent with the previous comment on fromYAML().

> The `toYaml`, or `toYAML`, function parses a Golang object into a YAML string. For example, you can use this function with a dictionary object. For a multiline result to be properly indented, you must pass the output to either the `autoindent` or `indent` function.
created_at: 2025-06-02T21:17:50Z
author_association: NONE
diff_hunk: @@ -324,6 +326,46 @@ spec:
           {{ (fromConfigMap "site-config" "site1" "enabled")  | toBool }}
 ----
 
+[#fromYaml-function]
+=== _fromYaml_
+
+The `fromYaml`, or `fromYAML`, function parses a YAML string into a Golang object. You can use this function with a ConfigMap resource that has a YAML string value.
+
path: governance/template_functions.adoc
user: login: dhaiducek
body: @drkho Yes, that'd be a good update if it'd make it clearer that the `ConfigMap` is just an example.
created_at: 2025-06-02T23:59:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: dhaiducek
created_at: 2025-05-22T18:52:39Z
body: @swopebe Made the updates--please take another look when you have a minute!
author_association: CONTRIBUTOR
user: login: openshift-ci[bot]
created_at: 2025-05-22T18:58:21Z
body: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/stolostron/rhacm-docs/pull/7848#" title="Author self-approved">dhaiducek</a>*, *<a href="https://github.com/stolostron/rhacm-docs/pull/7848#pullrequestreview-2862287477" title="Approved">swopebe</a>*


The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=stolostron%2Frhacm-docs).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/stolostron/rhacm-docs/blob/2.14_stage/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: NONE
user: login: openshift-ci[bot]
created_at: 2025-05-22T19:02:38Z
body: New changes are detected. LGTM label has been removed.
author_association: NONE