From a102dae5f20c460e8d279da6d3caa77e91e612d8 Mon Sep 17 00:00:00 2001 From: Nick Anderson Date: Fri, 28 Aug 2026 17:43:18 -0500 Subject: [PATCH 1/2] Clarified that bundles are not functions but can return values Added cross-references to the useresult and bundle_return_value_index attributes. Changelog: None --- .../language-concepts/bundles.markdown | 24 +++++++++++-------- .../reference/promise-types/methods.markdown | 2 +- .../reference/promise-types/reports.markdown | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/content/reference/language-concepts/bundles.markdown b/content/reference/language-concepts/bundles.markdown index d0d125548b..1e83b6978c 100644 --- a/content/reference/language-concepts/bundles.markdown +++ b/content/reference/language-concepts/bundles.markdown @@ -6,26 +6,30 @@ aliases: - "/reference-language-concepts-bundles.html" --- -A bundle is a collection of promises. They allow to group related promises -together into named building blocks that can be thought of as "subroutines" in -the CFEngine promise language. A bundle that groups a number of promises +A bundle is a collection of promises. They group related promises together +into named, optionally parameterized building blocks that can be run from +elsewhere in the policy. A bundle that groups a number of promises related to configuring a web server or a file system would be named "webserver" or "filesystem," respectively. -**NOTE**: Bundles **are not functions**. They maintain state across actuations -within the same agent run. +**NOTE**: Bundles **are not functions**. A bundle run does not start with a +clean slate, and state from each execution compounds within the same agent +run. -- Classic arrays are cleared at the beginning of a bundle actuation. +- Classic arrays are cleared at the beginning of each bundle run. - Lists, strings, ints, reals, and data-containers are preserved but can be re-defined if not guarded with `if => isvariable()`. - `bundle` scoped classes are cleared at the end of the bundles execution - `namespace` scoped classes are not cleared automatically, though they can be explicitly undefined. -Most promise types are specific to a particular kind of interpretation that -requires a typed interpreter - the bundle _type_. Bundles belong to the agent -that is used to keep the promises in the bundle. So `cf-agent` has bundles -declared as: +Each bundle run can, however, return a scalar value to its caller, using +the `methods` attribute [`useresult`][methods#useresult] together with the +`reports` attribute [`bundle_return_value_index`][reports#bundle_return_value_index]. + +Most promise types are only understood by one particular component, such as +`cf-agent` or `cf-serverd`. The bundle _type_ declares which component's +promises a bundle contains. So `cf-agent` has bundles declared as: ```cf3 bundle agent my_name diff --git a/content/reference/promise-types/methods.markdown b/content/reference/promise-types/methods.markdown index c204312055..033ba38b24 100644 --- a/content/reference/promise-types/methods.markdown +++ b/content/reference/promise-types/methods.markdown @@ -193,6 +193,6 @@ bundle agent child } ``` -**See also:** [reports bundle_return_value_index attribute][reports#bundle_return_value_index] +**See also:** [reports bundle_return_value_index attribute][reports#bundle_return_value_index], [Bundles][bundles] **History:** Was introduced in 3.4.0 (2012) diff --git a/content/reference/promise-types/reports.markdown b/content/reference/promise-types/reports.markdown index 976fbed3ab..cdddbb9734 100644 --- a/content/reference/promise-types/reports.markdown +++ b/content/reference/promise-types/reports.markdown @@ -216,7 +216,7 @@ bundle agent child } ``` -**See also:** [methods useresult attribute][methods#useresult] +**See also:** [methods useresult attribute][methods#useresult], [Bundles][bundles] **History:** Introduced in 3.4.0. From de196f5b37e8b7af6cba26b7ba909221e1937a3b Mon Sep 17 00:00:00 2001 From: Nick Anderson Date: Fri, 28 Aug 2026 18:54:53 -0500 Subject: [PATCH 2/2] Fixed backwards isvariable guard, documented variable indirection if => isvariable() was backwards for preserving state across bundle runs; changed to unless => isvariable(). Also documented that a variable's name can itself be computed. Changelog: None --- .../reference/language-concepts/bundles.markdown | 11 ++++++----- .../reference/language-concepts/variables.markdown | 13 +++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/content/reference/language-concepts/bundles.markdown b/content/reference/language-concepts/bundles.markdown index 1e83b6978c..db282f52a3 100644 --- a/content/reference/language-concepts/bundles.markdown +++ b/content/reference/language-concepts/bundles.markdown @@ -17,15 +17,16 @@ clean slate, and state from each execution compounds within the same agent run. - Classic arrays are cleared at the beginning of each bundle run. -- Lists, strings, ints, reals, and data-containers are preserved but can be - re-defined if not guarded with `if => isvariable()`. +- Lists, strings, ints, reals, and data-containers are preserved, but a + `vars` promise that runs again can still redefine them unless something + prevents it, such as guarding with `unless => isvariable()`. - `bundle` scoped classes are cleared at the end of the bundles execution - `namespace` scoped classes are not cleared automatically, though they can be explicitly undefined. -Each bundle run can, however, return a scalar value to its caller, using -the `methods` attribute [`useresult`][methods#useresult] together with the -`reports` attribute [`bundle_return_value_index`][reports#bundle_return_value_index]. +A bundle run can return a scalar value to its caller, using the `methods` +attribute [`useresult`][methods#useresult] together with the `reports` +attribute [`bundle_return_value_index`][reports#bundle_return_value_index]. Most promise types are only understood by one particular component, such as `cf-agent` or `cf-serverd`. The bundle _type_ declares which component's diff --git a/content/reference/language-concepts/variables.markdown b/content/reference/language-concepts/variables.markdown index 8e3c2516b3..b47ea55897 100644 --- a/content/reference/language-concepts/variables.markdown +++ b/content/reference/language-concepts/variables.markdown @@ -75,6 +75,19 @@ of the bundle in which it is defined: $(bundle_name.qualified) +### Indirection + +The same expansion applies to the promiser when a variable is being +defined, so a variable's name can itself be computed: + +```cf3 {skip TODO} +vars: + "key" string => "my_var"; + "$(key)" string => "value"; +``` + +This defines a variable named `my_var`, so `$(my_var)` expands to `value`. + ### Quoting When quoting strings CFEngine allows the use of `'`, `"`, and or `` ` ``. This