summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelen Campbell <helen@puppetlabs.com>2016-08-10 14:17:16 +0100
committerHelen Campbell <helen@puppetlabs.com>2016-08-11 18:59:15 +0100
commitadf922c28441bc95f5cbac1f0951256c080b3298 (patch)
tree709bcf434658a291ce9a87e3bc4639992141725b
parent999c267a3871c7d59513869c94c43c3477f1c6f1 (diff)
(WIP) Addition of validate legacy function
-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")
+
+}