Skip to content

Commit aa8d57f

Browse files
author
Dmitry Ilyin
committed
Add the default value to the "loadyaml" function
This value will be returned if the is no file to load or a file could not be parsed. It's similar to the "parseyaml" function's default value. Add the "loadjson" function too
1 parent b63849c commit aa8d57f

File tree

7 files changed

+210
-18
lines changed

7 files changed

+210
-18
lines changed

README.markdown

+27-1
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,38 @@ Returns the keys of a hash as an array. *Type*: rvalue.
660660

661661
#### `loadyaml`
662662

663-
Loads a YAML file containing an array, string, or hash, and returns the data in the corresponding native data type. For example:
663+
Loads a YAML file containing an array, string, or hash, and returns the data in the corresponding native data type.
664+
For example:
664665

665666
~~~
666667
$myhash = loadyaml('/etc/puppet/data/myhash.yaml')
667668
~~~
668669

670+
The second parameter will be returned if the file was not found or could not be parsed.
671+
For example:
672+
673+
~~~
674+
$myhash = loadyaml('no-file.yaml', {'default'=>'value'})
675+
~~~
676+
677+
*Type*: rvalue.
678+
679+
#### `loadjson`
680+
681+
Loads a JSON file containing an array, string, or hash, and returns the data in the corresponding native data type.
682+
For example:
683+
684+
~~~
685+
$myhash = loadjson('/etc/puppet/data/myhash.json')
686+
~~~
687+
688+
The second parameter will be returned if the file was not found or could not be parsed.
689+
For example:
690+
691+
~~~
692+
$myhash = loadjson('no-file.json', {'default'=>'value'})
693+
~~~
694+
669695
*Type*: rvalue.
670696

