]> gitweb.fluxo.info Git - puppet-stdlib.git/commitdiff
[MODULES-2462] Improve parseyaml function
authorDmitry Ilyin <dilyin@mirantis.com>
Mon, 24 Aug 2015 19:00:18 +0000 (22:00 +0300)
committerDmitry Ilyin <dilyin@mirantis.com>
Tue, 25 Aug 2015 18:41:03 +0000 (21:41 +0300)
* Add default value support
  Second argument will be returned if yaml cannot be parsed
  instead of false value
* Update tests

README.markdown
lib/puppet/parser/functions/parsejson.rb
lib/puppet/parser/functions/parseyaml.rb
spec/acceptance/parsejson_spec.rb
spec/acceptance/parseyaml_spec.rb
spec/functions/parsejson_spec.rb
spec/functions/parseyaml_spec.rb

index 8ed3d9b2492500ee9fc6bd74d7f0e840a100b471..2f84a24337ec88ff729586fbb8c6450a0a5aff9b 100644 (file)
@@ -490,10 +490,12 @@ Converts a number or a string representation of a number into a true boolean. Ze
 #### `parsejson`
 
 Converts a string of JSON into the correct Puppet structure. *Type*: rvalue.
+The optional second argument will be returned if the data was not correct.
 
 #### `parseyaml`
 
 Converts a string of YAML into the correct Puppet structure. *Type*: rvalue.
+The optional second argument will be returned if the data was not correct.
 
 #### `pick`
 
index a9a16a4524bce8cae03456ed6217f818c61911d0..f822fc473744f0d34856a3bbf3614eae1b4c6012 100644 (file)
@@ -3,21 +3,22 @@
 #
 
 module Puppet::Parser::Functions
-  newfunction(:parsejson, :type => :rvalue, :doc => <<-EOS
-This function accepts JSON as a string and converts into the correct Puppet
-structure.
-    EOS
+  newfunction(:parsejson, :type => :rvalue, :arity => -2, :doc => <<-EOS
+This function accepts JSON as a string and converts it into the correct
+Puppet structure.
+
+The optional second argument can be used to pass a default value that will
+be returned if the parsing of YAML string have failed.
+  EOS
   ) do |arguments|
+    raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1
 
-    if (arguments.size != 1) then
-      raise(Puppet::ParseError, "parsejson(): Wrong number of arguments "+
-        "given #{arguments.size} for 1")
+    begin
+      PSON::load(arguments[0]) || arguments[1]
+    rescue Exception
+      arguments[1]
     end
 
-    json = arguments[0]
-
-    # PSON is natively available in puppet
-    PSON.load(json)
   end
 end
 
index 53d54faff749099f6c7f663e3d840c0885094f1b..d38b3ef84c38ec3d8021847bd2bf4889336428a7 100644 (file)
@@ -3,20 +3,22 @@
 #
 
 module Puppet::Parser::Functions
-  newfunction(:parseyaml, :type => :rvalue, :doc => <<-EOS
+  newfunction(:parseyaml, :type => :rvalue, :arity => -2, :doc => <<-EOS
 This function accepts YAML as a string and converts it into the correct
 Puppet structure.
-    EOS
-  ) do |arguments|
-
-    if (arguments.size != 1) then
-      raise(Puppet::ParseError, "parseyaml(): Wrong number of arguments "+
-        "given #{arguments.size} for 1")
-    end
 
+The optional second argument can be used to pass a default value that will
+be returned if the parsing of YAML string have failed.
+  EOS
+  ) do |arguments|
+    raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1
     require 'yaml'
 
-    YAML::load(arguments[0])
+    begin
+      YAML::load(arguments[0]) || arguments[1]
+    rescue Exception
+      arguments[1]
+    end
 
   end
 end
index 509781027269edbbe6e0a16d0b631e897fafa788..d0feabd37baa4f9429f72f7035a6e95c20627523 100755 (executable)
@@ -16,19 +16,28 @@ describe 'parsejson function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('o
       end
     end
   end
+
   describe 'failure' do
     it 'raises error on incorrect json' do
       pp = <<-EOS
       $a = '{"hunter": "washere", "tests": "passing",}'
-      $ao = parsejson($a)
+      $ao = parsejson($a, {'tests' => 'using the default value'})
       notice(inline_template('a is <%= @ao.inspect %>'))
       EOS
 
-      apply_manifest(pp, :expect_failures => true) do |r|
-        expect(r.stderr).to match(/expected next name/)
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/tests are "using the default value"/)
       end
     end
 
