Should `set` ignore resources that don't support `set`
Summary of the new feature / enhancement
It's possible a resource supports export, but not set and with an upcoming change, get will be called when attempting an export if the resource doesn't support it directly. Now imagine you've exported current state (which might even include the OSinfo resource which only supports get).
I can imagine a scenario where a user wants to turn around and deploy this exported config as set, but it will fail once it hits a resource that doesn't support set.
Proposed technical implementation details (optional)
A potential solution is that the user can either opt-in or opt-out of the default behavior of whether set ignores (or warns) on resources that don't implement set rather than outright error and fail.
In this case, a resource that ONLY supports get is effectively read-only. So I would argue that the user should understand this and thus read-only properties are ignored instead of erroring. In which case, the default behavior is to ignore (and if not explicitly opt-ed out emit a warning message) and the user can apply metadata per resource or at document level to explicitly opt-in or opt-out of ignoring:
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
contentVersion: 1.0.0
resources:
- metadata:
Microsoft.DSC:
setNotImplemented: Ignore | Warning | Error
type: Microsoft/OSInfo
name: Microsoft/OSInfo-0
properties:
$id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json
family: macOS
version: 15.6.0
bitness: '64'
architecture: arm64
Could you provide a document level opt-in/out example?
@ThomasNieto if we use the proposed metadata above, it would look like:
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
contentVersion: 1.0.0
metadata:
Microsoft.DSC:
setNotImplemented: Ignore | Warning | Error
resources:
type: Microsoft/OSInfo
name: Microsoft/OSInfo-0
properties:
$id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json
family: macOS
version: 15.6.0
bitness: '64'
architecture: arm64
Basically, the same metadata would be at the top level. And you can override it at each resource level.
Another alternative would be to collect unsettable resources from export and insert them automatically into a Microsoft.Dsc/Assertion resource - which also clearly indicates to the reader of the exported document that this specific subset of resources can't be enforced, only audited. The main problem with this that I foresee is dependencies between instances defined in the input configuration document (I don't think exported resources currently have a way to indicate dependencies) and needing to do this processing after the resources have returned their exported instances but before emitting the result.
I'm not against implementing the metadata directive, but I do think that its reasonably easy for a user to call dsc config export and not immediately understand which exported resources are settable without looking up every exported resource. This problem is compounded by the use of exporter resources, where the user could relatively easily author a configuration for export without fully understanding every resource it's going to return.
Thinking about this, it might be cleaner to have export add a condition automatically when it knows that the resource doesn't support set, something like condition: "[not(equals(operation(), 'set'))]" where we would need an operation() function that simply returns the current operation
The working group discussed the scenario about running get for a particular resource while in a set operation. This would be used when one resource needs to get the output of another. The proposal would be to use the metadata property for the resource instance to tell the DSC engine to only run the get operation even if the resource can support set.
The working group discussed the possibility of using Bicep Exisitng. After investigation it was determined that this will not work for DSC. Including Steve's comments below:
_From talking to Bicep team, the fundamental thing is that existing leverages reference() with resourceid() to retrieve the instance so you can use it. The problem for DSC is that ARM uses name as an identity while dsc uses key properties for the identity. As such, the semantics don't line up and I don't think we want to enforce a syntax for name that specifies the key properties.
What this currently means is that existing as it's currently designed won't work for DSC._
The WG discussed this and propose metadata to indicate if a resource will be used always for get or test (the two metadata below are mutually exclusive). When assert is used and passes, then you can use reference() to retrieve it.
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
contentVersion: 1.0.0
resources:
- type: Microsoft/OSInfo
metadata:
Microsoft.DSC:
retrieve[ActualState]: true # get
assert[ActualState]: true # test
name: myOS
properties:
family: Windows
- type: Microsoft.Debug/Echo
name: example
condition: "[equals(reference(resourceId('Microsoft/OSInfo','myOS')).family,'Windows']"
properties:
output: Hello World