diff options
Diffstat (limited to 'lib/chef/provider/lwrp_base.rb')
-rw-r--r-- | lib/chef/provider/lwrp_base.rb | 135 |
1 files changed, 76 insertions, 59 deletions
diff --git a/lib/chef/provider/lwrp_base.rb b/lib/chef/provider/lwrp_base.rb index 0eadfe9467..38430ced6d 100644 --- a/lib/chef/provider/lwrp_base.rb +++ b/lib/chef/provider/lwrp_base.rb @@ -69,9 +69,6 @@ class Chef end - extend Chef::Mixin::ConvertToClassName - extend Chef::Mixin::FromFile - include Chef::DSL::Recipe # These were previously provided by Chef::Mixin::RecipeDefinitionDSLCore. @@ -80,72 +77,92 @@ class Chef include Chef::DSL::PlatformIntrospection include Chef::DSL::DataQuery - def self.build_from_file(cookbook_name, filename, run_context) - provider_class = nil - provider_name = filename_to_qualified_string(cookbook_name, filename) + # no-op `load_current_resource`. Allows simple LWRP providers to work + # without defining this method explicitly (silences + # Chef::Exceptions::Override exception) + def load_current_resource + end + + # class methods + class <<self + include Chef::Mixin::ConvertToClassName + include Chef::Mixin::FromFile + + def build_from_file(cookbook_name, filename, run_context) + if LWRPBase.loaded_lwrps[filename] + Chef::Log.info("LWRP provider #{filename} from cookbook #{cookbook_name} has already been loaded! Skipping the reload.") + return loaded_lwrps[filename] + end - class_name = convert_to_class_name(provider_name) + resource_name = filename_to_qualified_string(cookbook_name, filename) - if Chef::Provider.const_defined?(class_name, false) - Chef::Log.info("#{class_name} light-weight provider is already initialized -- Skipping loading #{filename}!") - Chef::Log.debug("Overriding already defined LWRPs is not supported anymore starting with Chef 12.") - provider_class = Chef::Provider.const_get(class_name) - else + # We load the class first to give it a chance to set its own name provider_class = Class.new(self) - Chef::Provider.const_set(class_name, provider_class) - provider_class.provides provider_name.to_sym + provider_class.provides resource_name.to_sym provider_class.class_from_file(filename) - Chef::Log.debug("Loaded contents of #{filename} into a provider named #{provider_name} defined in Chef::Provider::#{class_name}") - end - provider_class - end + # Respect resource_name set inside the LWRP + provider_class.instance_eval do + define_method(:to_s) do + "LWRP provider #{resource_name} from cookbook #{cookbook_name}" + end + define_method(:inspect) { to_s } + end - # Enables inline evaluation of resources in provider actions. - # - # Without this option, any resources declared inside the LWRP are added - # to the resource collection after the current position at the time the - # action is executed. Because they are added to the primary resource - # collection for the chef run, they can notify other resources outside - # the LWRP, and potentially be notified by resources outside the LWRP - # (but this is complicated by the fact that they don't exist until the - # provider executes). In this mode, it is impossible to correctly set the - # updated_by_last_action flag on the parent LWRP resource, since it - # executes and returns before its component resources are run. - # - # With this option enabled, each action creates a temporary run_context - # with its own resource collection, evaluates the action's code in that - # context, and then converges the resources created. If any resources - # were updated, then this provider's new_resource will be marked updated. - # - # In this mode, resources created within the LWRP cannot interact with - # external resources via notifies, though notifications to other - # resources within the LWRP will work. Delayed notifications are executed - # at the conclusion of the provider's action, *not* at the end of the - # main chef run. - # - # This mode of evaluation is experimental, but is believed to be a better - # set of tradeoffs than the append-after mode, so it will likely become - # the default in a future major release of Chef. - # - def self.use_inline_resources - extend InlineResources::ClassMethods - include InlineResources - end + Chef::Log.debug("Loaded contents of #{filename} into provider #{resource_name} (#{provider_class})") + + LWRPBase.loaded_lwrps[filename] = true - # DSL for defining a provider's actions. - def self.action(name, &block) - define_method("action_#{name}") do - instance_eval(&block) + Chef::Provider.register_deprecated_lwrp_class(provider_class, convert_to_class_name(resource_name)) + + provider_class end - end - # no-op `load_current_resource`. Allows simple LWRP providers to work - # without defining this method explicitly (silences - # Chef::Exceptions::Override exception) - def load_current_resource - end + # Enables inline evaluation of resources in provider actions. + # + # Without this option, any resources declared inside the LWRP are added + # to the resource collection after the current position at the time the + # action is executed. Because they are added to the primary resource + # collection for the chef run, they can notify other resources outside + # the LWRP, and potentially be notified by resources outside the LWRP + # (but this is complicated by the fact that they don't exist until the + # provider executes). In this mode, it is impossible to correctly set the + # updated_by_last_action flag on the parent LWRP resource, since it + # executes and returns before its component resources are run. + # + # With this option enabled, each action creates a temporary run_context + # with its own resource collection, evaluates the action's code in that + # context, and then converges the resources created. If any resources + # were updated, then this provider's new_resource will be marked updated. + # + # In this mode, resources created within the LWRP cannot interact with + # external resources via notifies, though notifications to other + # resources within the LWRP will work. Delayed notifications are executed + # at the conclusion of the provider's action, *not* at the end of the + # main chef run. + # + # This mode of evaluation is experimental, but is believed to be a better + # set of tradeoffs than the append-after mode, so it will likely become + # the default in a future major release of Chef. + # + def use_inline_resources + extend InlineResources::ClassMethods + include InlineResources + end + + # DSL for defining a provider's actions. + def action(name, &block) + define_method("action_#{name}") do + instance_eval(&block) + end + end + + protected + def loaded_lwrps + @loaded_lwrps ||= {} + end + end end end end |