Class: Chef::Provider

Inherits:
Object
  • Object
show all
Extended by:
Mixin::Provides, DeprecatedLWRPClass
Includes:
Mixin::PowershellOut, Mixin::ShellOut, Mixin::WhyRun
Defined in:
lib/chef/provider.rb,
lib/chef/provider/env.rb,
lib/chef/provider/git.rb,
lib/chef/provider/log.rb,
lib/chef/provider/cron.rb,
lib/chef/provider/file.rb,
lib/chef/provider/link.rb,
lib/chef/provider/ohai.rb,
lib/chef/provider/user.rb,
lib/chef/provider/batch.rb,
lib/chef/provider/group.rb,
lib/chef/provider/mdadm.rb,
lib/chef/provider/mount.rb,
lib/chef/provider/deploy.rb,
lib/chef/provider/reboot.rb,
lib/chef/provider/script.rb,
lib/chef/provider/execute.rb,
lib/chef/provider/launchd.rb,
lib/chef/provider/package.rb,
lib/chef/provider/service.rb,
lib/chef/provider/user/pw.rb,
lib/chef/provider/cron/aix.rb,
lib/chef/provider/erl_call.rb,
lib/chef/provider/group/pw.rb,
lib/chef/provider/ifconfig.rb,
lib/chef/provider/template.rb,
lib/chef/provider/user/aix.rb,
lib/chef/provider/cron/unix.rb,
lib/chef/provider/directory.rb,
lib/chef/provider/group/aix.rb,
lib/chef/provider/lwrp_base.rb,
lib/chef/provider/mount/aix.rb,
lib/chef/provider/user/dscl.rb,
lib/chef/provider/apt_update.rb,
lib/chef/provider/breakpoint.rb,
lib/chef/provider/dsc_script.rb,
lib/chef/provider/group/dscl.rb,
lib/chef/provider/group/suse.rb,
lib/chef/provider/ruby_block.rb,
lib/chef/provider/subversion.rb,
lib/chef/provider/env/windows.rb,
lib/chef/provider/mount/mount.rb,
lib/chef/provider/osx_profile.rb,
lib/chef/provider/package/aix.rb,
lib/chef/provider/package/apt.rb,
lib/chef/provider/package/ips.rb,
lib/chef/provider/package/rpm.rb,
lib/chef/provider/package/yum.rb,
lib/chef/provider/remote_file.rb,
lib/chef/provider/service/aix.rb,
lib/chef/provider/dsc_resource.rb,
lib/chef/provider/file/content.rb,
lib/chef/provider/http_request.rb,
lib/chef/provider/ifconfig/aix.rb,
lib/chef/provider/package/dpkg.rb,
lib/chef/provider/registry_key.rb,
lib/chef/provider/service/init.rb,
lib/chef/provider/user/solaris.rb,
lib/chef/provider/user/useradd.rb,
lib/chef/provider/user/windows.rb,
lib/chef/provider/cookbook_file.rb,
lib/chef/provider/group/gpasswd.rb,
lib/chef/provider/group/usermod.rb,
lib/chef/provider/group/windows.rb,
lib/chef/provider/mount/solaris.rb,
lib/chef/provider/mount/windows.rb,
lib/chef/provider/group/groupadd.rb,
lib/chef/provider/group/groupmod.rb,
lib/chef/provider/package/pacman.rb,
lib/chef/provider/package/zypper.rb,
lib/chef/provider/service/debian.rb,
lib/chef/provider/service/macosx.rb,
lib/chef/provider/service/redhat.rb,
lib/chef/provider/service/simple.rb,
lib/chef/provider/windows_script.rb,
lib/chef/provider/deploy/revision.rb,
lib/chef/provider/ifconfig/debian.rb,
lib/chef/provider/ifconfig/redhat.rb,
lib/chef/provider/package/openbsd.rb,
lib/chef/provider/package/paludis.rb,
lib/chef/provider/package/portage.rb,
lib/chef/provider/package/smartos.rb,
lib/chef/provider/package/solaris.rb,
lib/chef/provider/package/windows.rb,
lib/chef/provider/remote_file/ftp.rb,
lib/chef/provider/resource_update.rb,
lib/chef/provider/service/aixinit.rb,
lib/chef/provider/service/freebsd.rb,
lib/chef/provider/service/insserv.rb,
lib/chef/provider/service/openbsd.rb,
lib/chef/provider/service/solaris.rb,
lib/chef/provider/service/upstart.rb,
lib/chef/provider/template_finder.rb,
lib/chef/provider/package/homebrew.rb,
lib/chef/provider/package/macports.rb,
lib/chef/provider/package/rubygems.rb,
lib/chef/provider/remote_directory.rb,
lib/chef/provider/remote_file/http.rb,
lib/chef/provider/template/content.rb,
lib/chef/provider/powershell_script.rb,
lib/chef/provider/service/invokercd.rb,
lib/chef/provider/deploy/timestamped.rb,
lib/chef/provider/package/chocolatey.rb,
lib/chef/provider/package/freebsd/pkg.rb,
lib/chef/provider/package/windows/exe.rb,
lib/chef/provider/package/windows/msi.rb,
lib/chef/provider/remote_file/content.rb,
lib/chef/provider/remote_file/fetcher.rb,
lib/chef/provider/package/easy_install.rb,
lib/chef/provider/package/freebsd/base.rb,
lib/chef/provider/package/freebsd/port.rb,
lib/chef/provider/cookbook_file/content.rb,
lib/chef/provider/package/freebsd/pkgng.rb,
lib/chef/provider/remote_file/local_file.rb,
lib/chef/provider/whyrun_safe_ruby_block.rb,
lib/chef/provider/remote_file/network_file.rb,
lib/chef/provider/remote_file/cache_control_data.rb,
lib/chef/provider/package/windows/registry_uninstall_entry.rb