671697
#### `load_module_metadata`
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module Puppet::Parser::Functions
2+
newfunction(:loadjson, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
3+
Load a JSON file containing an array, string, or hash, and return the data
4+
in the corresponding native data type.
5+
The second parameter is the default value. It will be returned if the file
6+
was not found or could not be parsed.
7+
8+
For example:
9+
10+
$myhash = loadjson('/etc/puppet/data/myhash.json')
11+
$myhash = loadjson('no-file.json', {'default' => 'value'})
12+
ENDHEREDOC
13+
14+
raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless args.length >= 1
15+
16+
if File.exists?(args[0])
17+
begin
18+
content = File.read(args[0])
19+
PSON::load(content) || args[1]
20+
rescue Exception => e
21+
if args[1]
22+
args[1]
23+
else
24+
raise e
25+
end
26+
end
27+
else
28+
warning("Can't load '#{args[0]}' File does not exist!")
29+
args[1]
30+
end
31+
32+
end
33+
34+
end

lib/puppet/parser/functions/loadyaml.rb

+23-14
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
module Puppet::Parser::Functions
2+
newfunction(:loadyaml, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
3+
Load a YAML file containing an array, string, or hash, and return the data
4+
in the corresponding native data type.
5+
The second parameter is the default value. It will be returned if the file
6+
was not found or could not be parsed.
27
3-
newfunction(:loadyaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
4-
Load a YAML file containing an array, string, or hash, and return the data
5-
in the corresponding native data type.
8+
For example:
69
7-
For example:
10+
$myhash = loadyaml('/etc/puppet/data/myhash.yaml')
11+
$myhash = loadyaml('no-file.yaml', {'default' => 'value'})
12+
ENDHEREDOC
813

9-
$myhash = loadyaml('/etc/puppet/data/myhash.yaml')
10-
ENDHEREDOC
14+
raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless args.length >= 1
15+
require 'yaml'
1116

12-
unless args.length == 1
13-
raise Puppet::ParseError, ("loadyaml(): wrong number of arguments (#{args.length}; must be 1)")
14-
end
15-
16-
if File.exists?(args[0]) then
17-
YAML.load_file(args[0])
17+
if File.exists?(args[0])
18+
begin
19+
YAML::load_file(args[0]) || args[1]
20+
rescue Exception => e
21+
if args[1]
22+
args[1]
23+
else
24+
raise e
25+
end
26+
end
1827
else
19-
warning("Can't load " + args[0] + ". File does not exist!")
20-
nil
28+
warning("Can't load '#{args[0]}' File does not exist!")
29+
args[1]
2130
end
2231

2332
end

spec/acceptance/loadjson_spec.rb

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#! /usr/bin/env ruby -S rspec
2+
require 'spec_helper_acceptance'
3+
4+
tmpdir = default.tmpdir('stdlib')
5+
6+
describe 'loadjson function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
7+
describe 'success' do
8+
it 'loadjsons array of values' do
9+
shell("echo '{\"aaa\":1,\"bbb\":2,\"ccc\":3,\"ddd\":4}' > #{tmpdir}/testjson.json")
10+
pp = <<-EOS
11+
$o = loadjson('#{tmpdir}/testjson.json')
12+
notice(inline_template('loadjson[aaa] is <%= @o["aaa"].inspect %>'))
13+
notice(inline_template('loadjson[bbb] is <%= @o["bbb"].inspect %>'))
14+
notice(inline_template('loadjson[ccc] is <%= @o["ccc"].inspect %>'))
15+
notice(inline_template('loadjson[ddd] is <%= @o["ddd"].inspect %>'))
16+
EOS
17+
18+
apply_manifest(pp, :catch_failures => true) do |r|
19+
expect(r.stdout).to match(/loadjson\[aaa\] is 1/)
20+
expect(r.stdout).to match(/loadjson\[bbb\] is 2/)
21+
expect(r.stdout).to match(/loadjson\[ccc\] is 3/)
22+
expect(r.stdout).to match(/loadjson\[ddd\] is 4/)
23+
end
24+
end
25+
26+
it 'returns the default value if there is no file to load' do
27+
pp = <<-EOS
28+
$o = loadjson('#{tmpdir}/no-file.json', {'default' => 'value'})
29+
notice(inline_template('loadjson[default] is <%= @o["default"].inspect %>'))
30+
EOS
31+
32+
apply_manifest(pp, :catch_failures => true) do |r|
33+
expect(r.stdout).to match(/loadjson\[default\] is "value"/)
34+
end
35+
end
36+
37+
it 'returns the default value if the file was parsed with an error' do
38+
shell("echo '!' > #{tmpdir}/testjson.json")
39+
pp = <<-EOS
40+
$o = loadjson('#{tmpdir}/testjson.json', {'default' => 'value'})
41+
notice(inline_template('loadjson[default] is <%= @o["default"].inspect %>'))
42+
EOS
43+
44+
apply_manifest(pp, :catch_failures => true) do |r|
45+
expect(r.stdout).to match(/loadjson\[default\] is "value"/)
46+
end
47+
end
48+
end
49+
describe 'failure' do
50+
it 'fails with no arguments'
51+
end
52+
end

spec/acceptance/loadyaml_spec.rb

+23
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,29 @@
2626
expect(r.stdout).to match(/loadyaml\[ddd\] is 4/)
2727
end
2828
end
29+
30+
it 'returns the default value if there is no file to load' do
31+
pp = <<-EOS
32+
$o = loadyaml('#{tmpdir}/no-file.yaml', {'default' => 'value'})
33+
notice(inline_template('loadyaml[default] is <%= @o["default"].inspect %>'))
34+
EOS
35+
36+
apply_manifest(pp, :catch_failures => true) do |r|
37+
expect(r.stdout).to match(/loadyaml\[default\] is "value"/)
38+
end
39+
end
40+
41+
it 'returns the default value if the file was parsed with an error' do
42+
shell("echo '!' > #{tmpdir}/testyaml.yaml")
43+
pp = <<-EOS
44+
$o = loadyaml('#{tmpdir}/testyaml.yaml', {'default' => 'value'})
45+
notice(inline_template('loadyaml[default] is <%= @o["default"].inspect %>'))
46+
EOS
47+
48+
apply_manifest(pp, :catch_failures => true) do |r|
49+
expect(r.stdout).to match(/loadyaml\[default\] is "value"/)
50+
end
51+
end
2952
end
3053
describe 'failure' do
3154
it 'fails with no arguments'

spec/functions/loadjson_spec.rb

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
require 'spec_helper'
2+
3+
describe 'loadjson' do
4+
it { is_expected.not_to eq(nil) }
5+
it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
6+
7+
context 'when a non-existing file is specified' do
8+
let(:filename) { '/tmp/doesnotexist' }
9+
before {
10+
File.expects(:exists?).with(filename).returns(false).once
11+
PSON.expects(:load).never
12+
}
13+
it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
14+
end
15+
16+
context 'when an existing file is specified' do
17+
let(:filename) { '/tmp/doesexist' }
18+
let(:data) { { 'key' => 'value' } }
19+
let(:json) { '{"key":"value"}' }
20+
before {
21+
File.expects(:exists?).with(filename).returns(true).once
22+
File.expects(:read).with(filename).returns(json).once
23+
PSON.expects(:load).with(json).returns(data).once
24+
}
25+
it { is_expected.to run.with_params(filename).and_return(data) }
26+
end
27+
28+
context 'when the file could not be parsed' do
29+
let(:filename) { '/tmp/doesexist' }
30+
let(:json) { '{"key":"value"}' }
31+
before {
32+
File.expects(:exists?).with(filename).returns(true).once
33+
File.expects(:read).with(filename).returns(json).once
34+
PSON.stubs(:load).with(json).once.raises StandardError, 'Something terrible have happened!'
35+
}
36+
it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
37+
end
38+
end

spec/functions/loadyaml_spec.rb

+13-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
describe 'loadyaml' do
44
it { is_expected.not_to eq(nil) }
5-
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
6-
it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
5+
it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
6+
77
context 'when a non-existing file is specified' do
88
let(:filename) { '/tmp/doesnotexist' }
99
before {
1010
File.expects(:exists?).with(filename).returns(false).once
1111
YAML.expects(:load_file).never
1212
}
13-
it { is_expected.to run.with_params(filename).and_return(nil) }
13+
it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
1414
end
15+
1516
context 'when an existing file is specified' do
1617
let(:filename) { '/tmp/doesexist' }
1718
let(:data) { { 'key' => 'value' } }
@@ -21,4 +22,13 @@
2122
}
2223
it { is_expected.to run.with_params(filename).and_return(data) }
2324
end
25+
26+
context 'when the file could not be parsed' do
27+
let(:filename) { '/tmp/doesexist' }
28+
before {
29+
File.expects(:exists?).with(filename).returns(true).once
30+
YAML.stubs(:load_file).with(filename).once.raises StandardError, 'Something terrible have happened!'
31+
}
32+
it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
33+
end
2434
end

0 commit comments

Comments
 (0)