-    it 'raises error on incorrect number of arguments'
+    it 'raises error on incorrect number of arguments' do
+      pp = <<-EOS
+      $o = parsejson()
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/wrong number of arguments/i)
+      end
+    end
   end
 end
index 5819837cfa1aaab11a66c4a42ab7e080d777b473..7946de09d04a28557dc34a6b1712a802c1f110da 100755 (executable)
@@ -16,20 +16,29 @@ describe 'parseyaml function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('o
       end
     end
   end
+
   describe 'failure' do
-    it 'raises error on incorrect yaml' do
+    it 'returns the default value on incorrect yaml' do
       pp = <<-EOS
       $a = "---\nhunter: washere\ntests: passing\n:"
-      $o = parseyaml($a)
+      $o = parseyaml($a, {'tests' => 'using the default value'})
       $tests = $o['tests']
       notice(inline_template('tests are <%= @tests.inspect %>'))
       EOS
 
-      apply_manifest(pp, :expect_failures => true) do |r|
-        expect(r.stderr).to match(/(syntax error|did not find expected key)/)
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/tests are "using the default value"/)
       end
     end
 
-    it 'raises error on incorrect number of arguments'
+    it 'raises error on incorrect number of arguments' do
+      pp = <<-EOS
+      $o = parseyaml()
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/wrong number of arguments/i)
+      end
+    end
   end
 end
index 436566e79c935622015a1e7c25435529c9f7ae13..5bea8af7fbcb2cdb809bad3318a6354049785638 100755 (executable)
@@ -1,9 +1,64 @@
 require 'spec_helper'
 
 describe 'parsejson' do
-  it { is_expected.not_to eq(nil) }
-  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
-  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
-  it { is_expected.to run.with_params('["one"').and_raise_error(PSON::ParserError) }
-  it { is_expected.to run.with_params('["one", "two", "three"]').and_return(['one', 'two', 'three']) }
+  it 'should exist' do
+    is_expected.not_to eq(nil)
+  end
+
+  it 'should raise an error if called without any arguments' do
+    is_expected.to run.with_params().
+                       and_raise_error(/wrong number of arguments/i)
+  end
+
+  context 'with correct JSON data' do
+
+    it 'should be able to parse a JSON data with a Hash' do
+      is_expected.to run.with_params('{"a":"1","b":"2"}').
+                         and_return({'a'=>'1', 'b'=>'2'})
+    end
+
+    it 'should be able to parse a JSON data with an Array' do
+      is_expected.to run.with_params('["a","b","c"]').
+                         and_return(['a', 'b', 'c'])
+    end
+
+    it 'should be able to parse empty JSON values' do
+      is_expected.to run.with_params('[]').
+                         and_return([])
+      is_expected.to run.with_params('{}').
+                         and_return({})
+    end
+
+    it 'should be able to parse a JSON data with a mixed structure' do
+      is_expected.to run.with_params('{"a":"1","b":2,"c":{"d":[true,false]}}').
+                         and_return({'a' =>'1', 'b' => 2, 'c' => { 'd' => [true, false] } })
+    end
+
+    it 'should not return the default value if the data was parsed correctly' do
+      is_expected.to run.with_params('{"a":"1"}', 'default_value').
+                         and_return({'a' => '1'})
+    end
+
+  end
+
+  context 'with incorrect YAML data' do
+    it 'should return "nil" if a default value should be returned but is not provided' do
+      is_expected.to run.with_params('').
+                         and_return(nil)
+    end
+
+    it 'should support a structure for a default value' do
+      is_expected.to run.with_params('', {'a' => '1'}).
+                         and_return({'a' => '1'})
+    end
+
+    ['', 1, 1.2, nil, true, false, [], {}, :yaml].each do |value|
+      it "should return the default value for an incorrect #{value.inspect} (#{value.class}) parameter" do
+        is_expected.to run.with_params(value, 'default_value').
+                           and_return('default_value')
+      end
+    end
+
+  end
+
 end