Defined Under Namespace

Modules: DeprecatedLWRPClass, InlineResources Classes: AptUpdate, Batch, Breakpoint, CookbookFile, Cron, Deploy, Directory, DscResource, DscScript, Env, ErlCall, Execute, File, Git, Group, HttpRequest, Ifconfig, LWRPBase, Launchd, Link, Log, Mdadm, Mount, Ohai, OsxProfile, Package, PowershellScript, Reboot, RegistryKey, RemoteDirectory, RemoteFile, ResourceUpdate, Route, RubyBlock, Script, Service, Subversion, Template, TemplateFinder, User, WhyrunSafeRubyBlock, WindowsScript

Constant Summary

Constants included from Mixin::ShellOut

Mixin::ShellOut::DEPRECATED_OPTIONS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mixin::Provides

provided_as, provides, provides?

Methods included from Mixin::DescendantsTracker

#descendants, descendants, direct_descendants, #direct_descendants, find_descendants_by_name, #find_descendants_by_name, #inherited, store_inherited

Methods included from DeprecatedLWRPClass

const_missing, register_deprecated_lwrp_class

Methods included from Mixin::PowershellOut

#powershell_out, #powershell_out!

Methods included from Mixin::WindowsArchitectureHelper

#assert_valid_windows_architecture!, #disable_wow64_file_redirection, #forced_32bit_override_required?, #is_i386_process_on_x86_64_windows?, #node_supports_windows_architecture?, #node_windows_architecture, #restore_wow64_file_redirection, #valid_windows_architecture?, #with_os_architecture, #wow64_architecture_override_required?, #wow64_directory

Methods included from Mixin::ShellOut

#run_command_compatible_options, #shell_out, #shell_out!, #shell_out_with_systems_locale, #shell_out_with_systems_locale!

Constructor Details

#initialize(new_resource, run_context) ⇒ Provider

Returns a new instance of Provider.



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/chef/provider.rb', line 60

def initialize(new_resource, run_context)
  @new_resource = new_resource
  @action = action
  @current_resource = nil
  @run_context = run_context
  @converge_actions = nil

  @recipe_name = nil
  @cookbook_name = nil
  self.class.include_resource_dsl_module(new_resource)
end

Instance Attribute Details

#actionObject

– TODO: this should be a reader, and the action should be passed in the constructor; however, many/most subclasses override the constructor so changing the arity would be a breaking change. Change this at the next break, e.g., Chef 11.



58
59
60
# File 'lib/chef/provider.rb', line 58

def action
  @action
end

#cookbook_nameObject (readonly)

Returns the value of attribute cookbook_name.



51
52
53
# File 'lib/chef/provider.rb', line 51

def cookbook_name
  @cookbook_name
end

#current_resourceObject

Returns the value of attribute current_resource.



47
48
49
# File 'lib/chef/provider.rb', line 47

def current_resource
  @current_resource
end

#new_resourceObject

Returns the value of attribute new_resource.



46
47
48
# File 'lib/chef/provider.rb', line 46

def new_resource
  @new_resource
end

#recipe_nameObject (readonly)

Returns the value of attribute recipe_name.



50
51
52
# File 'lib/chef/provider.rb', line 50

def recipe_name
  @recipe_name
end

#run_contextObject

Returns the value of attribute run_context.



48
49
50
# File 'lib/chef/provider.rb', line 48

def run_context
  @run_context
end

Class Method Details

.include_resource_dsl(include_resource_dsl) ⇒ Object

