diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2fac5786c..62f469494 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -81,28 +81,33 @@ changes since the last release, see the [diff on GitHub][unreleased].
[actual configuration set operation][ur-ab], except that the metadata field
[executionType][ur-ac] is set to `WhatIf` instead of `Actual`.
- In this release, the generated output is synthetic, based on the results of the resources' `test`
- operation. In the future, resources will be able to participate in what-if operations, reporting
- more specifically how they will change the system. For example, participating resources could
- indicate whether an actual set operation will require a reboot or whether the current user has
-the correct permissions to manage that resource instance.
+ By default, the generated output is synthetic, based on the results of the resources' `test`
+ operation. Resources can define the [whatIf][ur-ad] property in their resource manifest to
+ participate in what-if operations, reporting more specifically how they will change the system.
+ For example, participating resources could indicate whether an actual set operation will require
+ a reboot or whether the current user has the correct permissions to manage that resource
+ instance.
+
+ Participating resources have the [WhatIf capability][ur-ae].
Related work items
- Issues: [#70][#70]
- - PRs: [#400][#400]
+ - PRs:
+ - [#400][#400]
+ - [#441][#441]
-- Added support for [importer resources][ur-ad]. These resources resolve external sources to a
+- Added support for [importer resources][ur-af]. These resources resolve external sources to a
nested DSC Configuration document. The resolved instances are processed as nested resource
instances.
This required some updates to the schemas, all backwards-compatible:
- - Added a new [resourceKind][ur-ae] named `Import`.
- - Added the [resolve][ur-af] command to resource manifests.
- - Added the new [`Resolve`][ur-ag] capability, returned in the output for the
+ - Added a new [resourceKind][ur-ag] named `Import`.
+ - Added the [resolve][ur-ah] command to resource manifests.
+ - Added the new [`Resolve`][ur-ai] capability, returned in the output for the
[dsc resource list][cmd-rlist] command when DSC discovers an importer resource.
Related work items
@@ -232,10 +237,12 @@ the correct permissions to manage that resource instance.
[ur-aa]: ./docs/reference/cli/config/set.md#-w---what-if
[ur-ab]: ./docs/reference/schemas/outputs/config/set.md
[ur-ac]: ./docs/reference/schemas/metadata/Microsoft.DSC/properties.md#executiontype
-[ur-ad]: ./docs/reference/schemas/definitions/resourceKind.md#importer-resources
-[ur-ae]: ./docs/reference/schemas/definitions/resourceKind.md
-[ur-af]: ./docs/reference/schemas/resource/manifest/resolve.md
-[ur-ag]: ./docs/reference/schemas/outputs/resource/list.md#capability-resolve
+[ur-ad]: ./docs/reference/schemas/resource/manifest/whatif.md
+[ur-ae]: ./docs/reference/schemas/outputs/resource/list.md#capability-whatif
+[ur-af]: ./docs/reference/schemas/definitions/resourceKind.md#importer-resources
+[ur-ag]: ./docs/reference/schemas/definitions/resourceKind.md
+[ur-ah]: ./docs/reference/schemas/resource/manifest/resolve.md
+[ur-ai]: ./docs/reference/schemas/outputs/resource/list.md#capability-resolve
[ur-fa]: ./docs/reference/schemas/resource/manifest/root.md#exitcodes
## [v3.0.0-preview.7][release-v3.0.0-preview.7] - 2024-04-22
@@ -1505,6 +1512,7 @@ For the full list of changes in this release, see the [diff on GitHub][compare-v
[#432]: https://github.com/PowerShell/DSC/issues/432
[#434]: https://github.com/PowerShell/DSC/issues/434
[#438]: https://github.com/PowerShell/DSC/issues/438
+[#441]: https://github.com/PowerShell/DSC/issues/441
[#45]: https://github.com/PowerShell/DSC/issues/45
[#49]: https://github.com/PowerShell/DSC/issues/49
[#57]: https://github.com/PowerShell/DSC/issues/57
diff --git a/docs/reference/schemas/outputs/resource/list.md b/docs/reference/schemas/outputs/resource/list.md
index 6970ffb65..a9d23a7f5 100644
--- a/docs/reference/schemas/outputs/resource/list.md
+++ b/docs/reference/schemas/outputs/resource/list.md
@@ -85,15 +85,15 @@ optional and depend on the resource.
The following list describes the available capabilities for a resource:
-- `Get` - The resource supports retrieving the current state of an
+- `Get` - The resource supports retrieving the current state of an
instance. All DSC Resources must have this capability. A resource has this capability when it
defines the mandatory [get][07] property in its resource manifest.
-- `Set` - The resource supports enforcing the desired state of an
+- `Set` - The resource supports enforcing the desired state of an
instance. A resource has this capability when it defines the [set][08] property in its resource
manifest. Resources without this capability can't be used with the [dsc resource set][09] or
[dsc config set][10] commands unless they're in a [Microsoft.DSC/Assertion][11] group as a nested
instance.
-- `SetHandlesExist` - The resource supports the
+- `SetHandlesExist` - The resource supports the
[_exist property][12] directly. A resource has this capability when it defines the
[handlesExist][13] property as `true` in the definition of the [set][08] command property in its
resource manifest.
@@ -106,28 +106,43 @@ The following list describes the available capabilities for a resource:
If the resource doesn't have this capability or the `Delete` capability, DSC raises an error when
an instance defines `_exist` as `false`.
-- `Test` - The resource supports validating the desired state of an
+- `WhatIf` - The resource supports returning explicit information
+ about how it will modify state when a user calls [dsc config set][10] with the [--what-if][15]
+ option. A resource has this capability when it defines the [What-if method][16] in its resource
+ manifest.
+
+ When a resource has this capability, DSC calls the defined command with its arguments when a
+ user executes the `dsc config set` command with the `--what-if` option.
+
+ When a resource doesn't have this capability, DSC synthesizes how the resource will change and
+ instance by converting the `Test` result for the instance into a `Set` result. The synthetic
+ operation can't indicate potential issues or changes that can't be determined by comparing the
+ result of the `Test` operation against the resource's desired state. For example, the credentials
+ used to test a resource might be valid for that operation, but not have permissions to actually
+ modify the system state. Only a resource with this capability can fully report whether and how
+ the resource will change system state.
+- `Test` - The resource supports validating the desired state of an
instance against the current state of the instance. A resource has this capability when it
- defines the [test][15] property in its resource manifest.
+ defines the [test][17] property in its resource manifest.
If a resource doesn't have the `Test` capability, DSC uses a synthetic test for instances of the
resource. The synthetic test compares each property for the desired state of an instance against
the actual state. The synthetic test uses strict, case-sensitive equivalence. If the desired
state for a property and the actual state aren't the same, DSC marks the property as out of the
desired state.
-- `Delete` - The resource supports removing an instance. A resource
+- `Delete` - The resource supports removing an instance. A resource
has this capability when it defines the [delete][14] property in its resource manifest. This
capability isn't mutually exclusive with the `SetHandlesExist` property. A resource can handle
- the `_exist` property in set operations and be called directly with [dsc resource delete][16] to
+ the `_exist` property in set operations and be called directly with [dsc resource delete][18] to
remove an instance.
-- `Export` - The resource supports enumerating every instance of the
- resource. A resource has this capability when it defines the [export][17] property in its resource
- manifest. Only resources with this capability are usable with the [dsc resource export][18] and
- [dsc config export][19] commands.
-- `Resolve` - The resource supports resolving nested resource
+- `Export` - The resource supports enumerating every instance of
+ the resource. A resource has this capability when it defines the [export][19] property in its
+ resource manifest. Only resources with this capability are usable with the
+ [dsc resource export][20] and [dsc config export][21] commands.
+- `Resolve` - The resource supports resolving nested resource
instances from an external source. A resource has this capability when it defines the
- [resolve][20] property in its resource manifest. This functionality is primarily used by
- [importer resources][21].
+ [resolve][22] property in its resource manifest. This functionality is primarily used by
+ [importer resources][23].
```yaml
Type: array
@@ -215,7 +230,7 @@ Required: true
Represents the values defined in the resource's manifest. This value is `null` for resources that
aren't command-based. For more information on the value for this property, see
-[Command-based DSC Resource manifest schema reference][22].
+[Command-based DSC Resource manifest schema reference][24].
```yaml
Type: [object, 'null']
@@ -237,11 +252,13 @@ Required: true
[12]: ../../resource/properties/exist.md
[13]: ../../resource/manifest/set.md#handlesexist
[14]: ../../resource/manifest/delete.md
-[15]: ../../resource/manifest/test.md
-[16]: ../../../cli/resource/delete.md
-[17]: ../../resource/manifest/export.md
-[18]: ../../../cli/resource/export.md
-[19]: ../../../cli/config/export.md
-[20]: ../../resource/manifest/resolve.md
-[21]: ../../definitions/resourceKind.md#importer-resources
-[22]: ../../resource/manifest/root.md
+[15]: ../../../cli/config/set.md#-w---what-if
+[16]: ../../resource/manifest/whatif.md
+[17]: ../../resource/manifest/test.md
+[18]: ../../../cli/resource/delete.md
+[19]: ../../resource/manifest/export.md
+[20]: ../../../cli/resource/export.md
+[21]: ../../../cli/config/export.md
+[22]: ../../resource/manifest/resolve.md
+[23]: ../../definitions/resourceKind.md#importer-resources
+[24]: ../../resource/manifest/root.md
diff --git a/docs/reference/schemas/resource/manifest/whatif.md b/docs/reference/schemas/resource/manifest/whatif.md
new file mode 100644
index 000000000..ed5054edb
--- /dev/null
+++ b/docs/reference/schemas/resource/manifest/whatif.md
@@ -0,0 +1,283 @@
+---
+description: JSON schema reference for the 'whatIf' property in a DSC Resource manifest
+ms.date: 01/17/2024
+ms.topic: reference
+title: DSC Resource manifest whatIf property schema reference
+---
+
+# DSC Resource manifest whatIf property schema reference
+
+## Synopsis
+
+Defines how to indicate whether and how the set command will modify an instance.
+
+## Metadata
+
+```yaml
+SchemaDialect: https://json-schema.org/draft/2020-12/schema
+SchemaID: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json
+Type: object
+```
+
+## Description
+
+When enforcing a configuration document with the [dsc config set][01] command, users can specify
+the [--what-if][02] option to see whether and how resources will change system state without
+actually doing so. This property defines how DSC can invoke the resource to return that information
+directly.
+
+When this property isn't defined, DSC synthesizes this behavior by converting the result of a test
+operation against the resource into a set result. The synthetic result can only indicate how the
+operation will change the resource properties. It can't indicate whether the `set` operation will
+fail due to invalid parameters or which read-only properties the resource will return from the
+operation. The following list describes a few cases where a synthetic what-if result won't return
+sufficient information to the user:
+
+- A resource requiring a credential parameter might successfully test the instance but not have
+ permissions to modify it. In this case, the user might run `dsc config set --what-if` and see an
+ apparently successful prediction for the resource. Then, when they run the command without the
+ `--what-if` option, the resource raises an error that the user has to investigate. If any other
+ resources applied successfully before the instance that failed, the system might be left in a
+ partially-configured state.
+- A resource with a dependency service won't be able to report whether that service needs to be
+ restarted from a synthetic result. After reviewing the impact of the configuration based on the
+ what-if result, a user might then inadvertently restart a service or leave the configuration in a
+ partially-configured state until that service is rebooted.
+
+If your resource uses parameters or returns read-only properties from a `set` operation, define this
+method to ensure your users get the best information about whether and how the resource will modify
+system state in what-if mode.
+
+DSC sends data to the command in three ways:
+
+ 1. When `input` is `stdin`, DSC sends the data as a string representing the data as a compressed
+ JSON object without spaces or newlines between the object properties.
+ 1. When `input` is `env`, DSC sends the data as environment variables. It creates an environment
+ variable for each property in the input data object, using the name and value of the property.
+ 1. When the `args` array includes a JSON input argument definition, DSC sends the data as a
+ string representing the data as a compressed JSON object to the specified argument.
+
+If you don't define the `input` property and don't define a JSON input argument, DSC can't pass the
+input JSON to the resource. You can only define one JSON input argument for a command.
+
+You must define the `input` property, one JSON input argument in the `args` property array, or
+both.
+
+## Examples
+
+### Example 1 - Full definition
+
+```json
+"set": {
+ "executable": "my_app",
+ "args": [
+ "config",
+ "set",
+ "--what-if"
+ ],
+ "input": "stdin",
+ "return": "state"
+}
+```
+
+It defines `executable` as `my_app`, rather than `my_app.exe`. The extension isn't required when
+the operating system recognizes the command as an executable.
+
+The manifest defines three arguments, `config`, `set`, and `--what-if`. The value of the `input`
+property indicates that the `whatIf` command expects its input as a JSON blob from `stdin`.
+
+Combined with the value for `executable`, DSC calls the what-if method for this resource by
+running:
+
+```sh
+{ ... } | my_app config set --what-if
+```
+
+The manifest defines `return` as `state`, indicating that it only returns the expected final state
+of the resource after the `set` method runs. DSC compares the desired state to the return data of
+this resource to identify which of the resource's properties the `set` method will enforce, if any.
+
+## Required Properties
+
+The `whatIf` definition must include these properties:
+
+- [executable](#executable)
+
+## Properties
+
+### executable
+
+The `executable` property defines the name of the command to run. The value must be the name of a
+command discoverable in the system's `PATH` environment variable or the full path to the command. A
+file extension is only required when the command isn't recognizable by the operating system as an
+executable.
+
+```yaml
+Type: string
+Required: true
+```
+
+### args
+
+The `args` property defines the list of arguments to pass to the command. The arguments can be any
+number of strings. If you want to pass the JSON object representing the property bag for the
+resource to an argument, you can define a single item in the array as a JSON object, indicating the
+name of the argument with the `jsonInputArg` string property and whether the argument is mandatory
+for the command with the `mandatory` boolean property.
+
+```yaml
+Type: array
+Required: false
+Default: []
+Type: [string, object(JSON Input Argument)]
+```
+
+#### String arguments
+
+Any item in the argument array can be a string representing a static argument to pass to the
+command, like `config` or `--format`.
+
+```yaml
+Type: string
+```
+
+#### JSON input argument
+
+Defines an argument for the command that accepts the JSON input object as a string. DSC passes the
+JSON input to the named argument when available. A JSON input argument is defined as a JSON object
+with the following properties:
+
+- `jsonInputArg` (required) - the argument to pass the JSON data to for the command, like `--input`.
+- `mandatory` (optional) - Indicate whether DSC should always pass the argument to the command,
+ even when there's no JSON input for the command. In that case, DSC passes an empty string to the
+ JSON input argument.
+
+You can only define one JSON input argument per arguments array.
+
+If you define a JSON input argument and an `input` kind for a command, DSC sends the JSON data both
+ways:
+
+- If you define `input` as `env` and a JSON input argument, DSC sets an environment variable for
+ each property in the JSON input and passes the JSON input object as a string to the defined
+ argument.
+- If you define `input` as `stdin` and a JSON input argument, DSC passes the JSON input over stdin
+ and as a string to the defined argument.
+- If you define a JSON input argument without defining the `input` property, DSC only passes the
+ JSON input as a string to the defined argument.
+
+If you don't define the `input` property and don't define a JSON input argument, DSC can't pass the
+input JSON to the resource. This makes the manifest invalid. You must define the `input` property,
+a JSON input argument in the `args` property array, or both.
+
+```yaml
+Type: object
+RequiredProperties: [jsonInputArg]
+```
+
+### input
+
+The `input` property defines how to pass input to the resource. If this property isn't defined and
+the definition doesn't define a [JSON input argument](#json-input-argument), DSC doesn't send any
+input to the resource when invoking the `whatIf` operation.
+
+The value of this property must be one of the following strings:
+
+- `env` - Indicates that the resource expects the properties of an instance to be specified as
+ environment variables with the same names and casing.
+
+ This option only supports the following data types for instance properties:
+
+ - `boolean`
+ - `integer`
+ - `number`
+ - `string`
+ - `array` of `integer` values
+ - `array` of `number` values
+ - `array` of `string` values
+
+ For non-array values, DSC sets the environment variable to the specified value as-is. When the
+ data type is an array of values, DSC sets the environment variable as a comma-delimited string.
+ For example, the property `foo` with a value of `[1, 2, 3]` is saved in the `foo` environment
+ variable as `"1,2,3"`.
+
+ If the resource needs to support complex properties with an `object` value or multi-type arrays,
+ set this to `stdin` instead.
+- `stdin` - Indicates that the resource expects a JSON blob representing an instance from `stdin`.
+ The JSON must adhere to the instance schema for the resource.
+
+```yaml
+Type: string
+Required: false
+ValidValues: [env, stdin]
+```
+
+### implementsPretest
+
+The `implementsPretest` property defines whether the resource tests whether the instance is in the
+desired state internally before enforcing the desired state. Set this property to `true` when the
+resource tests the instance as part of the `set` operation. Set this property to `false` when it
+doesn't. In most cases, this value should be set the same as the `implementsPretest` property in
+the definition for the [set method][03] in the resource manifest.
+
+When this value is `false`, it indicates that users should always call `dsc resource test` against
+the instance before invoking the `dsc resource set` command against the resource.
+
+The default value is `false`.
+
+```yaml
+Type: boolean
+Required: false
+Default: false
+```
+
+### handlesExist
+
+The `handlesExist` property defines whether the resource has built-in handling for the
+[_exist][04] property in the `set` operation. The default value is `false`. In most cases, this
+value should be set the same as the `implementsPretest` property in the definition for the
+[set method][03] in the resource manifest.
+
+Set this property to `true` when the resource meets the following implementation requirements:
+
+- The resource's [instance schema][05] defines the `_exist` property as a valid instance property.
+- The resource's `set` command handles creating, updating, and deleting an instance based on the
+ current state of the instance and the value of the `_exist` property in the desired state.
+
+When this property is set to `true`, the resource indicates that it has the [SetHandlesExist][06]
+[capability][07]. When processing resources with the `SetHandlesExist` capability in a
+configuration, DSC calls the `set` operation for the resource when an instance defines `_exist` as
+`false`. Without this capability, a resource must define the [delete][08] operation to support
+removing instances of the resource.
+
+If a resource manifest doesn't define this property as `true` and doesn't define the `delete`
+operation, DSC raises an error when it encounters an instance of the resource with `_exist` set to
+`false`.
+
+### return
+
+The `return` property defines how DSC should process the output for this method. The value of this
+property must be one of the following strings:
+
+- `state` - Indicates that the resource returns only the instance's expected final state after the
+ set operation as a JSON blob.
+- `stateAndDiff` - Indicates that the resource returns the instance's expected final state and an
+ array of property names that the resource modified.
+
+The default value is `state`.
+
+```yaml
+Type: string
+Required: false
+Default: state
+ValidValues: [state, stateAndDiff]
+```
+
+
+[01]: ../../../cli/config/set.md
+[02]: ../../../cli/config/set.md#-w---what-if
+[03]: ./set.md
+[04]: ../properties/exist.md
+[05]: ./root.md#schema-1
+[06]: ../../outputs/resource/list.md#capability-sethandlesexist
+[07]: ../../outputs/resource/list.md#capabilities
+[08]: ./delete.md
diff --git a/schemas/2024/04/bundled/outputs/resource/list.json b/schemas/2024/04/bundled/outputs/resource/list.json
index c678e738f..9b98affa6 100644
--- a/schemas/2024/04/bundled/outputs/resource/list.json
+++ b/schemas/2024/04/bundled/outputs/resource/list.json
@@ -24,6 +24,7 @@
"Get",
"Set",
"SetHandlesExist",
+ "WhatIf",
"Test",
"Delete",
"Export",
@@ -200,6 +201,9 @@
"set": {
"$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.set.json"
},
+ "whatIf": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json"
+ },
"test": {
"$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json"
},
@@ -441,6 +445,89 @@
}
]
},
+ "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json",
+ "title": "What-if method",
+ "description": "Defines how DSC must call the DSC Resource to indicate whether and how the set command will modify an instance and how to process the output from the DSC Resource.",
+ "type": "object",
+ "required": [
+ "executable"
+ ],
+ "properties": {
+ "executable": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/commandExecutable.json"
+ },
+ "args": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/commandArgs.json"
+ },
+ "input": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/inputKind.json"
+ },
+ "implementsPretest": {
+ "title": "Resource Performs Pre-Test",
+ "description": "Defines whether the DSC Resource performs its own test to ensure idempotency when calling the `set --what-if` command. Set this value to `true` if the DSC Resource tests input before processing how it will modify system state.",
+ "type": "boolean",
+ "default": false
+ },
+ "handlesExist": {
+ "title": "Resource handles _exist property",
+ "description": "Defines whether the DSC Resource has its own built-in handling for the `_exist` common property. Set this value to `true` if the DSC Resource handles instance deletion internally when receiving a `set --what-if` command where the instance defines the `_exist` property as `false`.",
+ "type": "boolean",
+ "default": false
+ },
+ "return": {
+ "description": "Defines whether the command returns a JSON blob of the DSC Resource's expected state after a set operation in what-if mode or the state and an array of the properties the DSC Resource would modify.",
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/returnKind.json"
+ }
+ },
+ "oneOf": [
+ {
+ "required": [
+ "input"
+ ],
+ "not": {
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ {
+ "not": {
+ "required": [
+ "input"
+ ]
+ },
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ },
+ {
+ "required": [
+ "input"
+ ],
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ }
+ ]
+ },
"https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json",
diff --git a/schemas/2024/04/bundled/outputs/resource/list.vscode.json b/schemas/2024/04/bundled/outputs/resource/list.vscode.json
index b0fa46dad..994bf9d8d 100644
--- a/schemas/2024/04/bundled/outputs/resource/list.vscode.json
+++ b/schemas/2024/04/bundled/outputs/resource/list.vscode.json
@@ -24,6 +24,7 @@
"Get",
"Set",
"SetHandlesExist",
+ "WhatIf",
"Test",
"Delete",
"Export",
@@ -548,6 +549,9 @@
"set": {
"$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/resource/manifest.set.json"
},
+ "whatIf": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json"
+ },
"test": {
"$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json"
},
@@ -895,6 +899,142 @@
}
]
},
+ "manifest.whatIf.json": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json",
+ "title": "What-if method",
+ "description": "Defines how DSC must call the DSC Resource to indicate whether and how the set command will modify an instance and how to process the output from the DSC Resource.",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines how DSC must call the DSC Resource to indicate whether and how the set command will\nmodify an instance and how to process the output from the DSC Resource. If a resource doesn't\ndefine this method in the manifest, DSC synthesizes this behavior by converting the result of\nthe test operation for the resource into the [set result][02].\n\nThis method definition has the same structure as the [set method][03] in the resource manifest.\n\nDSC sends data to the command in three ways:\n\n1. When `input` is `stdin`, DSC sends the data as a string representing the data as a compressed\n JSON object without spaces or newlines between the object properties.\n1. When `input` is `env`, DSC sends the data as environment variables. It creates an environment\n variable for each property in the input data object, using the name and value of the property.\n1. When the `args` array includes a JSON input argument definition, DSC sends the data as a string\n representing the data as a compressed JSON object to the specified argument.\n\nIf you don't define the `input` property and don't define a JSON input argument, DSC can't pass\nthe input JSON to the resource. You can only define one JSON input argument for a command.\n\nYou must define the `input` property, one JSON input argument in the `args` property array, or\nboth.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true\n[02]: https://learn.microsoft.com/powershell/dsc/reference/schemas/outputs/resource/set?view=dsc-3.0&preserve-view=true\n[03]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/set?view=dsc-3.0&preserve-view=true\n",
+ "type": "object",
+ "required": [
+ "executable"
+ ],
+ "properties": {
+ "executable": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/commandExecutable.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines the name of the command to run. The value must be the name of a command discoverable\nin the system's `PATH` environment variable or the full path to the command. A file extension\nis only required when the command isn't recognizable by the operating system as an\nexecutable.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#executable\n"
+ },
+ "args": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/commandArgs.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines an array of strings to pass as arguments to the command. DSC passes the arguments to\nthe command in the order they're specified.\n\nFor example, the given the following definition:\n\n```json\n{\n \"executable\": \"myresource\",\n \"args\": [\"config\", \"set\", \"--what-if\"],\n}\n```\n\nDSC invokes the command for the resource as:\n\n```bash\nmyresource config set --what-if\n```\n\nIf you want to pass the JSON object representing the property bag for a resource instance to\nan argument, you can define a single item in the array as a JSON object. Indicate the name of\nthe argument with the `jsonInputArg` string property and whether the argument is mandatory\nfor the command with the `mandatory` boolean property.` When the `mandatory` property is\ndefined as `true`, DSC passes an empty string to the argument when no JSON input is\navailable. When the `mandatory` property is undefined or defined as `false`, DSC doesn't pass\nthe argument at all when no JSON input is available. The default value for the `mandatory`\nproperty is `false`.\n\nFor example, given the following definition:\n\n```json\n{\n \"executable\": \"myresource\"\n \"args\": [\n \"config\",\n \"set\",\n \"--what-if\",\n { \"jsonInputArg\": \"--properties\" }\n ]\n}\n```\n\nDSC invokes the command for the resource as:\n\n```bash\nmyresource config set --what-if --properties \n```\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#args\n"
+ },
+ "input": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/inputKind.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines how DSC should pass input to the command, either as environment variables or JSON\nover `stdin`. This property is optional when you define an object in the `args` list. If\nyou define a JSON input argument and an `input`, DSC sends the JSON data both ways:\n\n- If you define `input` as `env` and a JSON input argument, DSC sets an environment variable\n for each property in the JSON input and passes the JSON input object as a string to the\n defined argument.\n- If you define `input` as `stdin` and a JSON input argument, DSC passes the JSON input over\n stdin and as a string to the defined argument.\n- If you define a JSON input argument without defining the `input` property, DSC only passes\n the JSON input as a string to the defined argument.\n\nIf you don't define the `input` property and don't define a JSON input argument, DSC can't\npass the input JSON to the resource. This makes the manifest invalid. You must define the\n`input` property, a JSON input argument in the `args` property array, or both.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#input\n"
+ },
+ "implementsPretest": {
+ "title": "Resource Performs Pre-Test",
+ "description": "Defines whether the DSC Resource performs its own test to ensure idempotency when calling the `set --what-if` command. Set this value to `true` if the DSC Resource tests input before processing how it will modify system state.",
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines whether the DSC Resource performs its own test to ensure idempotency when calling the\n`set --what-if` command . Set this value to `true` if the DSC Resource tests input before\nprocessing how it will modify system state.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#implementspretest\n"
+ },
+ "handlesExist": {
+ "title": "Resource handles _exist property",
+ "description": "Defines whether the DSC Resource has its own built-in handling for the `_exist` common property. Set this value to `true` if the DSC Resource handles instance deletion internally when receiving a `set --what-if` command where the instance defines the `_exist` property as `false`.",
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines whether the DSC Resource has its own built-in handling for the [`_exist`][02] common\nproperty. Set this value to `true` if the DSC Resource handles instance deletion internally\nwhen receiving a `set --what-if` command where the instance defines the `_exist` property as\n`false`.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#handlesExist\n[02]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/properties/exist?view=dsc-3.0&preserve-view=true\n"
+ },
+ "return": {
+ "description": "Defines whether the command returns a JSON blob of the DSC Resource's expected state after a set operation in what-if mode or the state and an array of the properties the DSC Resource would modify.",
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/returnKind.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines whether the command returns a JSON blob of the DSC Resource's expected state after a\nset operation in what-if mode or the state and an array of the properties the DSC Resource\nwould modify.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#return\n",
+ "markdownEnumDescriptions": [
+ "_Final state only_\n\n> Indicates that the resource returns only the instance's expected final state after the\n> set operation as a JSON blob.\n",
+ "_Final state and changed properties_\n\n> Indicates that the resource returns the instance's expected final state and an array of\n> property names that the resource would modify.\n"
+ ]
+ }
+ },
+ "oneOf": [
+ {
+ "required": [
+ "input"
+ ],
+ "not": {
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ {
+ "not": {
+ "required": [
+ "input"
+ ]
+ },
+ "properties": {
+ "args": {
+ "errorMessage": "The `whatIf` command doesn't define either the `input` property or a JSON input argument, or it defines more than one JSON input argument. If you don't define the `input` property and don't define a JSON input argument, DSC can't pass the input JSON to the resource. You can only define one JSON input argument for a command.\n\nYou must define the `input` property, one JSON input argument in the `args` property array, or both. For more information, see:\n\nhttps://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true",
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ },
+ {
+ "required": [
+ "input"
+ ],
+ "properties": {
+ "args": {
+ "errorMessage": "You can only specify one JSON input argument for the `whatIf` command. Remove the extra JSON input argument. When you use the JSON input argument, DSC sends the full JSON object as a string to the named argument.\n\nFor more information, see:\n\nhttps://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true",
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ }
+ ],
+ "defaultSnippets": [
+ {
+ "label": " Define without arguments",
+ "markdownDescription": "Define the `whatIf` command for the resource when no arguments are required and the JSON\ninput is sent over stdin or as environment variables.\n",
+ "body": {
+ "input": "${1|stdin,env|}",
+ "implementsPretest": "^${2|true,false|}",
+ "return": "${3|state,stateAndDiff|}",
+ "executable": "${4:executable_name}"
+ }
+ },
+ {
+ "label": " Define with string arguments",
+ "markdownDescription": "Define the `whatIf` command for the resource when at least one argument is required and the\nJSON input is sent over stdin or as environment variables.",
+ "body": {
+ "input": "${1|stdin,env|}",
+ "implementsPretest": "^${2|true,false|}",
+ "return": "${3|state,stateAndDiff|}",
+ "executable": "${4:executable_name}",
+ "args": [
+ "${5:--first-argument}"
+ ]
+ }
+ },
+ {
+ "label": " Define with a JSON input argument",
+ "markdownDescription": "Define the `whatIf` command for the resource where the JSON input is passed as a one-line\nJSON object string to the specified argument.",
+ "body": {
+ "implementsPretest": "^${1|true,false|}",
+ "return": "${2|state,stateAndDiff|}",
+ "executable": "${3:executable_name}",
+ "args": [
+ {
+ "jsonInputArg": "${4:argument_name}",
+ "mandatory": "^$5"
+ }
+ ]
+ }
+ }
+ ]
+ },
"manifest.test.json": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json",
diff --git a/schemas/2024/04/bundled/resource/manifest.json b/schemas/2024/04/bundled/resource/manifest.json
index 3ee9da2ce..6c3d3eb15 100644
--- a/schemas/2024/04/bundled/resource/manifest.json
+++ b/schemas/2024/04/bundled/resource/manifest.json
@@ -59,6 +59,9 @@
"set": {
"$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.set.json"
},
+ "whatIf": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json"
+ },
"test": {
"$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json"
},
@@ -330,6 +333,89 @@
}
]
},
+ "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json",
+ "title": "What-if method",
+ "description": "Defines how DSC must call the DSC Resource to indicate whether and how the set command will modify an instance and how to process the output from the DSC Resource.",
+ "type": "object",
+ "required": [
+ "executable"
+ ],
+ "properties": {
+ "executable": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/commandExecutable.json"
+ },
+ "args": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/commandArgs.json"
+ },
+ "input": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/inputKind.json"
+ },
+ "implementsPretest": {
+ "title": "Resource Performs Pre-Test",
+ "description": "Defines whether the DSC Resource performs its own test to ensure idempotency when calling the `set --what-if` command. Set this value to `true` if the DSC Resource tests input before processing how it will modify system state.",
+ "type": "boolean",
+ "default": false
+ },
+ "handlesExist": {
+ "title": "Resource handles _exist property",
+ "description": "Defines whether the DSC Resource has its own built-in handling for the `_exist` common property. Set this value to `true` if the DSC Resource handles instance deletion internally when receiving a `set --what-if` command where the instance defines the `_exist` property as `false`.",
+ "type": "boolean",
+ "default": false
+ },
+ "return": {
+ "description": "Defines whether the command returns a JSON blob of the DSC Resource's expected state after a set operation in what-if mode or the state and an array of the properties the DSC Resource would modify.",
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/returnKind.json"
+ }
+ },
+ "oneOf": [
+ {
+ "required": [
+ "input"
+ ],
+ "not": {
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ {
+ "not": {
+ "required": [
+ "input"
+ ]
+ },
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ },
+ {
+ "required": [
+ "input"
+ ],
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ }
+ ]
+ },
"https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json",
diff --git a/schemas/2024/04/bundled/resource/manifest.vscode.json b/schemas/2024/04/bundled/resource/manifest.vscode.json
index 429d5445a..ccdc82dc0 100644
--- a/schemas/2024/04/bundled/resource/manifest.vscode.json
+++ b/schemas/2024/04/bundled/resource/manifest.vscode.json
@@ -297,6 +297,9 @@
"set": {
"$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/resource/manifest.set.json"
},
+ "whatIf": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json"
+ },
"test": {
"$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json"
},
@@ -784,6 +787,142 @@
}
]
},
+ "manifest.whatIf.json": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json",
+ "title": "What-if method",
+ "description": "Defines how DSC must call the DSC Resource to indicate whether and how the set command will modify an instance and how to process the output from the DSC Resource.",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines how DSC must call the DSC Resource to indicate whether and how the set command will\nmodify an instance and how to process the output from the DSC Resource. If a resource doesn't\ndefine this method in the manifest, DSC synthesizes this behavior by converting the result of\nthe test operation for the resource into the [set result][02].\n\nThis method definition has the same structure as the [set method][03] in the resource manifest.\n\nDSC sends data to the command in three ways:\n\n1. When `input` is `stdin`, DSC sends the data as a string representing the data as a compressed\n JSON object without spaces or newlines between the object properties.\n1. When `input` is `env`, DSC sends the data as environment variables. It creates an environment\n variable for each property in the input data object, using the name and value of the property.\n1. When the `args` array includes a JSON input argument definition, DSC sends the data as a string\n representing the data as a compressed JSON object to the specified argument.\n\nIf you don't define the `input` property and don't define a JSON input argument, DSC can't pass\nthe input JSON to the resource. You can only define one JSON input argument for a command.\n\nYou must define the `input` property, one JSON input argument in the `args` property array, or\nboth.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true\n[02]: https://learn.microsoft.com/powershell/dsc/reference/schemas/outputs/resource/set?view=dsc-3.0&preserve-view=true\n[03]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/set?view=dsc-3.0&preserve-view=true\n",
+ "type": "object",
+ "required": [
+ "executable"
+ ],
+ "properties": {
+ "executable": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/commandExecutable.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines the name of the command to run. The value must be the name of a command discoverable\nin the system's `PATH` environment variable or the full path to the command. A file extension\nis only required when the command isn't recognizable by the operating system as an\nexecutable.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#executable\n"
+ },
+ "args": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/commandArgs.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines an array of strings to pass as arguments to the command. DSC passes the arguments to\nthe command in the order they're specified.\n\nFor example, the given the following definition:\n\n```json\n{\n \"executable\": \"myresource\",\n \"args\": [\"config\", \"set\", \"--what-if\"],\n}\n```\n\nDSC invokes the command for the resource as:\n\n```bash\nmyresource config set --what-if\n```\n\nIf you want to pass the JSON object representing the property bag for a resource instance to\nan argument, you can define a single item in the array as a JSON object. Indicate the name of\nthe argument with the `jsonInputArg` string property and whether the argument is mandatory\nfor the command with the `mandatory` boolean property.` When the `mandatory` property is\ndefined as `true`, DSC passes an empty string to the argument when no JSON input is\navailable. When the `mandatory` property is undefined or defined as `false`, DSC doesn't pass\nthe argument at all when no JSON input is available. The default value for the `mandatory`\nproperty is `false`.\n\nFor example, given the following definition:\n\n```json\n{\n \"executable\": \"myresource\"\n \"args\": [\n \"config\",\n \"set\",\n \"--what-if\",\n { \"jsonInputArg\": \"--properties\" }\n ]\n}\n```\n\nDSC invokes the command for the resource as:\n\n```bash\nmyresource config set --what-if --properties \n```\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#args\n"
+ },
+ "input": {
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/inputKind.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines how DSC should pass input to the command, either as environment variables or JSON\nover `stdin`. This property is optional when you define an object in the `args` list. If\nyou define a JSON input argument and an `input`, DSC sends the JSON data both ways:\n\n- If you define `input` as `env` and a JSON input argument, DSC sets an environment variable\n for each property in the JSON input and passes the JSON input object as a string to the\n defined argument.\n- If you define `input` as `stdin` and a JSON input argument, DSC passes the JSON input over\n stdin and as a string to the defined argument.\n- If you define a JSON input argument without defining the `input` property, DSC only passes\n the JSON input as a string to the defined argument.\n\nIf you don't define the `input` property and don't define a JSON input argument, DSC can't\npass the input JSON to the resource. This makes the manifest invalid. You must define the\n`input` property, a JSON input argument in the `args` property array, or both.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#input\n"
+ },
+ "implementsPretest": {
+ "title": "Resource Performs Pre-Test",
+ "description": "Defines whether the DSC Resource performs its own test to ensure idempotency when calling the `set --what-if` command. Set this value to `true` if the DSC Resource tests input before processing how it will modify system state.",
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines whether the DSC Resource performs its own test to ensure idempotency when calling the\n`set --what-if` command . Set this value to `true` if the DSC Resource tests input before\nprocessing how it will modify system state.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#implementspretest\n"
+ },
+ "handlesExist": {
+ "title": "Resource handles _exist property",
+ "description": "Defines whether the DSC Resource has its own built-in handling for the `_exist` common property. Set this value to `true` if the DSC Resource handles instance deletion internally when receiving a `set --what-if` command where the instance defines the `_exist` property as `false`.",
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines whether the DSC Resource has its own built-in handling for the [`_exist`][02] common\nproperty. Set this value to `true` if the DSC Resource handles instance deletion internally\nwhen receiving a `set --what-if` command where the instance defines the `_exist` property as\n`false`.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#handlesExist\n[02]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/properties/exist?view=dsc-3.0&preserve-view=true\n"
+ },
+ "return": {
+ "description": "Defines whether the command returns a JSON blob of the DSC Resource's expected state after a set operation in what-if mode or the state and an array of the properties the DSC Resource would modify.",
+ "$ref": "#/$defs/PowerShell/DSC/main/schemas/2024/04/definitions/returnKind.json",
+ "markdownDescription": "***\n[_Online Documentation_][01]\n***\n\nDefines whether the command returns a JSON blob of the DSC Resource's expected state after a\nset operation in what-if mode or the state and an array of the properties the DSC Resource\nwould modify.\n\n[01]: https://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true#return\n",
+ "markdownEnumDescriptions": [
+ "_Final state only_\n\n> Indicates that the resource returns only the instance's expected final state after the\n> set operation as a JSON blob.\n",
+ "_Final state and changed properties_\n\n> Indicates that the resource returns the instance's expected final state and an array of\n> property names that the resource would modify.\n"
+ ]
+ }
+ },
+ "oneOf": [
+ {
+ "required": [
+ "input"
+ ],
+ "not": {
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ {
+ "not": {
+ "required": [
+ "input"
+ ]
+ },
+ "properties": {
+ "args": {
+ "errorMessage": "The `whatIf` command doesn't define either the `input` property or a JSON input argument, or it defines more than one JSON input argument. If you don't define the `input` property and don't define a JSON input argument, DSC can't pass the input JSON to the resource. You can only define one JSON input argument for a command.\n\nYou must define the `input` property, one JSON input argument in the `args` property array, or both. For more information, see:\n\nhttps://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true",
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ },
+ {
+ "required": [
+ "input"
+ ],
+ "properties": {
+ "args": {
+ "errorMessage": "You can only specify one JSON input argument for the `whatIf` command. Remove the extra JSON input argument. When you use the JSON input argument, DSC sends the full JSON object as a string to the named argument.\n\nFor more information, see:\n\nhttps://learn.microsoft.com/powershell/dsc/reference/schemas/resource/manifest/whatif?view=dsc-3.0&preserve-view=true",
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ }
+ ],
+ "defaultSnippets": [
+ {
+ "label": " Define without arguments",
+ "markdownDescription": "Define the `whatIf` command for the resource when no arguments are required and the JSON\ninput is sent over stdin or as environment variables.\n",
+ "body": {
+ "input": "${1|stdin,env|}",
+ "implementsPretest": "^${2|true,false|}",
+ "return": "${3|state,stateAndDiff|}",
+ "executable": "${4:executable_name}"
+ }
+ },
+ {
+ "label": " Define with string arguments",
+ "markdownDescription": "Define the `whatIf` command for the resource when at least one argument is required and the\nJSON input is sent over stdin or as environment variables.",
+ "body": {
+ "input": "${1|stdin,env|}",
+ "implementsPretest": "^${2|true,false|}",
+ "return": "${3|state,stateAndDiff|}",
+ "executable": "${4:executable_name}",
+ "args": [
+ "${5:--first-argument}"
+ ]
+ }
+ },
+ {
+ "label": " Define with a JSON input argument",
+ "markdownDescription": "Define the `whatIf` command for the resource where the JSON input is passed as a one-line\nJSON object string to the specified argument.",
+ "body": {
+ "implementsPretest": "^${1|true,false|}",
+ "return": "${2|state,stateAndDiff|}",
+ "executable": "${3:executable_name}",
+ "args": [
+ {
+ "jsonInputArg": "${4:argument_name}",
+ "mandatory": "^$5"
+ }
+ ]
+ }
+ }
+ ]
+ },
"manifest.test.json": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json",
diff --git a/schemas/2024/04/outputs/resource/list.json b/schemas/2024/04/outputs/resource/list.json
index e9f63bbdd..80fe5a84b 100644
--- a/schemas/2024/04/outputs/resource/list.json
+++ b/schemas/2024/04/outputs/resource/list.json
@@ -24,6 +24,7 @@
"Get",
"Set",
"SetHandlesExist",
+ "WhatIf",
"Test",
"Delete",
"Export",
diff --git a/schemas/2024/04/resource/manifest.json b/schemas/2024/04/resource/manifest.json
index ddfd2cee2..0cafa7473 100644
--- a/schemas/2024/04/resource/manifest.json
+++ b/schemas/2024/04/resource/manifest.json
@@ -59,6 +59,9 @@
"set": {
"$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.set.json"
},
+ "whatIf": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json"
+ },
"test": {
"$ref": "/PowerShell/DSC/main/schemas/2024/04/resource/manifest.test.json"
},
diff --git a/schemas/2024/04/resource/manifest.whatIf.json b/schemas/2024/04/resource/manifest.whatIf.json
new file mode 100644
index 000000000..ef34720e9
--- /dev/null
+++ b/schemas/2024/04/resource/manifest.whatIf.json
@@ -0,0 +1,83 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/manifest.whatIf.json",
+ "title": "What-if method",
+ "description": "Defines how DSC must call the DSC Resource to indicate whether and how the set command will modify an instance and how to process the output from the DSC Resource.",
+ "type": "object",
+ "required": [
+ "executable"
+ ],
+ "properties": {
+ "executable": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/commandExecutable.json"
+ },
+ "args": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/commandArgs.json"
+ },
+ "input": {
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/inputKind.json"
+ },
+ "implementsPretest": {
+ "title": "Resource Performs Pre-Test",
+ "description": "Defines whether the DSC Resource performs its own test to ensure idempotency when calling the `set --what-if` command. Set this value to `true` if the DSC Resource tests input before processing how it will modify system state.",
+ "type": "boolean",
+ "default": false
+ },
+ "handlesExist": {
+ "title": "Resource handles _exist property",
+ "description": "Defines whether the DSC Resource has its own built-in handling for the `_exist` common property. Set this value to `true` if the DSC Resource handles instance deletion internally when receiving a `set --what-if` command where the instance defines the `_exist` property as `false`.",
+ "type": "boolean",
+ "default": false
+ },
+ "return": {
+ "description": "Defines whether the command returns a JSON blob of the DSC Resource's expected state after a set operation in what-if mode or the state and an array of the properties the DSC Resource would modify.",
+ "$ref": "/PowerShell/DSC/main/schemas/2024/04/definitions/returnKind.json"
+ }
+ },
+ "oneOf": [
+ {
+ "required": [
+ "input"
+ ],
+ "not": {
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ {
+ "not": {
+ "required": [
+ "input"
+ ]
+ },
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ },
+ {
+ "required": [
+ "input"
+ ],
+ "properties": {
+ "args": {
+ "contains": {
+ "type": "object"
+ },
+ "minContains": 1,
+ "maxContains": 1
+ }
+ }
+ }
+ ]
+}
diff --git a/schemas/src/outputs/resource/list.yaml b/schemas/src/outputs/resource/list.yaml
index ac7e558a9..0eda2c42c 100644
--- a/schemas/src/outputs/resource/list.yaml
+++ b/schemas/src/outputs/resource/list.yaml
@@ -34,6 +34,7 @@ properties:
- Get
- Set
- SetHandlesExist
+ - WhatIf
- Test
- Delete
- Export
diff --git a/schemas/src/resource/manifest.whatIf.yaml b/schemas/src/resource/manifest.whatIf.yaml
new file mode 100644
index 000000000..711c86024
--- /dev/null
+++ b/schemas/src/resource/manifest.whatIf.yaml
@@ -0,0 +1,280 @@
+# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
+$schema: https://json-schema.org/draft/2020-12/schema
+$id: ///resource/manifest.whatIf.yaml
+
+title: What-if method
+description: >-
+ Defines how DSC must call the DSC Resource to indicate whether and how the set command will
+ modify an instance and how to process the output from the DSC Resource.
+markdownDescription: | # VS Code only
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines how DSC must call the DSC Resource to indicate whether and how the set command will
+ modify an instance and how to process the output from the DSC Resource. If a resource doesn't
+ define this method in the manifest, DSC synthesizes this behavior by converting the result of
+ the test operation for the resource into the [set result][02].
+
+ This method definition has the same structure as the [set method][03] in the resource manifest.
+
+ DSC sends data to the command in three ways:
+
+ 1. When `input` is `stdin`, DSC sends the data as a string representing the data as a compressed
+ JSON object without spaces or newlines between the object properties.
+ 1. When `input` is `env`, DSC sends the data as environment variables. It creates an environment
+ variable for each property in the input data object, using the name and value of the property.
+ 1. When the `args` array includes a JSON input argument definition, DSC sends the data as a string
+ representing the data as a compressed JSON object to the specified argument.
+
+ If you don't define the `input` property and don't define a JSON input argument, DSC can't pass
+ the input JSON to the resource. You can only define one JSON input argument for a command.
+
+ You must define the `input` property, one JSON input argument in the `args` property array, or
+ both.
+
+ [01]: /reference/schemas/resource/manifest/whatif?
+ [02]: /reference/schemas/outputs/resource/set?
+ [03]: /reference/schemas/resource/manifest/set?
+
+type: object
+required:
+ - executable
+properties:
+ executable:
+ $ref: ///definitions/commandExecutable.yaml
+ markdownDescription: |
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines the name of the command to run. The value must be the name of a command discoverable
+ in the system's `PATH` environment variable or the full path to the command. A file extension
+ is only required when the command isn't recognizable by the operating system as an
+ executable.
+
+ [01]: /reference/schemas/resource/manifest/whatif?#executable
+ args:
+ $ref: ///definitions/commandArgs.yaml
+ markdownDescription: |
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines an array of strings to pass as arguments to the command. DSC passes the arguments to
+ the command in the order they're specified.
+
+ For example, the given the following definition:
+
+ ```json
+ {
+ "executable": "myresource",
+ "args": ["config", "set", "--what-if"],
+ }
+ ```
+
+ DSC invokes the command for the resource as:
+
+ ```bash
+ myresource config set --what-if
+ ```
+
+ If you want to pass the JSON object representing the property bag for a resource instance to
+ an argument, you can define a single item in the array as a JSON object. Indicate the name of
+ the argument with the `jsonInputArg` string property and whether the argument is mandatory
+ for the command with the `mandatory` boolean property.` When the `mandatory` property is
+ defined as `true`, DSC passes an empty string to the argument when no JSON input is
+ available. When the `mandatory` property is undefined or defined as `false`, DSC doesn't pass
+ the argument at all when no JSON input is available. The default value for the `mandatory`
+ property is `false`.
+
+ For example, given the following definition:
+
+ ```json
+ {
+ "executable": "myresource"
+ "args": [
+ "config",
+ "set",
+ "--what-if",
+ { "jsonInputArg": "--properties" }
+ ]
+ }
+ ```
+
+ DSC invokes the command for the resource as:
+
+ ```bash
+ myresource config set --what-if --properties
+ ```
+
+ [01]: /reference/schemas/resource/manifest/whatif?#args
+ input:
+ $ref: ///definitions/inputKind.yaml
+ markdownDescription: |
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines how DSC should pass input to the command, either as environment variables or JSON
+ over `stdin`. This property is optional when you define an object in the `args` list. If
+ you define a JSON input argument and an `input`, DSC sends the JSON data both ways:
+
+ - If you define `input` as `env` and a JSON input argument, DSC sets an environment variable
+ for each property in the JSON input and passes the JSON input object as a string to the
+ defined argument.
+ - If you define `input` as `stdin` and a JSON input argument, DSC passes the JSON input over
+ stdin and as a string to the defined argument.
+ - If you define a JSON input argument without defining the `input` property, DSC only passes
+ the JSON input as a string to the defined argument.
+
+ If you don't define the `input` property and don't define a JSON input argument, DSC can't
+ pass the input JSON to the resource. This makes the manifest invalid. You must define the
+ `input` property, a JSON input argument in the `args` property array, or both.
+
+ [01]: /reference/schemas/resource/manifest/whatif?#input
+ implementsPretest:
+ title: Resource Performs Pre-Test
+ description: >-
+ Defines whether the DSC Resource performs its own test to ensure idempotency when calling the
+ `set --what-if` command. Set this value to `true` if the DSC Resource tests input before
+ processing how it will modify system state.
+ type: boolean
+ default: false
+ # VS Code only
+ markdownDescription: |
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines whether the DSC Resource performs its own test to ensure idempotency when calling the
+ `set --what-if` command . Set this value to `true` if the DSC Resource tests input before
+ processing how it will modify system state.
+
+ [01]: /reference/schemas/resource/manifest/whatif?#implementspretest
+ handlesExist:
+ title: Resource handles _exist property
+ description: >-
+ Defines whether the DSC Resource has its own built-in handling for the `_exist` common
+ property. Set this value to `true` if the DSC Resource handles instance deletion internally
+ when receiving a `set --what-if` command where the instance defines the `_exist` property as
+ `false`.
+ type: boolean
+ default: false
+ # VS Code only
+ markdownDescription: |
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines whether the DSC Resource has its own built-in handling for the [`_exist`][02] common
+ property. Set this value to `true` if the DSC Resource handles instance deletion internally
+ when receiving a `set --what-if` command where the instance defines the `_exist` property as
+ `false`.
+
+ [01]: /reference/schemas/resource/manifest/whatif?#handlesExist
+ [02]: /reference/schemas/resource/properties/exist?
+ return:
+ description: >-
+ Defines whether the command returns a JSON blob of the DSC Resource's expected state after a
+ set operation in what-if mode or the state and an array of the properties the DSC Resource
+ would modify.
+ $ref: ///definitions/returnKind.yaml
+ # VS Code only
+ markdownDescription: |
+ ***
+ [_Online Documentation_][01]
+ ***
+
+ Defines whether the command returns a JSON blob of the DSC Resource's expected state after a
+ set operation in what-if mode or the state and an array of the properties the DSC Resource
+ would modify.
+
+ [01]: /reference/schemas/resource/manifest/whatif?#return
+ markdownEnumDescriptions:
+ - | # state
+ _Final state only_
+
+ > Indicates that the resource returns only the instance's expected final state after the
+ > set operation as a JSON blob.
+ - | # stateAndDiff
+ _Final state and changed properties_
+
+ > Indicates that the resource returns the instance's expected final state and an array of
+ > property names that the resource would modify.
+
+# Need to use a oneOf with three possibilities because YAML extension in VS Code doesn't understand
+# minContains - so we can't use a single if/else/then. Note that JSON, but not YAML, will fail when
+# the manifest defines more than one JSON input argument. If/when the YAML extension is updated to
+# support 2019-09 and later, we can simplify this to two schemas.
+#
+# We use long lines for error messages, which can't use Markdown.
+oneOf:
+ - # What-if command with explicit input kind - when `input` is defined and `args` is only strings.
+ # This subschema never triggers an error in testing.
+ required: [input]
+ not:
+ properties: { args: { contains: { type: object } } }
+ - # What-if command with JSON input argument - when `input` isn't defined and `args` doesn't
+ # include a JSON input argument. Only raises an error when `args` has zero JSON input arguments
+ # or more than one.
+ not: { required: [input] }
+ properties:
+ args:
+ errorMessage: |-
+ The `whatIf` command doesn't define either the `input` property or a JSON input argument, or it defines more than one JSON input argument. If you don't define the `input` property and don't define a JSON input argument, DSC can't pass the input JSON to the resource. You can only define one JSON input argument for a command.
+
+ You must define the `input` property, one JSON input argument in the `args` property array, or both. For more information, see:
+
+ /reference/schemas/resource/manifest/whatif?
+ contains: { type: object }
+ minContains: 1
+ maxContains: 1
+ - # What-if command with explicit input kind and JSON input argument - when `input` is defined and
+ # args includes a JSON input argument. Only raises an error when `input` is defined and `args`
+ # contains more than one JSON input argument.
+ required: [input]
+ properties:
+ args:
+ errorMessage: |-
+ You can only specify one JSON input argument for the `whatIf` command. Remove the extra JSON input argument. When you use the JSON input argument, DSC sends the full JSON object as a string to the named argument.
+
+ For more information, see:
+
+ /reference/schemas/resource/manifest/whatif?
+ contains: { type: object }
+ minContains: 1
+ maxContains: 1
+
+defaultSnippets: # VS Code only
+ - label: ' Define without arguments'
+ markdownDescription: |
+ Define the `whatIf` command for the resource when no arguments are required and the JSON
+ input is sent over stdin or as environment variables.
+ body:
+ input: ${1|stdin,env|}
+ implementsPretest: ^${2|true,false|}
+ return: ${3|state,stateAndDiff|}
+ executable: ${4:executable_name}
+ - label: ' Define with string arguments'
+ markdownDescription: |-
+ Define the `whatIf` command for the resource when at least one argument is required and the
+ JSON input is sent over stdin or as environment variables.
+ body:
+ input: ${1|stdin,env|}
+ implementsPretest: ^${2|true,false|}
+ return: ${3|state,stateAndDiff|}
+ executable: ${4:executable_name}
+ args:
+ - ${5:--first-argument}
+ - label: ' Define with a JSON input argument'
+ markdownDescription: |-
+ Define the `whatIf` command for the resource where the JSON input is passed as a one-line
+ JSON object string to the specified argument.
+ body:
+ implementsPretest: ^${1|true,false|}
+ return: ${2|state,stateAndDiff|}
+ executable: ${3:executable_name}
+ args:
+ - jsonInputArg: ${4:argument_name}
+ mandatory: ^$5
diff --git a/schemas/src/resource/manifest.yaml b/schemas/src/resource/manifest.yaml
index 11899107f..81e265ed7 100644
--- a/schemas/src/resource/manifest.yaml
+++ b/schemas/src/resource/manifest.yaml
@@ -445,6 +445,8 @@ properties:
$ref: ///resource/manifest.get.yaml
set:
$ref: ///resource/manifest.set.yaml
+ whatIf:
+ $ref: ///resource/manifest.whatIf.yaml
test:
$ref: ///resource/manifest.test.yaml
delete: