Resource installation validation

I am trying to understand how Chef on Windows but also unix, checks whether applications and packages specified in the cookbook are installed so it can skip any resource blocks in the recipe rather than attempt to just re-install over the top of an existing app or package. I see 3 scenarios for Windows according to the docs:

1. The source property is supplied with a value:
The docs for "package" or "windows_package" resources say that the "source" property if used should point to a package on the file system or URL. Is it looking for the exact file name installer executable with file extension or without?

package 'adobereader' do
   source C:\path\to\my\installer_file\adobereader.exe
end

windows_package 'adobereader' do
  source C:\path\to\my\installer_file\adobereader.exe
end

I don't see how this indicates installed vs not, but can see that it might be checking behind the scenes if the file exists.

2. Source property is NOT provided:
If the "source" property is not provided in the resource block, Chef uses the resource block name to associate with a file or URL. Filename with or without extension?

package 'adobereader' do
end

windows_package 'adobereader' do
end    

I don't see how this indicates installed vs not either, but can see that it might be checking behind the scenes if the file exists.

3. Resource block name, or "package_name" property matches DisplayName value in registry:
If no source property is provided, the display name of the resource block or a provided "package_name" property, instead of pointing to a installer filename on the file system or a URL, it should point to the DisplayName value matching an entry in any of the following registry hives:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

package 'Adobe Reader DC' do
  package_name 'Adobe Reader DC'
end

windows_package 'Adobe Reader DC' do
  package_name 'Adobe Reader DC'
end

If Chef does not find a file at the location or URL, does it automatically check the registry?
Checking the registry for this DisplayName does validate whether something is installed but ONLY IF the program registers it there. A lot of pre-req utilities and smaller apps/tools, don't publish there.

Further Questions:

  1. Are cookbook authors supposed to use notifies, guards, or script resources to do custom checks for whether software is installed?

  2. What about windows_features? Docs say nothing about whether the resource block name is checked against existing enabled DISM values. In addition DISM values differ from the Server Mgr GUI display name, for instance 'HTTPS Errors' is the name of the check box in the GUI and the DISM value is 'IIS-HttpErrors'. Both DISM and powershell cmdlets use the DISM values.

But the real question I have is it checking to see if it is installed or enabled? IF NOT, how does it not just re-install the feature and overwrite? If it is checking, shouldn't this be noted in the docs or listed somewhere with all the other resources that do that?

  1. What about package and the unix package managers, how does Chef work with them to validate installed or not before converging and re-installing or overwriting?

  2. Are there any other resources that function like windows_package to use the registry or some other source of installation validation? Or are all required to have custom guards, notifies, that have logic to check based on the author's knowledge of how to tell the app is installed?

  3. Where does the Ohai data get factored into the check? It does not contain installed information outside of the package attribute which is essentially the unistall registry DisplayName items.

  4. Is there some sort of mapping or cross reference chart that lists resources and the system item used to verify application installations or whether Chef should skip the resource in a cookbook every time the client runs?

No it is not intended that cookbook authors use notifies, guards or anything else to check whether software is installed, besides a package reference in the general case. On Windows specifically, you’ve brought up a scenario in which you may need to, but usually cookbook authors will try to wrapper those checks in a custom resource. Indeed you’ll see a lot of guards used in Windows cookbooks, not so much on Mac or the Unix variants.

A good example is the seven_zip cookbook, where it indeed adds an additional parameter for a file to check: https://github.com/windowschefcookbooks/seven_zip/blob/master/resources/tool.rb

And then it will also try to grab the install path out of SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths among other things to find the executable, not merely relying on the DisplayName.

However the author wrapped this in a custom resource so that other people could reuse this guard functionality without needing to remember to do it for that program. You’ll see this kind of thing a lot in Windows cookbooks.

The existence check is not as thorough as you might hope in actually checking for the existence of specific executables but it is usually (but not always) sufficient, except in the case you mention. There is no behind-the-scenes checking for file existence. It just checks to see that the “installer” ran successfully and assumes that the relevant files will be there.

On Windows the source attribute refers to the path or url for an installer to use when windows_package decides that the software is not present. It is not used in the existence check. This is a bit of a unix-ism in that on those systems the os is configured with default locations in which to look for the equivalent of installer executables (a.k.a. packages). On Windows you only get this if you use chocolatey or nuget or habitat (which I definitely recommend, as it solves a lot of these problems, but might not be an option for you).

windows_package does just rely on the DisplayName for the windows_package resource as pointed out in the docs. No dism or other behind-the-scenes checks. You are correct that this is not always reliable for supporting utilities that don’t register in these locations. This is also inheriting a unix-ism. That list is more reliable on those systems, as a list of installed “packages” is a more iron-clad existence check there. A windows equivalent is the chocolatey_package resource using chocolatey. This is a popular option for DevOps folks on Windows. If you install a Windows package via chocolatey it will be reflected in the ohai data in a more unix-style reliable fashion. Chocolatey makes sure that all the components that get installed register with it and that gets reflected in chai.