Include attributes, public and protected methods from this Resource in the provider.

If this is set to true, delegate methods are included in the provider so that you can call (for example) ‘attrname` and it will call `new_resource.attrname`.

The actual include does not happen until the first time the Provider is instantiated (so that we don’t have to worry about load order issues).

Parameters:

  • include_resource_dsl (Boolean)

    Whether to include resource DSL or not (defaults to ‘false`).



269
270
271
# File 'lib/chef/provider.rb', line 269

def self.include_resource_dsl(include_resource_dsl)
  @include_resource_dsl = include_resource_dsl
end

.include_resource_dsl_module(resource) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Create the resource DSL module that forwards resource methods to new_resource



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/chef/provider.rb', line 276

def self.include_resource_dsl_module(resource)
  if @include_resource_dsl && !defined?(@included_resource_dsl_module)
    provider_class = self
    @included_resource_dsl_module = Module.new do
      extend Forwardable
      define_singleton_method(:to_s) { "forwarder module for #{provider_class}" }
      define_singleton_method(:inspect) { to_s }
      # Add a delegator for each explicit property that will get the *current* value
      # of the property by default instead of the *actual* value.
      resource.class.properties.each do |name, property|
        class_eval(<<-EOM, __FILE__, __LINE__)
          def #{name}(*args, &block)
            # If no arguments were passed, we process "get" by defaulting
            # the value to current_resource, not new_resource. This helps
            # avoid issues where resources accidentally overwrite perfectly
            # valid stuff with default values.
            if args.empty? && !block
              if !new_resource.property_is_set?(__method__) && current_resource
                return current_resource.public_send(__method__)
              end
            end
            new_resource.public_send(__method__, *args, &block)
          end
        EOM
      end
      dsl_methods =
        resource.class.public_instance_methods +
        resource.class.protected_instance_methods -
        provider_class.instance_methods -
        resource.class.properties.keys
      def_delegators(:new_resource, *dsl_methods)
    end
    include @included_resource_dsl_module
  end
end

.provides(short_name, opts = {}, &block) ⇒ Object



247
248
249
# File 'lib/chef/provider.rb', line 247

def self.provides(short_name, opts = {}, &block)
  Chef.provider_handler_map.set(short_name, self, opts, &block)
end

.provides?(node, resource) ⇒ Boolean

Returns:

  • (Boolean)


251
252
253
# File 'lib/chef/provider.rb', line 251

def self.provides?(node, resource)
  Chef::ProviderResolver.new(node, resource, :nothing).provided_by?(self)
end

.supports?(resource, action) ⇒ Boolean

supports the given resource and action (late binding)

Returns:

  • (Boolean)


42
43
44
# File 'lib/chef/provider.rb', line 42

def self.supports?(resource, action)
  true
end

.use_inline_resourcesObject

Enables inline evaluation of resources in provider actions.

