Expose the functions of ruby's built-in Shellwords module (#580)
* Add shell_escape function, shell_join function & shell_split function
This commit is contained in:
parent
24797bb5ad
commit
9e1f74f3fc
7 changed files with 190 additions and 0 deletions
|
@ -821,6 +821,40 @@ Strips spaces to the right of the string. *Type*: rvalue.
|
|||
|
||||
Takes an integer max value and a string seed value and returns a repeatable random integer smaller than max. Like `fqdn_rand`, but does not add node specific data to the seed. *Type*: rvalue.
|
||||
|
||||
#### `shell_escape`
|
||||
|
||||
Escapes a string so that it can be safely used in a Bourne shell command line. Note that the resulting string should be used unquoted and is not intended for use in double quotes nor in single quotes. This function behaves the same as ruby's `Shellwords.shellescape()` function, also see the [ruby documentation](http://ruby-doc.org/stdlib-2.3.0/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape).
|
||||
|
||||
*Example:*
|
||||
~~~
|
||||
shell_escape('foo b"ar') => 'foo\ b\"ar'
|
||||
~~~
|
||||
|
||||
*Type*: rvalue.
|
||||
|
||||
#### `shell_join`
|
||||
|
||||
Builds a command line string from the given array of strings. Each array item is escaped for Bourne shell. All items are
|
||||
then joined together, with a single space in between. This function behaves the same as ruby's `Shellwords.shelljoin()` function, also see the [ruby documentation](http://ruby-doc.org/stdlib-2.3.0/libdoc/shellwords/rdoc/Shellwords.html#method-c-shelljoin).
|
||||
|
||||
*Example:*
|
||||
~~~
|
||||
shell_join(['foo bar', 'ba"z']) => 'foo\ bar ba\"z'
|
||||
~~~
|
||||
|
||||
*Type*: rvalue.
|
||||
|
||||
#### `shell_split`
|
||||
|
||||
Splits a string into an array of tokens in the same way the Bourne shell does. This function behaves the same as ruby's `Shellwords.shellsplit()` function, also see the [ruby documentation](http://ruby-doc.org/stdlib-2.3.0/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellsplit).
|
||||
|
||||
*Example:*
|
||||
~~~
|
||||
shell_split('foo\ bar ba\"z') => ['foo bar', 'ba"z']
|
||||
~~~
|
||||
|
||||
*Type*: rvalue.
|
||||
|
||||
#### `shuffle`
|
||||
|
||||
Randomizes the order of a string or array elements. *Type*: rvalue.
|
||||
|
|
30
lib/puppet/parser/functions/shell_escape.rb
Normal file
30
lib/puppet/parser/functions/shell_escape.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# shell_escape.rb
|
||||
#
|
||||
|
||||
require 'shellwords'
|
||||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:shell_escape, :type => :rvalue, :doc => <<-EOS
|
||||
Escapes a string so that it can be safely used in a Bourne shell command line.
|
||||
|
||||
Note that the resulting string should be used unquoted and is not intended for use in double quotes nor in single
|
||||
quotes.
|
||||
|
||||
This function behaves the same as ruby's Shellwords.shellescape() function.
|
||||
EOS
|
||||
) do |arguments|
|
||||
|
||||
raise(Puppet::ParseError, "shell_escape(): Wrong number of arguments " +
|
||||
"given (#{arguments.size} for 1)") if arguments.size != 1
|
||||
|
||||
# explicit conversion to string is required for ruby 1.9
|
||||
string = arguments[0].to_s
|
||||
|
||||
result = Shellwords.shellescape(string)
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
31
lib/puppet/parser/functions/shell_join.rb
Normal file
31
lib/puppet/parser/functions/shell_join.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# shell_join.rb
|
||||
#
|
||||
|
||||
require 'shellwords'
|
||||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:shell_join, :type => :rvalue, :doc => <<-EOS
|
||||
Builds a command line string from the given array of strings. Each array item is escaped for Bourne shell. All items are
|
||||
then joined together, with a single space in between.
|
||||
|
||||
This function behaves the same as ruby's Shellwords.shelljoin() function
|
||||
EOS
|
||||
) do |arguments|
|
||||
|
||||
raise(Puppet::ParseError, "shell_join(): Wrong number of arguments " +
|
||||
"given (#{arguments.size} for 1)") if arguments.size != 1
|
||||
|
||||
array = arguments[0]
|
||||
|
||||
raise Puppet::ParseError, ("First argument is not an Array: #{array.inspect}") unless array.is_a?(Array)
|
||||
|
||||
# explicit conversion to string is required for ruby 1.9
|
||||
array = array.map { |item| item.to_s }
|
||||
result = Shellwords.shelljoin(array)
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
26
lib/puppet/parser/functions/shell_split.rb
Normal file
26
lib/puppet/parser/functions/shell_split.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# shell_split.rb
|
||||
#
|
||||
|
||||
require 'shellwords'
|
||||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:shell_split, :type => :rvalue, :doc => <<-EOS
|
||||
Splits a string into an array of tokens in the same way the Bourne shell does.
|
||||
|
||||
This function behaves the same as ruby's Shellwords.shellsplit() function
|
||||
EOS
|
||||
) do |arguments|
|
||||
|
||||
raise(Puppet::ParseError, "shell_split(): Wrong number of arguments " +
|
||||
"given (#{arguments.size} for 1)") if arguments.size != 1
|
||||
|
||||
string = arguments[0].to_s
|
||||
|
||||
result = Shellwords.shellsplit(string)
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
# vim: set ts=2 sw=2 et :
|
22
spec/functions/shell_escape_spec.rb
Normal file
22
spec/functions/shell_escape_spec.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'shell_escape' do
|
||||
it { is_expected.not_to eq(nil) }
|
||||
|
||||
describe 'signature validation' do
|
||||
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
|
||||
it { is_expected.to run.with_params('foo', 'bar').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
|
||||
end
|
||||
|
||||
describe 'stringification' do
|
||||
it { is_expected.to run.with_params(10).and_return('10') }
|
||||
it { is_expected.to run.with_params(false).and_return('false') }
|
||||
end
|
||||
|
||||
describe 'escaping' do
|
||||
it { is_expected.to run.with_params('foo').and_return('foo') }
|
||||
it { is_expected.to run.with_params('foo bar').and_return('foo\ bar') }
|
||||
it { is_expected.to run.with_params('~`!@#$%^&*()_+-=[]\{}|;\':",./<>?')
|
||||
.and_return('\~\`\!@\#\$\%\^\&\*\(\)_\+-\=\[\]\\\\\{\}\|\;\\\':\",./\<\>\?') }
|
||||
end
|
||||
end
|
23
spec/functions/shell_join_spec.rb
Normal file
23
spec/functions/shell_join_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'shell_join' do
|
||||
it { is_expected.not_to eq(nil) }
|
||||
|
||||
describe 'signature validation' do
|
||||
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
|
||||
it { is_expected.to run.with_params(['foo'], ['bar']).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
|
||||
it { is_expected.to run.with_params('foo').and_raise_error(Puppet::ParseError, /is not an Array/i) }
|
||||
end
|
||||
|
||||
describe 'shell argument joining' do
|
||||
it { is_expected.to run.with_params(['foo']).and_return('foo') }
|
||||
it { is_expected.to run.with_params(['foo', 'bar']).and_return('foo bar') }
|
||||
it { is_expected.to run.with_params(['foo', 'bar baz']).and_return('foo bar\ baz') }
|
||||
it { is_expected.to run.with_params(['~`!@#$', '%^&*()_+-=', '[]\{}|;\':"', ',./<>?'])
|
||||
.and_return('\~\`\!@\#\$ \%\^\&\*\(\)_\+-\= \[\]\\\\\{\}\|\;\\\':\" ,./\<\>\?') }
|
||||
end
|
||||
|
||||
describe 'stringification' do
|
||||
it { is_expected.to run.with_params([10, false, 'foo']).and_return('10 false foo') }
|
||||
end
|
||||
end
|
24
spec/functions/shell_split_spec.rb
Normal file
24
spec/functions/shell_split_spec.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'shell_split' do
|
||||
it { is_expected.not_to eq(nil) }
|
||||
|
||||
describe 'signature validation' do
|
||||
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
|
||||
it { is_expected.to run.with_params('foo', 'bar').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
|
||||
end
|
||||
|
||||
describe 'stringification' do
|
||||
it { is_expected.to run.with_params(10).and_return(['10']) }
|
||||
it { is_expected.to run.with_params(false).and_return(['false']) }
|
||||
end
|
||||
|
||||
describe 'shell line spliting' do
|
||||
it { is_expected.to run.with_params('foo').and_return(['foo']) }
|
||||
it { is_expected.to run.with_params('foo bar').and_return(['foo', 'bar']) }
|
||||
it { is_expected.to run.with_params('\~\`\!@\#\$\%\^\&\*\(\)_\+-\=\[\]\\\\\{\}\|\;\\\':\",./\<\>\?')
|
||||
.and_return(['~`!@#$%^&*()_+-=[]\{}|;\':",./<>?']) }
|
||||
it { is_expected.to run.with_params('\~\`\!@\#\$ \%\^\&\*\(\)_\+-\= \[\]\\\\\{\}\|\;\\\':\" ,./\<\>\?')
|
||||
.and_return(['~`!@#$', '%^&*()_+-=', '[]\{}|;\':"', ',./<>?']) }
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue