Here is my scenario: I have a configuration that imports a number of composite resources. Several of these composite resources import the same resource module, also specifying a version with the -ModuleVersion parameter. Now I make a new version of that resource module, and in one of the composite resources I change the ModuleVersion imported. When attempting to compile the configuration, I get an error: “Resource name ‘xxxx’ is already being used by another Resource or Configuration”.
The only way to fix the issue is to change all the composite resources that reference that module so they import the same version of the module. I consider this a limitation, which sometimes becomes painful for us. We version everything, including composite resources. So because I change the version of a module referenced in one composite resource, I have to go and create new versions of half a dozen other composites that don’t really need the functionality of the new resource module version.
I was wondering if this was a limitation of DSC itself, or more of a limitation of how PowerShell compiles configurations. For instance, if I look at a resulting MOF, I see that each item has its own ModuleName and ModuleVersion property. That makes me think it should be possible to have different module versions referenced in the same config.
Ha, “jury rig” - that is exactly how composite resources struck me when I first encountered them. Surely there is a better way of providing for re-use of configs inside other configs. Ansible pulls it off elegantly with “roles”.
There are other ways, although not necessarily better. We cover them fairly well in “The DSC Book” in fact. I’m becoming a fan of having configuration “fragments” that are essentially dot-sourced together into a complete configuration, which then makes a MOF. There’s no automation for this, but as I find a “Push Server” mode a more alluring concept, it seems easy to implement. Tug (the open-source pull server project) would also enable that model. So instead of a MOF pretending to be a resource, you just merge together a bunch of artifacts based on a node’s role. There’s even a jury-rig where the node does that itself, a kind of self-modifying configuration where the initial MOF is just a custom resource that reaches out elsewhere, grabs a bunch of configuration fragments, merges them, runs it to produce a MOF, and then plants that MOF in the node’s own brain for the next run. I theorize about that in The DSC Book, also.
Thanks Don. After considering the options you mentioned, I think I’m going to abandon composite resources and go with something like the following:
-Create a library of configuration “fragments”. These will be formatted like configurations, but without the “Configuration {…}” part.
-Create configs as xml or json files. These will have two basic lists: 1) names and versions of composite resources to import, 2) fragments to include.
-Make a script that will parse the above file and create an actual DSC Configuration, and compile it. (This is actually a pretty simple script; it just creates import-DscResource commands at the top then pastes the fragments together.
The upsides: I get to specify module versions in a single place for an entire config. Fragments are dead simple to create and use (as opposed to composite resources). I can do cross-fragment dependencies if I want by simply putting them in the fragments.
The downsides: No more Intellisense or error-checking until I compile a config. Cross-fragment dependencies are admittedly hacky and hide the dependencies from the master xml/json config.