Without this option, any resources declared inside the Provider 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 Provider, and potentially be notified by resources outside the Provider (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 Provider 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 Provider cannot interact with external resources via notifies, though notifications to other resources within the Provider 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.



339
340
341
342
# File 'lib/chef/provider.rb', line 339

def self.use_inline_resources
  extend InlineResources::ClassMethods
  include InlineResources
end

Instance Method Details

#action_nothingObject



106
107
108
109
# File 'lib/chef/provider.rb', line 106

def action_nothing
  Chef::Log.debug("Doing nothing for #{@new_resource}")
  true
end

#check_resource_semantics!Object



93
94
# File 'lib/chef/provider.rb', line 93

def check_resource_semantics!
end

#cleanup_after_convergeObject



103
104
# File 'lib/chef/provider.rb', line 103

def cleanup_after_converge
end

#converge_by(descriptions, &block) ⇒ Object



174
175
176
# File 'lib/chef/provider.rb', line 174

def converge_by(descriptions, &block)
  converge_actions.add_action(descriptions, &block)
end

#converge_if_changed(*properties, &converge_block) ⇒ Boolean

Handle patchy convergence safely.

  • Does not call the block if the current_resource’s properties match the properties the user specified on the resource.

  • Calls the block if current_resource does not exist

  • Calls the block if the user has specified any properties in the resource whose values are different from current_resource.

  • Does not call the block if why-run is enabled (just prints out text).

  • Prints out automatic green text saying what properties have changed.

Parameters:

  • properties

    An optional list of property names (symbols). If not specified, ‘new_resource.class.state_properties` will be used.

  • converge_block

    The block to do the converging in.

Returns:

  • (Boolean)

    whether the block was executed.



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/chef/provider.rb', line 195

def converge_if_changed(*properties, &converge_block)
  if !converge_block
    raise ArgumentError, "converge_if_changed must be passed a block!"
  end

  properties = new_resource.class.state_properties.map { |p| p.name } if properties.empty?
  properties = properties.map { |p| p.to_sym }
  if current_resource
    # Collect the list of modified properties
    specified_properties = properties.select { |property| new_resource.property_is_set?(property) }
    modified = specified_properties.select { |p| new_resource.send(p) != current_resource.send(p) }
    if modified.empty?
      properties_str = if sensitive
                         specified_properties.join(", ")
                       else
                         specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ")
                       end
      Chef::Log.debug("Skipping update of #{new_resource}: has not changed any of the specified properties #{properties_str}.")
      return false
    end

    # Print the pretty green text and run the block
    property_size = modified.map { |p| p.size }.max
    modified.map! do |p|
      properties_str = if sensitive
                         "(suppressed sensitive property)"
                       else
                         "#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})"
                       end
      "  set #{p.to_s.ljust(property_size)} to #{properties_str}"
    end
    converge_by([ "update #{current_resource.identity}" ] + modified, &converge_block)

  else
    # The resource doesn't exist. Mark that we are *creating* this, and
    # write down any properties we are setting.
    property_size = properties.map { |p| p.size }.max
    created = properties.map do |property|
      default = " (default value)" unless new_resource.property_is_set?(property)
      properties_str = if sensitive
                         "(suppressed sensitive property)"
                       else
                         new_resource.send(property).inspect
                       end
      "  set #{property.to_s.ljust(property_size)} to #{properties_str}#{default}"
    end

    converge_by([ "create #{new_resource.identity}" ] + created, &converge_block)
  end
  true
end

#define_resource_requirementsObject



100
101
# File 'lib/chef/provider.rb', line 100

def define_resource_requirements
end

#eventsObject



111
112
113
# File 'lib/chef/provider.rb', line 111

def events
  run_context.events
end

#load_current_resourceObject



96
97
98
# File 'lib/chef/provider.rb', line 96

def load_current_resource
  raise Chef::Exceptions::Override, "You must override load_current_resource in #{self}"
end

#nodeObject



80
81
82
# File 'lib/chef/provider.rb', line 80

def node
  run_context && run_context.node
end

#process_resource_requirementsObject



152
153
154
155
# File 'lib/chef/provider.rb', line 152

def process_resource_requirements
  requirements.run(:all_actions) unless @action == :nothing
  requirements.run(@action)
end

#requirementsObject



170
171
172
# File 'lib/chef/provider.rb', line 170

def requirements
  @requirements ||= ResourceRequirements.new(@new_resource, run_context)
end

#resource_collectionObject

Used by providers supporting embedded recipes



85
86
87
# File 'lib/chef/provider.rb', line 85

def resource_collection
  run_context && run_context.resource_collection
end

#resource_updated?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/chef/provider.rb', line 157

def resource_updated?
  !converge_actions.empty? || @new_resource.updated_by_last_action?
end

#run_action(action = nil) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/chef/provider.rb', line 115

def run_action(action = nil)
  @action = action unless action.nil?

  # TODO: it would be preferable to get the action to be executed in the
  # constructor...

  check_resource_semantics!

  # user-defined LWRPs may include unsafe load_current_resource methods that cannot be run in whyrun mode
  if whyrun_mode? && !whyrun_supported?
    events.resource_current_state_load_bypassed(@new_resource, @action, @current_resource)
  else
    load_current_resource
    events.resource_current_state_loaded(@new_resource, @action, @current_resource)
  end

  define_resource_requirements
  process_resource_requirements

  # user-defined providers including LWRPs may
  # not include whyrun support - if they don't support it
  # we can't execute any actions while we're running in
  # whyrun mode. Instead we 'fake' whyrun by documenting that
  # we can't execute the action.
  # in non-whyrun mode, this will still cause the action to be
  # executed normally.
  if whyrun_mode? && (!whyrun_supported? || requirements.action_blocked?(@action))
    events.resource_bypassed(@new_resource, @action, self)
  else
    send("action_#{@action}")
  end

  set_updated_status

  cleanup_after_converge
end

#set_updated_statusObject



161
162
163
164
165
166
167
168
# File 'lib/chef/provider.rb', line 161

def set_updated_status
  if !resource_updated?
    events.resource_up_to_date(@new_resource, @action)
  else
    events.resource_updated(@new_resource, @action)
    new_resource.updated_by_last_action(true)
  end
end

#whyrun_mode?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/chef/provider.rb', line 72

def whyrun_mode?
  Chef::Config[:why_run]
end

#whyrun_supported?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/chef/provider.rb', line 76

def whyrun_supported?
  false
end