1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 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 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 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
|
# frozen_string_literal: true
require 'set'
require_relative '../../puppet/settings/errors'
# The base setting type
class Puppet::Settings::BaseSetting
attr_writer :default
attr_accessor :name, :desc, :section
attr_reader :short, :deprecated, :call_hook
# Hooks are called during different parts of the settings lifecycle:
#
# * :on_write_only - This is the default hook type. The hook will be called
# if its value is set in `main` or programmatically. If its value is set in
# a section that doesn't match the application's run mode, it will be
# ignored entirely. If the section does match the run mode, the value will
# be used, but the hook will not be called!
#
# * :on_define_and_write - The hook behaves the same as above, except it is
# also called immediately when the setting is defined in
# {Puppet::Settings.define_settings}. In that case, the hook receives the
# default value as specified.
#
# * :on_initialize_and_write - The hook will be called if the value is set in
# `main`, the section that matches the run mode, or programmatically.
#
HOOK_TYPES = Set.new([:on_define_and_write, :on_initialize_and_write, :on_write_only]).freeze
def self.available_call_hook_values
HOOK_TYPES.to_a
end
# Registers a hook to be called later based on the type of hook specified in `value`.
#
# @param value [Symbol] One of {HOOK_TYPES}
def call_hook=(value)
if value.nil?
# TRANSLATORS ':%{name}', ':call_hook', and ':on_write_only' should not be translated
Puppet.warning _("Setting :%{name} :call_hook is nil, defaulting to :on_write_only") % { name: name }
value = :on_write_only
end
unless HOOK_TYPES.include?(value)
# TRANSLATORS 'call_hook' is a Puppet option name and should not be translated
raise ArgumentError, _("Invalid option %{value} for call_hook") % { value: value }
end
@call_hook = value
end
# @see {HOOK_TYPES}
def call_hook_on_define?
call_hook == :on_define_and_write
end
# @see {HOOK_TYPES}
def call_hook_on_initialize?
call_hook == :on_initialize_and_write
end
# get the arguments in getopt format
def getopt_args
if short
[["--#{name}", "-#{short}", GetoptLong::REQUIRED_ARGUMENT]]
else
[["--#{name}", GetoptLong::REQUIRED_ARGUMENT]]
end
end
# get the arguments in OptionParser format
def optparse_args
if short
["--#{name}", "-#{short}", desc, :REQUIRED]
else
["--#{name}", desc, :REQUIRED]
end
end
def hook=(block)
@has_hook = true
meta_def :handle, &block
end
def has_hook?
@has_hook
end
# Create the new element. Pretty much just sets the name.
def initialize(args = {})
@settings = args.delete(:settings)
unless @settings
raise ArgumentError, "You must refer to a settings object"
end
# explicitly set name prior to calling other param= methods to provide meaningful feedback during
# other warnings
@name = args[:name] if args.include? :name
# set the default value for call_hook
@call_hook = :on_write_only if args[:hook] and !(args[:call_hook])
@has_hook = false
if args[:call_hook] and !(args[:hook])
# TRANSLATORS ':call_hook' and ':hook' are specific setting names and should not be translated
raise ArgumentError, _("Cannot reference :call_hook for :%{name} if no :hook is defined") % { name: @name }
end
args.each do |param, value|
method = param.to_s + "="
unless respond_to? method
raise ArgumentError, _("%{class_name} (setting '%{setting}') does not accept %{parameter}") %
{ class_name: self.class, setting: args[:name], parameter: param }
end
send(method, value)
end
unless desc
raise ArgumentError, _("You must provide a description for the %{class_name} config option") % { class_name: name }
end
end
def iscreated
@iscreated = true
end
def iscreated?
@iscreated
end
# short name for the element
def short=(value)
raise ArgumentError, _("Short names can only be one character.") if value.to_s.length != 1
@short = value.to_s
end
def default(check_application_defaults_first = false)
if @default.is_a? Proc
# Give unit tests a chance to reevaluate the call by removing the instance variable
unless instance_variable_defined?(:@evaluated_default)
@evaluated_default = @default.call
end
default_value = @evaluated_default
else
default_value = @default
end
return default_value unless check_application_defaults_first
@settings.value(name, :application_defaults, true) || default_value
end
# Convert the object to a config statement.
def to_config
require_relative '../../puppet/util/docs'
# Scrub any funky indentation; comment out description.
str = Puppet::Util::Docs.scrub(@desc).gsub(/^/, "# ") + "\n"
# Add in a statement about the default.
str << "# The default value is '#{default(true)}'.\n" if default(true)
# If the value has not been overridden, then print it out commented
# and unconverted, so it's clear that that's the default and how it
# works.
value = @settings.value(name)
if value != @default
line = "#{@name} = #{value}"
else
line = "# #{@name} = #{@default}"
end
str << (line + "\n")
# Indent
str.gsub(/^/, " ")
end
# @param bypass_interpolation [Boolean] Set this true to skip the
# interpolation step, returning the raw setting value. Defaults to false.
# @return [String] Retrieves the value, or if it's not set, retrieves the default.
# @api public
def value(bypass_interpolation = false)
@settings.value(name, nil, bypass_interpolation)
end
# Modify the value when it is first evaluated
def munge(value)
value
end
# Print the value for the user in a config compatible format
def print(value)
munge(value)
end
def set_meta(meta)
Puppet.notice("#{name} does not support meta data. Ignoring.")
end
def deprecated=(deprecation)
unless [:completely, :allowed_on_commandline].include?(deprecation)
# TRANSLATORS 'deprecated' is a Puppet setting and ':completely' and ':allowed_on_commandline' are possible values and should not be translated
raise ArgumentError, _("Unsupported deprecated value '%{deprecation}'.") % { deprecation: deprecation } +
' ' + _("Supported values for deprecated are ':completely' or ':allowed_on_commandline'")
end
@deprecated = deprecation
end
def deprecated?
!!@deprecated
end
# True if we should raise a deprecation_warning if the setting is submitted
# on the commandline or is set in puppet.conf.
def completely_deprecated?
@deprecated == :completely
end
# True if we should raise a deprecation_warning if the setting is found in
# puppet.conf, but not if the user sets it on the commandline
def allowed_on_commandline?
@deprecated == :allowed_on_commandline
end
def inspect
%Q(<#{self.class}:#{object_id} @name="#{@name}" @section="#{@section}" @default="#{@default}" @call_hook="#{@call_hook}">)
end
end
|