I'm using Puppet to set up workstations and I want to modify the default (NTUSER.DAT) HKLM registry before the user logs on, which involves loading and unloading the hive. I have written some PowerShell scripts to facilitate the load/unload. Although I have three distinct actions, it appears that Puppet is trying to unload the hive before the registry
module can make all the changes. I believe I need to add some dependencies using subscribe
and refreshonly
.
This question is very similar to this one, with the exception that my data is in Hiera, therefore I want to iterate over the data.
$temp_hive_name = $base_windows::temp_hive_name
# LOAD REGISTRY HIVE
exec { 'load_registry_hive' :
command => template('base_windows/Load-RegHive.ps1.erb'),
unless => template('base_windows/Test-HiveLoadState.ps1.erb'),
provider => powershell,
logoutput => true,
}
# MODIFY REGISTRY, ITERATING OVER HIERA DATA
$base_windows::registry.each | $key, $value | {
registry::value { "registry_${key}" :
key => "${value['key']}\\${temp_hive_name}\\${value['subkey']}",
type => $value['type'],
data => $value['data'],
value => $value['value'],
}
}
# UNLOAD REGISTRY HIVE
exec { 'unload_registry_hive' :
command => template('base_windows/Unload-RegHive.ps1.erb'),
onlyif => template('base_windows/Test-HiveLoadState.ps1.erb'),
provider => powershell,
logoutput => true,
}
This works fine when there are one or two Hiera entries.
I guess I could put the load / unload exec resources into an .each
loop and add subscribe
and refreshonly
, however, it seems rather inefficient to do that for each item.
If anyone has any ideas, I'd be grateful if you could share?
T.I.A.
I believe I need to add some dependencies using
subscribe
andrefreshonly
.
I'm not so sure that you need to add dependencies, because without explicit dependencies, resources should be applied in the relative order in which they appear in the manifest. Additionally, refreshonly
does not declare a dependency, and subscribe
is probably not appropriate for this particular task. Furthermore, although refreshonly
works in conjunction with dependencies, it's probably not appropriate for this task, either, because notify
/ subscribe
is not right for it.
In a general sense, the key issues are these:
the hive must be loaded before you can attempt to sync any registry entries, so you cannot know whether any given registry resource is out of sync without loading the hive first;
if the hive is loaded then it must also be unloaded;
but the hive must not be unloaded before all the registry entries are synced.
You cannot make Exec['load_registry_hive']
refreshonly because there is no resource that would signal it. You can, however, check whether $base_windows::registry
has any elements as a precondition for doing any of the work. If it does, then you definitely need to load the hive.
You can set up explicit dependencies, and I'm generally inclined to do that, as it protects against surprises when a resource is affected by dependency edges that are not apparent at the point of its declaration. So I would suggest this:
$temp_hive_name = $base_windows::temp_hive_name
if ! $base_windows::registry.empty() {
# LOAD REGISTRY HIVE
exec { 'load_registry_hive' :
command => template('base_windows/Load-RegHive.ps1.erb'),
unless => template('base_windows/Test-HiveLoadState.ps1.erb'),
provider => powershell,
logoutput => true,
}
# MODIFY REGISTRY, ITERATING OVER HIERA DATA
$base_windows::registry.each | $key, $value | {
registry::value { "registry_${key}" :
key => "${value['key']}\\${temp_hive_name}\\${value['subkey']}",
type => $value['type'],
data => $value['data'],
value => $value['value'],
require => Exec['load_registry_hive'],
before => Exec['unload_registry_hive'],
}
}
# UNLOAD REGISTRY HIVE
exec { 'unload_registry_hive' :
command => template('base_windows/Unload-RegHive.ps1.erb'),
onlyif => template('base_windows/Test-HiveLoadState.ps1.erb'),
provider => powershell,
logoutput => true,
}
}
Note that you will necessarily both load and unload the hive on each Puppet run, because you cannot determine whether any entries need to be updated without doing so.