cookbooks/fb_sysfs/resources/default.rb (70 lines of code) (raw):
#
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
#
# Copyright (c) 2016-present, Facebook, Inc.
# All rights reserved.
#
# 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.
#
default_action :set
property :path, String, :name_property => true
property :value, [String, Integer, :EINVAL], :required => true
property :type, Symbol, :required => true
property :ignore_einval, [true, false], :default => false
# allows clients to pass in a callback to be used instead of a direct read
property :read_method, Method, :required => false
action_class do
include FB::Sysfs::Provider
end
load_current_value do |new_resource|
# read normally when no custom read_method is present and path exists
if !new_resource.read_method && ::File.exist?(path)
begin
value ::File.read(path)
rescue SystemCallError => e
if e.errno == Errno::EINVAL::Errno
Chef::Log.debug("fb_sysfs: got EINVAL trying to read #{path}")
value :EINVAL
else
raise e
end
end
end
end
action :set do
if new_resource.read_method
update_needed = new_resource.read_method.call(node, new_resource.path,
new_resource.value)
unless [TrueClass, FalseClass].include?(update_needed.class)
fail 'fb_sysfs: read_method must return a boolean, got ' +
"#{update_needed.class}!"
end
if update_needed
Chef::Log.debug(
"fb_sysfs #{new_resource.path}: custom read method indicates update " +
'is needed',
)
converge_by("writing #{new_resource.value} to #{new_resource.path}") do
::File.write(new_resource.path, new_resource.value.to_s)
Chef::Log.debug("fb_sysfs #{new_resource.path}: value written " +
new_resource.value.to_s)
end
else
Chef::Log.debug(
"fb_sysfs #{new_resource.path}: custom read indicates no update is " +
'needed',
)
end
elsif current_resource.value == :EINVAL
if new_resource.ignore_einval
Chef::Log.warn("fb_sysfs: ignoring EINVAL on #{new_resource.path} as " +
'requested, resource will be left unmanaged!')
else
fail "fb_sysfs: got EINVAL on #{new_resource.path} and ignore_einval " +
'is false, aborting!'
end
elsif check(current_resource.value, new_resource.value, new_resource.type)
Chef::Log.debug(
"fb_sysfs #{new_resource.path}: Value set correctly, nothing to do. " +
"Current value: #{current_resource.value.inspect}",
)
else
# We are using file to write content, not to manage the file itself,
# so we exempt the internal foodcritic rule that requires owner/group/mode.
file new_resource.path do # ~FB023
if new_resource.type == :list
# Some :list sysfs require a newline at the end of the value to take
# effect. For others, the newline is ignored, so always write one (and
# only one) out regardless.
content "#{new_resource.value.to_s.chomp}\n"
else
content new_resource.value.to_s
end
end
end
end