On the dism question, there is a windows_feature resource which you can use to do a DISM or powershell check. That’s new in Chef Client 14. But you’d have to call that before the windows_package resource for the scenario you mention.

My overall question was related to a mapping of which resources check for installed software and how Chef does that checking behind the scenes. It is not documented anywhere and seems like pretty necessary information as a cookbook author to prevent a lot of wasted exploration and changes once you find out the resource you chose doesn't in fact do that checking or validation.

WINDOWS:
The HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\ hive, does not contain every application installed, for instance the Chef client is not even registered there lol!. Several enterprise applications, like SQL Server, Visual Studio, MS Visual C++, .Net Core, Octopus Deploy, even VMware VMTools, and several other third party apps we use, don't register there.

You say, "On Windows the source attribute refers to the path or url for an installer to use when windows_package decides that the software(Chef??) is not present."

  1. HOW does Chef check whether the application pointed to in the "source" property is installed?

You say, "This is a bit of a unix-ism in that on those systems the os is configured with default locations in which to look for the equivalent of installer executable (a.k.a. packages)."

However, on Windows it is the installer that is configured by the developer to determine the installed path of the application. General Windows instruction [ https://docs.microsoft.com/en-us/windows/win32/shell/app-registration
] is that "app Paths" Registry hive, but with optional decisions, like per user or per machine. Even if Chef was trying to be thorough by checking both of these hives, It would miss several major enterprise applications as indicated above.

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\

UNIX:
Almost all apps on unix are registered in a local packages database which makes it easier. But, I have the same question, which Chef resources check for installed packages and how on unix?

Overall, is there documentation showing which Chef resources check for application installations and where so the author can make an informed choice on which resource to use and which one requires custom installation validation work?

Otherwise it is a stab in the dark and a lot of wasted time....

On nearly all the unix variants, the check for installed packages happens in the package resource provider. When the package name is passed to the package manager it does the check. Also since the same data is reflected in chai, there are guards in the various package resources to avoid calling the package manager in the cases where the overhead is high, only delegating to the package manager when it is more efficient or more accurate to do so.

Yes, the windows-package resource leaves a lot to be desired in this area the way it currently works in this area, afaik. The check is based against the DisplayName and only looks at the registry keys listed in the docs, last time I checked against the source.

I’m not aware of there being any detailed documentation on this. When I’ve wanted to know more detail, I’ve been looking at the source code on GitHub for the relevant chef resources.

Also because of this issue, the majority of my clients that I help with windows end up using a different package resource provider as a result. Most end up using chocolatey-package or a custom resource around nuget. Even if windows-package checked more registry locations, it wouldn’t solve some of the more fundamental issues with packaging on windows around ui-less installs needed for automation. Ymmv.

I had similar questions about "windows_firewall_rule" resource, so I debugged the latest client code after downloading.
https://packages.chef.io/files/stable/chef/15.4.45/windows/2019/chef-client-15.4.45-1-x64.msi

\opscode\chef\embedded\lib\ruby\gems\2.6.0\gems\chef-15.4.45-universal-mingw32\lib\chef\resource\windows_firewall_rule.rb
contains a method to "load_firewall_state" which selects all the properties of the windows firewall rule as they currently exist in the firewall configuration and stores them in variables. It then calls a method defined in provider.rb.

\opscode\chef\embedded\lib\ruby\gems\2.6.0\gems\chef-15.4.45-universal-mingw32\lib\chef\provider.rb
contains the definition for the method "converge_if_changed" which receives the properties, does comparison, and if any need updating, it does converge_by update.

The other resources [\opscode\chef\embedded\lib\ruby\gems\2.6.0\gems\chef-15.4.45-universal-mingw32\lib\chef\resources] that have a "load_current_value" method tied with a method that fetches or retreives current state are:

action_class.rb,
chocolatey_config.rb,
chocolatey_feature.rb,
chocolatey_source.rb,
dmg_package.rb,
macos_userdefaults.rb,
powershell_package_source.rb,
sysctl.rb,
windows_dfs_server.rb,
windows_printer.rb,
windows_printer_port.rb,
windows_share.rb,
windows_shortcut.rb

The other resources [\opscode\chef\embedded\lib\ruby\gems\2.6.0\gems\chef-15.4.45-universal-mingw32\lib\chef\resources] from this list above that also call the "converge_if_changed" method are:

chocolatey_config,
chocolatey_source,
powershell_package_source,
sysctl,
windows_dfs_server,
windows_share,
windows_shortcut

So these resources seem like they check existing state/values logic is built into the Chef source files.

Just searching across files, it looks like several providers also load current values so still trying to understand how that method in a provider interacts with or affects the resources.

It also looks like [\opscode\chef\embedded\lib\ruby\gems\2.6.0\gems\chef-15.4.45-universal-mingw32\spec\integration\recipes\resource_converge_if_changed_spec.rb] loads current values so trying to understand how that spec works with or affects resources.