index fb635f8ee382ed4712d7d60148f7af30be96dc21..492a1c92119779fd34180fc666f1179a376840a5 100755 (executable)
@@ -1,14 +1,72 @@
 require 'spec_helper'
 
 describe 'parseyaml' do
-  it { is_expected.not_to eq(nil) }
-  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
-  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
-  it { is_expected.to run.with_params('["one", "two", "three"]').and_return(['one', 'two', 'three']) }
-  context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
-    it { is_expected.to run.with_params('["one"').and_raise_error(Psych::SyntaxError) }
+  it 'should exist' do
+    is_expected.not_to eq(nil)
   end
-  context 'when running on ruby 1.8.7, which does not have Psych', :if => RUBY_VERSION == '1.8.7' do
-    it { is_expected.to run.with_params('["one"').and_raise_error(ArgumentError) }
+
+  it 'should raise an error if called without any arguments' do
+    is_expected.to run.with_params().
+                       and_raise_error(/wrong number of arguments/i)
+  end
+
+  context 'with correct YAML data' do
+    it 'should be able to parse a YAML data with a String' do
+      is_expected.to run.with_params('--- just a string').
+                         and_return('just a string')
+      is_expected.to run.with_params('just a string').
+                         and_return('just a string')
+    end
+
+    it 'should be able to parse a YAML data with a Hash' do
+      is_expected.to run.with_params("---\na: '1'\nb: '2'\n").
+                         and_return({'a' => '1', 'b' => '2'})
+    end
+
+    it 'should be able to parse a YAML data with an Array' do
+      is_expected.to run.with_params("---\n- a\n- b\n- c\n").
+                         and_return(['a', 'b', 'c'])
+    end
+
+    it 'should be able to parse a YAML data with a mixed structure' do
+      is_expected.to run.with_params("---\na: '1'\nb: 2\nc:\n  d:\n  - :a\n  - true\n  - false\n").
+                         and_return({'a' => '1', 'b' => 2, 'c' => {'d' => [:a, true, false]}})
+    end
+
+    it 'should not return the default value if the data was parsed correctly' do
+      is_expected.to run.with_params("---\na: '1'\n", 'default_value').
+                         and_return({'a' => '1'})
+    end
+
   end
+
+  context 'with incorrect YAML data' do
+    it 'should return "nil" if a default value should be returned but is not provided' do
+      is_expected.to run.with_params('').
+                         and_return(nil)
+    end
+
+    it 'should support a structure for a default value' do
+      is_expected.to run.with_params('', {'a' => '1'}).
+                         and_return({'a' => '1'})
+    end
+
+    [1, 1.2, nil, true, false, [], {}, :yaml].each do |value|
+      it "should return the default value for an incorrect #{value.inspect} (#{value.class}) parameter" do
+        is_expected.to run.with_params(value, 'default_value').
+                           and_return('default_value')
+      end
+    end
+
+    context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
+      ['---', '...', '*8', ''].each do |value|
+        it "should return the default value for an incorrect #{value.inspect} string parameter" do
+          is_expected.to run.with_params(value, 'default_value').
+                             and_return('default_value')
+        end
+      end
+    end
+
+  end
+
 end