summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.markdown11
-rw-r--r--lib/puppet/functions/validate_legacy.rb54
-rw-r--r--spec/classes/validate_legacy_spec.rb39
-rw-r--r--spec/fixtures/test/manifests/validate_legacy.pp18
4 files changed, 122 insertions, 0 deletions
diff --git a/README.markdown b/README.markdown
index 0666b37..26fe55f 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1368,6 +1368,17 @@ The following values will fail, causing compilation to abort:
~~~
+#### `validate_legacy`
+
+Validates a value against both a specified type and a deprecated validation function. Silently passes if both pass, errors if one validation passes and the other does not, fails if both validations return false.
+Arguments include the type to check the value against, the full name of the previous validation function, the value itself to be checked, and an unspecified amount of arguments needed for the previous validation function.
+
+Example:
+
+ ~~~
+ validate_legacy("Optional[String]", "validate_re", "Value to be validated", ["."])
+ ~~~
+
#### `validate_numeric`
Validates that the first argument is a numeric value (or an array of numeric values). Aborts catalog compilation if any of the checks fail.
diff --git a/lib/puppet/functions/validate_legacy.rb b/lib/puppet/functions/validate_legacy.rb
new file mode 100644
index 0000000..9d7d012
--- /dev/null
+++ b/lib/puppet/functions/validate_legacy.rb
@@ -0,0 +1,54 @@
+Puppet::Functions.create_function(:validate_legacy, Puppet::Functions::InternalFunction) do
+ # The function checks a value against both the target_type (new) and the previous_validation function (old).
+
+ dispatch :validate_legacy do
+ param 'Type', :target_type
+ param 'String', :previous_validation
+ param 'NotUndef', :value
+ optional_param 'Any', :args
+ end
+ dispatch :validate_legacy_s do
+ scope_param
+ param 'String', :type_string
+ param 'String', :previous_validation
+ param 'NotUndef', :value
+ optional_repeated_param 'Any', :args
+ end
+
+ def validate_legacy_s(scope, type_string, *args)
+ t = Puppet::Pops::Types::TypeParser.new.parse(type_string, scope)
+ validate_legacy(t, *args)
+ end
+
+ def validate_legacy(target_type, previous_validation, value, *prev_args)
+ if assert_type(target_type, value)
+ if previous_validation(previous_validation, value, *prev_args)
+ # Silently passes
+ else
+ Puppet.warn("Accepting previously invalid value for target_type '#{target_type}'")
+ end
+ else
+ inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value)
+ error_msg = Puppet::Pops::Types::TypeMismatchDescriber.new.describe_mismatch(previous_validation, target_type, inferred_type)
+ if previous_validation(previous_validation, value, *prev_args)
+ Puppet.warn(error_msg)
+ else
+ call_function('fail', error_msg)
+ end
+ end
+ end
+
+ def previous_validation(previous_validation, value, *prev_args)
+ # Call the previous validation function and catch any errors. Return true if no errors are thrown.
+ begin
+ call_function(previous_validation, value, *prev_args)
+ true
+ rescue Puppet::ParseError
+ false
+ end
+ end
+
+ def assert_type(type, value)
+ Puppet::Pops::Types::TypeCalculator.instance?(type, value)
+ end
+end
diff --git a/spec/classes/validate_legacy_spec.rb b/spec/classes/validate_legacy_spec.rb
new file mode 100644
index 0000000..ded6890
--- /dev/null
+++ b/spec/classes/validate_legacy_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.0
+ # validate_legacy requires a proper scope to run, so we have to trigger a true compilation here,
+ # instead of being able to leverage the function test group.
+ describe 'test::validate_legacy', type: :class do
+
+ describe 'validate_legacy passes assertion of type but not previous validation' do
+ let(:params) {{ type: "Optional[Integer]", prev_validation: "validate_re", value: 5, previous_arg1: ["^\\d+$", ""] }}
+ it {
+ Puppet.expects(:warn).with(includes('Accepting previously invalid value for target_type'))
+ is_expected.to compile
+ }
+ end
+
+ describe 'validate_legacy passes assertion of type and previous validation' do
+ let(:params) {{ type: "Optional[String]", prev_validation: "validate_re", value: "5", previous_arg1: ["."] }}
+ it { is_expected.to compile }
+ end
+
+ describe 'validate_legacy fails assertion of type and passes previous validation' do
+ let(:params) {{ type: "Optional[Integer]", prev_validation: "validate_re", value: "5", previous_arg1: ["."] }}
+ it {
+ Puppet.expects(:warn).with(includes('expected'))
+ is_expected.to compile
+ }
+ end
+
+ describe 'validate_legacy fails assertion and fails previous validation' do
+ let(:params) {{ type: "Optional[Integer]", prev_validation: "validate_re", value: "5", previous_arg1: ["thisisnotright"] }}
+ it { is_expected.to compile.and_raise_error(/Error while evaluating a Function Call, \w* expected an \w* value, got \w*/) }
+ end
+
+ describe 'validate_legacy works with multi-argument validate_ functions' do
+ let(:params) {{ type: "Integer", prev_validation: "validate_integer", value: 10, previous_arg1: 100, previous_arg2: 0 }}
+ it { is_expected.to compile }
+ end
+ end
+end
diff --git a/spec/fixtures/test/manifests/validate_legacy.pp b/spec/fixtures/test/manifests/validate_legacy.pp
new file mode 100644
index 0000000..706df88
--- /dev/null
+++ b/spec/fixtures/test/manifests/validate_legacy.pp
@@ -0,0 +1,18 @@
+# Class to test stdlib validate_legacy function
+
+class test::validate_legacy(
+ $type,
+ $prev_validation,
+ $value,
+ $previous_arg1,
+ $previous_arg2 = undef,
+ ) {
+
+ if $previous_arg2 == undef {
+ validate_legacy( $type, $prev_validation, $value, $previous_arg1 )
+ } else {
+ validate_legacy( $type, $prev_validation, $value, $previous_arg1, $previous_arg2 )
+ }
+ notice("Success")
+
+}