diff options
Diffstat (limited to 'lib/chef/resource/alternatives.rb')
-rw-r--r-- | lib/chef/resource/alternatives.rb | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/lib/chef/resource/alternatives.rb b/lib/chef/resource/alternatives.rb new file mode 100644 index 0000000000..a2f08ad864 --- /dev/null +++ b/lib/chef/resource/alternatives.rb @@ -0,0 +1,149 @@ +# +# Copyright:: 2020, Chef Software Inc. +# Copyright:: 2016-2020, Virender Khatri +# +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../resource" + +class Chef + class Resource + class Alternatives < Chef::Resource + unified_mode true + + provides(:alternatives) { true } + + description "The alternatives resource allows for configuration of command alternatives in Linux using the alternatives or update-alternatives packages." + introduced "16.0" + + property :link_name, String, name_property: true + property :link, String, default: lazy { |n| "/usr/bin/#{n.link_name}" } + property :path, String + property :priority, [String, Integer], coerce: proc { |n| n.to_i } + + def define_resource_requirements + requirements.assert(:install) do |a| + a.assertion do + !new_resource.priority.nil? + end + + a.failure_message("Could not set alternatives for #{new_resource.link_name}, you must provide the :priority property") + end + + requirements.assert(:install, :set, :remove) do |a| + a.assertion do + !new_resource.path.nil? + end + + a.failure_message("Could not set alternatives for #{new_resource.link_name}, you must provide the :path property") + end + + requirements.assert(:install, :set, :remove) do |a| + a.assertion do + ::File.exist?(new_resource.path) + end + + a.whyrun("Assuming file #{new_resource.path} already exists or was created already") + a.failure_message("Could not set alternatives for #{new_resource.link_name}, missing #{new_resource.path}") + end + end + + action :install do + if path_priority != new_resource.priority + converge_by("adding alternative #{new_resource.link} #{new_resource.link_name} #{new_resource.path} #{new_resource.priority}") do + output = shell_out(alternatives_cmd, "--install", new_resource.link, new_resource.link_name, new_resource.path, new_resource.priority) + unless output.exitstatus == 0 + raise "failed to add alternative #{new_resource.link} #{new_resource.link_name} #{new_resource.path} #{new_resource.priority}" + end + end + end + end + + action :set do + if current_path != new_resource.path + converge_by("setting alternative #{new_resource.link_name} #{new_resource.path}") do + output = shell_out(alternatives_cmd, "--set", new_resource.link_name, new_resource.path) + unless output.exitstatus == 0 + raise "failed to set alternative #{new_resource.link_name} #{new_resource.path} \n #{output.stdout.strip}" + end + end + end + end + + action :remove do + if path_exists? + converge_by("removing alternative #{new_resource.link_name} #{new_resource.path}") do + shell_out(alternatives_cmd, "--remove", new_resource.link_name, new_resource.path) + end + end + end + + action :auto do + converge_by("setting auto alternative #{new_resource.link_name}") do + shell_out(alternatives_cmd, "--auto", new_resource.link_name) + end + end + + action :refresh do + converge_by("refreshing alternative #{new_resource.link_name}") do + shell_out(alternatives_cmd, "--refresh", new_resource.link_name) + end + end + + action_class do + # + # @return [String] The appropriate alternatives command based on the platform + # + def alternatives_cmd + if debian? + "update-alternatives" + else + "alternatives" + end + end + + # + # @return [Integer] The current path priority for the link_name alternative + # + def path_priority + # https://rubular.com/r/IcUlEU0mSNaMm3 + escaped_path = Regexp.new(Regexp.escape("#{new_resource.path} - priority ") + "(.*)") + match = shell_out(alternatives_cmd, "--display", new_resource.link_name).stdout.match(escaped_path) + + match.nil? ? nil : match[1].to_i + end + + # + # @return [String] The current path for the link_name alternative + # + def current_path + # https://rubular.com/r/ylsuvzUtquRPqc + match = shell_out(alternatives_cmd, "--display", new_resource.link_name).stdout.match(/link currently points to (.*)/) + match[1] + end + + # + # @return [Boolean] does the path exist for the link_name alternative + # + def path_exists? + # https://rubular.com/r/ogvDdq8h2IKRff + escaped_path = Regexp.new(Regexp.escape("#{new_resource.path} - priority")) + shell_out(alternatives_cmd, "--display", new_resource.link_name).stdout.match?(escaped_path) + end + end + end + end +end |