[chef] Re: Multiple providers for a particular resource & Chef 12.4.x?


Chronological Thread 
  • From: Nathan Williams < >
  • To:
  • Subject: [chef] Re: Multiple providers for a particular resource & Chef 12.4.x?
  • Date: Wed, 8 Jul 2015 18:31:17 -0700

if i understand the question correctly, the way i’ve seen this done for resources is as an attribute, like resource.installation_method, and a provider that knows how to do both. if you want to separate the logic of package and source install, i’d move that out into helper modules or mixins, and use them appropriately based on inspection of the resource from the provider.

then to provide users the ability to use you’re resource-powered cookbook and still be able to control it via attributes, provide a recipe they can include with an attribute-driven instance of your resource, like

```
# recipes/default.rb
resource “name” do
  installation_method node[‘my_software’][‘installation_method’]
  version node[‘my_software’][‘version’]
  ...
end
```

HTH


Ohai chefs,

With the recent release of 12.4 (see blog post for specifics), a lot of changes have been happening around resolving resources to providers. I'm writing because, while I've seen a lot of examples for providers that are platform-specific, or completely override another provider, I haven't seen any examples where a user might want to select between providers using an attribute, where the providers aren't overriding one another.

My example is for software installation (names changed to protect the innocent). I have a resource, software_install, and it has an option for installation by package or by tarball. I have written two providers, one for package installs, and one for installation by tarball. I was using this snippet inside each provider to get the resolve to choose the correct one:

class << self
  def supports?(resource, action)
    resource.type == :package
  end
end

That snippet was inside the provider that supports package installs, and I've got a similar one for the tarball option. To complicate matters, due to this software not being in a repo, it has to be downloaded by deb or rpm for the package install, so I've also got `provides:` statements that control which provider is picked when the package install method is selected:

provides :software_install (in the provider that installs from source)
provides :software_install, platform_family: [ "debian", "ubuntu" ] (in the provider that installs from deb)
provides :software_install, platform_family: [ "rhel", "fedora" ] (in the provider that installs from rpm)

I had to make a distinction between deb/rpm because the package provider for debian/ubuntu is apt-based, which can't directly install debs (I had to use the dpkg_package resource there, and the package resource everywhere else).

So I'm wondering... what's the best way to still have platform-specific providers while still steering chef to a provider based on an attribute like 'type' (one of 'package', 'source'). Should I really have written two resources, instead of giving an attribute to control how the software is installed? Or should I write one huge provider that can install from source or package?

Or is it reasonable to have two providers that perform the same work in different ways, but don't override each other? In the last case, Chef is now warning that one of them is masking the selection of the other -- but I want the user to be able to choose using an attribute (overriding using 'provider Chef::Provider::Foo' is marginally worse, but the same problem).

Thanks in advance for any design advice you might have. I feel like provider selection is becoming more & more focused on platforms and platform families and platform versions, making it harder for me to write providers that all map to the same resource, but encapsulate different, but equally valid ways to perform the same task.

Cheers,

- Martin Smith




Archive powered by MHonArc 2.6.16.

§