Class: Chef::Provider::Link

Inherits:
Chef::Provider show all
Includes:
Mixin::EnforceOwnershipAndPermissions, Mixin::FileClass
Defined in:
lib/chef/provider/link.rb

Constant Summary

Constants included from Mixin::ShellOut

Mixin::ShellOut::DEPRECATED_OPTIONS

Instance Attribute Summary

Attributes inherited from Chef::Provider

#action, #cookbook_name, #current_resource, #new_resource, #recipe_name, #run_context

Instance Method Summary collapse

Methods included from Mixin::FileClass

#file_class

Methods included from Mixin::EnforceOwnershipAndPermissions

#access_controls, #enforce_ownership_and_permissions

Methods inherited from Chef::Provider

#action_nothing, #check_resource_semantics!, #cleanup_after_converge, #converge_by, #converge_if_changed, #events, include_resource_dsl, include_resource_dsl_module, #initialize, #node, #process_resource_requirements, provides, provides?, #requirements, #resource_collection, #resource_updated?, #run_action, #set_updated_status, supports?, use_inline_resources, #whyrun_mode?

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, #deprecated_constants, #register_deprecated_lwrp_class

Methods included from Mixin::LazyModuleInclude

#descendants, #include, #included

Methods included from Mixin::NotifyingBlock

#notifying_block, #subcontext_block

Methods included from DSL::DeclareResource

#build_resource, #declare_resource, #delete_resource, #delete_resource!, #edit_resource, #edit_resource!, #find_resource, #find_resource!, #with_run_context

Methods included from Mixin::ShellOut

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

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 DSL::PlatformIntrospection

#docker?, #platform?, #platform_family?, #value_for_platform, #value_for_platform_family

Constructor Details

This class inherits a constructor from Chef::Provider

Instance Method Details

#action_createObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
# File 'lib/chef/provider/link.rb', line 92

def action_create
  # current_resource is the symlink that currently exists
  # new_resource is the symlink we need to create
  #   to - the location to link to
  #   target_file - the name of the link

  if @current_resource.to != canonicalize(@new_resource.to) ||
      @current_resource.link_type != @new_resource.link_type
    # Handle the case where the symlink already exists and is pointing at a valid to_file
    if @current_resource.to
      # On Windows, to fix a symlink already pointing at a directory we must first
      # ::Dir.unlink the symlink (not the directory), while if we have a symlink
      # pointing at file we must use ::File.unlink on the symlink.
      # However if the new symlink will point to a file and the current symlink is pointing at a
      # directory we want to throw an exception and calling ::File.unlink on the directory symlink
      # will throw the correct ones.
      if Chef::Platform.windows? && ::File.directory?(@new_resource.to) &&
          ::File.directory?(@current_resource.target_file)
        converge_by("unlink existing windows symlink to dir at #{@new_resource.target_file}") do
          ::Dir.unlink(@new_resource.target_file)
        end
      else
        converge_by("unlink existing symlink to file at #{@new_resource.target_file}") do
          ::File.unlink(@new_resource.target_file)
        end
      end
    end
    if @new_resource.link_type == :symbolic
      converge_by("create symlink at #{@new_resource.target_file} to #{@new_resource.to}") do
        file_class.symlink(canonicalize(@new_resource.to), @new_resource.target_file)
        Chef::Log.debug("#{@new_resource} created #{@new_resource.link_type} link from #{@new_resource.target_file} -> #{@new_resource.to}")
        Chef::Log.info("#{@new_resource} created")
      end
    elsif @new_resource.link_type == :hard
      converge_by("create hard link at #{@new_resource.target_file} to #{@new_resource.to}") do
        file_class.link(@new_resource.to, @new_resource.target_file)
        Chef::Log.debug("#{@new_resource} created #{@new_resource.link_type} link from #{@new_resource.target_file} -> #{@new_resource.to}")
        Chef::Log.info("#{@new_resource} created")
      end
    end
  end
  if @new_resource.link_type == :symbolic
    if access_controls.requires_changes?
      converge_by(access_controls.describe_changes) do
        access_controls.set_all
      end
    end
  end
end

#action_deleteObject



142
143
144
145
146
147
148
149
# File 'lib/chef/provider/link.rb', line 142

def action_delete
  if @current_resource.to # Exists
    converge_by("delete link at #{@new_resource.target_file}") do
      ::File.delete(@new_resource.target_file)
      Chef::Log.info("#{@new_resource} deleted")
    end
  end
end

#canonicalize(path) ⇒ Object



88
89
90
# File 'lib/chef/provider/link.rb', line 88

def canonicalize(path)
  Chef::Platform.windows? ? path.tr("/", '\\') : path
end

#define_resource_requirementsObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/chef/provider/link.rb', line 73

def define_resource_requirements
  requirements.assert(:delete) do |a|
    a.assertion do
      if @current_resource.to
        @current_resource.link_type == @new_resource.link_type &&
          (@current_resource.link_type == :symbolic || @current_resource.to != "")
      else
        true
      end
    end
    a.failure_message Chef::Exceptions::Link, "Cannot delete #{@new_resource} at #{@new_resource.target_file}! Not a #{@new_resource.link_type} link."
    a.whyrun("Would assume the link at #{@new_resource.target_file} was previously created")
  end
end

#load_current_resourceObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/chef/provider/link.rb', line 49

def load_current_resource
  @current_resource = Chef::Resource::Link.new(@new_resource.name)
  @current_resource.target_file(@new_resource.target_file)
  if file_class.symlink?(@current_resource.target_file)
    @current_resource.link_type(:symbolic)
    @current_resource.to(
      canonicalize(file_class.readlink(@current_resource.target_file))
    )
  else
    @current_resource.link_type(:hard)
    if ::File.exists?(@current_resource.target_file)
      if ::File.exists?(@new_resource.to) &&
          file_class.stat(@current_resource.target_file).ino ==
              file_class.stat(@new_resource.to).ino
        @current_resource.to(canonicalize(@new_resource.to))
      else
        @current_resource.to("")
      end
    end
  end
  ScanAccessControl.new(@new_resource, @current_resource).set_all!
  @current_resource
end

Implementation components *should not* follow symlinks when managing access control (e.g., use lchmod instead of chmod) if the resource is a symlink.

Returns:

  • (Boolean)


154
155
156
# File 'lib/chef/provider/link.rb', line 154

def manage_symlink_access?
  @new_resource.link_type == :symbolic
end

#whyrun_supported?Boolean

Returns:

  • (Boolean)


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

def whyrun_supported?
  true
end