diff options
43 files changed, 735 insertions, 249 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c33314..3b35d01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,59 @@ +##2015-08-13 - Supported Release 4.8.1 +###Summary + +Adds some new functions. + +####Features +- Add new functions: `dos2unix` and `unix2dos` + +####Bugfixes +- n/a + +####Improvements +- n/a + +## 2015-08-10 - Supported Release 4.8.0 +### Summary +This release adds a function for reading metadata.json from any module, and expands file\_line's abilities. + +#### Features +- New parameter `replace` on `file_line` +- New function `load_module_metadata()` to load metadata.json and return the content as a hash. +- Added hash support to `size()` + +#### Bugfixes +- Fix various docs typos +- Fix `file_line` resource on puppet < 3.3 + +##2015-06-22 - Supported Release 4.7.0 +###Summary + +Adds Solaris 12 support along with improved Puppet 4 support. There are significant test improvements, and some minor fixes. + +####Features +- Add support for Solaris 12 + +####Bugfixes +- Fix for AIO Puppet 4 +- Fix time for ruby 1.8.7 +- Specify rspec-puppet version +- range() fix for typeerror and missing functionality +- Fix pw_hash() on JRuby < 1.7.17 +- fqdn_rand_string: fix argument error message +- catch and rescue from looking up non-existent facts +- Use puppet_install_helper, for Puppet 4 + +####Improvements +- Enforce support for Puppet 4 testing +- fqdn_rotate/fqdn_rand_string acceptance tests and implementation +- Simplify mac address regex +- validate_integer, validate_numeric: explicitely reject hashes in arrays +- Readme edits +- Remove all the pops stuff for rspec-puppet +- Sync via modulesync +- Add validate_slength optional 3rd arg +- Move tests directory to examples directory + ##2015-04-14 - Supported Release 4.6.0 ###Summary @@ -32,9 +32,10 @@ group :system_tests do if beaker_rspec_version gem 'beaker-rspec', *location_for(beaker_rspec_version) else - gem 'beaker-rspec', :require => false + gem 'beaker-rspec', :require => false end - gem 'serverspec', :require => false + gem 'serverspec', :require => false + gem 'beaker-puppet_install_helper', :require => false end facterversion = ENV['GEM_FACTER_VERSION'] || ENV['FACTER_GEM_VERSION'] diff --git a/README.markdown b/README.markdown index 22bece8..a880222 100644 --- a/README.markdown +++ b/README.markdown @@ -99,6 +99,7 @@ All parameters are optional, unless otherwise noted. * `multiple`: Determines if `match` and/or `after` can change multiple lines. If set to false, an exception will be raised if more than one line matches. Valid options: 'true', 'false'. Default: Undefined. * `name`: Sets the name to use as the identity of the resource. This is necessary if you want the resource namevar to differ from the supplied `title` of the resource. Valid options: String. Default: Undefined. * `path`: **Required.** Defines the file in which Puppet will ensure the line specified by `line`. Must be an absolute path to the file. +* `replace`: Defines whether the resource will overwrite an existing line that matches the `match` parameter. If set to false and a line is found matching the `match` param, the line will not be placed in the file. Valid options: true, false, yes, no. Default: true ### Functions @@ -154,6 +155,12 @@ Appends the contents of multiple arrays onto the first array given. For example: * `concat(['1','2','3'],'4',['5','6','7'])` returns ['1','2','3','4','5','6','7']. *Type*: rvalue. +#### `convert_base` + +Converts a given integer or base 10 string representing an integer to a specified base, as a string. For example: + * `convert_base(5, 2)` results in: '101' + * `convert_base('254', '16')` results in: 'fe' + #### `count` If called with only an array, it counts the number of elements that are **not** nil/undef. If called with a second argument, counts the number of elements in an array that matches the second argument. *Type*: rvalue. @@ -198,6 +205,19 @@ Returns the difference between two arrays. The returned array is a copy of the o Returns the `dirname` of a path. For example, `dirname('/path/to/a/file.ext')` returns '/path/to/a'. *Type*: rvalue. +#### `dos2unix` + +Returns the Unix version of the given string. Very useful when using a File resource with a cross-platform template. *Type*: rvalue. + +~~~ +file{$config_file: + ensure => file, + content => dos2unix(template('my_module/settings.conf.erb')), +} +~~~ + +See also [unix2dos](#unix2dos). + #### `downcase` Converts the case of a string or of all strings in an array to lowercase. *Type*: rvalue. @@ -212,7 +232,7 @@ Takes a list of packages and only installs them if they don't already exist. It #### `ensure_resource` -Takes a resource type, title, and a list of attributes that describe a resource. +Takes a resource type, title, and a hash of attributes that describe the resource(s). ~~~ user { 'dan': @@ -449,6 +469,17 @@ Loads a YAML file containing an array, string, or hash, and returns the data in *Type*: rvalue. +#### `load_module_metadata` + +Loads the metadata.json of a target module. Can be used to determine module version and authorship for dynamic support of modules. + + ~~~ + $metadata = load_module_metadata('archive') + notify { $metadata['author']: } + ~~~ + +*Type*: rvalue. + #### `lstrip` Strips spaces to the left of a string. *Type*: rvalue. @@ -459,7 +490,7 @@ Returns the highest value of all arguments. Requires at least one argument. *Typ #### `member` -This function determines if a variable is a member of an array. The variable can be either a string, array, or fixnum. For example, `member(['a','b'], 'b')` and `member(['a','b','c'], ['b','c'])` return 'true', while `member(['a','b'], 'c')` and `member(['a','b','c'], ['c','d'])` return 'false'. *Note*: This function does not support nested arrays. If the first argument contains nested arrays, it will not recurse through them. +This function determines if a variable is a member of an array. The variable can be either a string, array, or fixnum. For example, `member(['a','b'], 'b')` and `member(['a','b','c'], ['b','c'])` return 'true', while `member(['a','b'], 'c')` and `member(['a','b','c'], ['c','d'])` return 'false'. *Note*: This function does not support nested arrays. If the first argument contains nested arrays, it will not recurse through them. *Type*: rvalue. @@ -507,10 +538,10 @@ From a list of values, returns the first value that is not undefined or an empty #### `prefix` -Applies a prefix to all elements in an array, or to the keys in a hash. -For example: +Applies a prefix to all elements in an array, or to the keys in a hash. +For example: * `prefix(['a','b','c'], 'p')` returns ['pa','pb','pc'] -* `prefix({'a'=>'b','b'=>'c','c'=>'d'}, 'p')` returns {'pa'=>'b','pb'=>'c','pc'=>'d'}. +* `prefix({'a'=>'b','b'=>'c','c'=>'d'}, 'p')` returns {'pa'=>'b','pb'=>'c','pc'=>'d'}. *Type*: rvalue. @@ -548,6 +579,8 @@ The second argument to this function is which type of hash to use. It will be co The third argument to this function is the salt to use. +*Type*: rvalue. + **Note:** this uses the Puppet master's implementation of crypt(3). If your environment contains several different operating systems, ensure that they are compatible before using this function. #### `range` @@ -578,7 +611,7 @@ Randomizes the order of a string or array elements. *Type*: rvalue. #### `size` -Returns the number of elements in a string or an array. *Type*: rvalue. +Returns the number of elements in a string, an array or a hash. *Type*: rvalue. #### `sort` @@ -713,12 +746,25 @@ Returns the literal type when passed a value. Requires the new parser. Useful fo #### `union` -Returns a union of two arrays, without duplicates. For example, `union(["a","b","c"],["b","c","d"])` returns ["a","b","c","d"]. +Returns a union of two or more arrays, without duplicates. For example, `union(["a","b","c"],["b","c","d"])` returns ["a","b","c","d"]. *Type*: rvalue. #### `unique` Removes duplicates from strings and arrays. For example, `unique("aabbcc")` returns 'abc', and `unique(["a","a","b","b","c","c"])` returns ["a","b","c"]. *Type*: rvalue. +#### `unix2dos` + +Returns the DOS version of the given string. Very useful when using a File resource with a cross-platform template. *Type*: rvalue. + +~~~ +file{$config_file: + ensure => file, + content => unix2dos(template('my_module/settings.conf.erb')), +} +~~~ + +See also [dos2unix](#dos2unix). + #### `upcase` Converts an object, array or hash of objects that respond to upcase to uppercase. For example, `upcase('abcd')` returns 'ABCD'. *Type*: rvalue. @@ -922,7 +968,7 @@ Validates that the first argument is an integer (or an array of integers). Abort * Plus all of the above, but any combination of values passed as strings ('false' or "false"). * Plus all of the above, but with incorrect combinations of negative integer values. - * Plus all of the above, but with non-integer crap in arrays or maximum / minimum argument. + * Plus all of the above, but with non-integer items in arrays or maximum / minimum argument. *Type*: statement. @@ -972,13 +1018,14 @@ test, and the second argument should be a stringified regular expression (withou #### `validate_slength` -Validates that the first argument is a string (or an array of strings), and is less than or equal to the length of the second argument. It fails if the first argument is not a string or array of strings, or if arg 2 is not convertable to a number. +Validates that the first argument is a string (or an array of strings), and is less than or equal to the length of the second argument. It fails if the first argument is not a string or array of strings, or if arg 2 is not convertable to a number. Optionally, a minimum string length can be given as the third argument. The following values pass: ~~~ validate_slength("discombobulate",17) validate_slength(["discombobulate","moo"],17) + validate_slength(["discombobulate","moo"],17,3) ~~~ The following values fail: @@ -986,6 +1033,7 @@ Validates that the first argument is a string (or an array of strings), and is l ~~~ validate_slength("discombobulate",1) validate_slength(["discombobulate","thermometer"],5) + validate_slength(["discombobulate","moo"],17,10) ~~~ *Type*: statement. @@ -1022,7 +1070,7 @@ Instead, use: #### `values` -Returns the values of a given hash. For example, given `$hash = {'a'=1, 'b'=2, 'c'=3} values($hash)` returns [1,2,3]. +Returns the values of a given hash. For example, given `$hash = {'a'=1, 'b'=2, 'c'=3} values($hash)` returns [1,2,3]. *Type*: rvalue. @@ -1053,6 +1101,7 @@ Versions | Puppet 2.6 | Puppet 2.7 | Puppet 3.x | Puppet 4.x | **stdlib 2.x** | **yes** | **yes** | no | no **stdlib 3.x** | no | **yes** | **yes** | no **stdlib 4.x** | no | **yes** | **yes** | no +**stdlib 4.6+** | no | **yes** | **yes** | **yes** **stdlib 5.x** | no | no | **yes** | **yes** **stdlib 5.x**: When released, stdlib 5.x will drop support for Puppet 2.7.x. Please see [this discussion](https://github.com/puppetlabs/puppetlabs-stdlib/pull/176#issuecomment-30251414). @@ -1067,7 +1116,3 @@ To report or research a bug with any part of this module, please go to ##Contributors The list of contributors can be found at: https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors - - - - diff --git a/tests/file_line.pp b/examples/file_line.pp index eea693e..85b1325 100644 --- a/tests/file_line.pp +++ b/examples/file_line.pp @@ -1,8 +1,8 @@ # This is a simple smoke test # of the file_line resource type. file { '/tmp/dansfile': - ensure => present -}-> + ensure => file, +} -> file_line { 'dans_line': line => 'dan is awesome', path => '/tmp/dansfile', diff --git a/tests/has_interface_with.pp b/examples/has_interface_with.pp index e1f1353..a578dd2 100644 --- a/tests/has_interface_with.pp +++ b/examples/has_interface_with.pp @@ -1,4 +1,4 @@ -include stdlib +include ::stdlib info('has_interface_with(\'lo\'):', has_interface_with('lo')) info('has_interface_with(\'loX\'):', has_interface_with('loX')) info('has_interface_with(\'ipaddress\', \'127.0.0.1\'):', has_interface_with('ipaddress', '127.0.0.1')) @@ -7,4 +7,3 @@ info('has_interface_with(\'network\', \'127.0.0.0\'):', has_interface_with('netw info('has_interface_with(\'network\', \'128.0.0.0\'):', has_interface_with('network', '128.0.0.0')) info('has_interface_with(\'netmask\', \'255.0.0.0\'):', has_interface_with('netmask', '255.0.0.0')) info('has_interface_with(\'netmask\', \'256.0.0.0\'):', has_interface_with('netmask', '256.0.0.0')) - diff --git a/tests/has_ip_address.pp b/examples/has_ip_address.pp index 8429a88..594143d 100644 --- a/tests/has_ip_address.pp +++ b/examples/has_ip_address.pp @@ -1,3 +1,3 @@ -include stdlib +include ::stdlib info('has_ip_address(\'192.168.1.256\'):', has_ip_address('192.168.1.256')) info('has_ip_address(\'127.0.0.1\'):', has_ip_address('127.0.0.1')) diff --git a/tests/has_ip_network.pp b/examples/has_ip_network.pp index a15d8c0..1f1130d 100644 --- a/tests/has_ip_network.pp +++ b/examples/has_ip_network.pp @@ -1,4 +1,3 @@ -include stdlib +include ::stdlib info('has_ip_network(\'127.0.0.0\'):', has_ip_network('127.0.0.0')) info('has_ip_network(\'128.0.0.0\'):', has_ip_network('128.0.0.0')) - diff --git a/examples/init.pp b/examples/init.pp new file mode 100644 index 0000000..ad27972 --- /dev/null +++ b/examples/init.pp @@ -0,0 +1 @@ +include ::stdlib diff --git a/lib/facter/root_home.rb b/lib/facter/root_home.rb index b4f87ff..ee3ffa8 100644 --- a/lib/facter/root_home.rb +++ b/lib/facter/root_home.rb @@ -30,3 +30,16 @@ Facter.add(:root_home) do hash['dir'].strip end end + +Facter.add(:root_home) do + confine :kernel => :aix + root_home = nil + setcode do + str = Facter::Util::Resolution.exec("lsuser -C -a home root") + str && str.split("\n").each do |line| + next if line =~ /^#/ + root_home = line.split(/:/)[1] + end + root_home + end +end diff --git a/lib/puppet/parser/functions/convert_base.rb b/lib/puppet/parser/functions/convert_base.rb new file mode 100644 index 0000000..0fcbafe --- /dev/null +++ b/lib/puppet/parser/functions/convert_base.rb @@ -0,0 +1,35 @@ +module Puppet::Parser::Functions + + newfunction(:convert_base, :type => :rvalue, :arity => 2, :doc => <<-'ENDHEREDOC') do |args| + + Converts a given integer or base 10 string representing an integer to a specified base, as a string. + + Usage: + + $binary_repr = convert_base(5, 2) # $binary_repr is now set to "101" + $hex_repr = convert_base("254", "16") # $hex_repr is now set to "fe" + + ENDHEREDOC + + raise Puppet::ParseError, ("convert_base(): First argument must be either a string or an integer") unless (args[0].is_a?(Integer) or args[0].is_a?(String)) + raise Puppet::ParseError, ("convert_base(): Second argument must be either a string or an integer") unless (args[1].is_a?(Integer) or args[1].is_a?(String)) + + if args[0].is_a?(String) + raise Puppet::ParseError, ("convert_base(): First argument must be an integer or a string corresponding to an integer in base 10") unless args[0] =~ /^[0-9]+$/ + end + + if args[1].is_a?(String) + raise Puppet::ParseError, ("convert_base(): First argument must be an integer or a string corresponding to an integer in base 10") unless args[1] =~ /^[0-9]+$/ + end + + number_to_convert = args[0] + new_base = args[1] + + number_to_convert = number_to_convert.to_i() + new_base = new_base.to_i() + + raise Puppet::ParseError, ("convert_base(): base must be at least 2 and must not be greater than 36") unless new_base >= 2 and new_base <= 36 + + return number_to_convert.to_s(new_base) + end +end diff --git a/lib/puppet/parser/functions/dos2unix.rb b/lib/puppet/parser/functions/dos2unix.rb new file mode 100644 index 0000000..ccac899 --- /dev/null +++ b/lib/puppet/parser/functions/dos2unix.rb @@ -0,0 +1,15 @@ +# Custom Puppet function to convert dos to unix format +module Puppet::Parser::Functions + newfunction(:dos2unix, :type => :rvalue, :arity => 1, :doc => <<-EOS + Returns the Unix version of the given string. + Takes a single string argument. + EOS + ) do |arguments| + + unless arguments[0].is_a?(String) + raise(Puppet::ParseError, 'dos2unix(): Requires string as argument') + end + + arguments[0].gsub(/\r\n/, "\n") + end +end diff --git a/lib/puppet/parser/functions/has_interface_with.rb b/lib/puppet/parser/functions/has_interface_with.rb index 3691524..e762798 100644 --- a/lib/puppet/parser/functions/has_interface_with.rb +++ b/lib/puppet/parser/functions/has_interface_with.rb @@ -38,8 +38,11 @@ has_interface_with("lo") => true # Bug with 3.7.1 - 3.7.3 when using future parser throws :undefined_variable # https://tickets.puppetlabs.com/browse/PUP-3597 factval = nil - catch :undefined_variable do - factval = lookupvar(kind) + begin + catch :undefined_variable do + factval = lookupvar(kind) + end + rescue Puppet::ParseError # Eat the exception if strict_variables = true is set end if factval == value return true diff --git a/lib/puppet/parser/functions/load_module_metadata.rb b/lib/puppet/parser/functions/load_module_metadata.rb new file mode 100644 index 0000000..0664a23 --- /dev/null +++ b/lib/puppet/parser/functions/load_module_metadata.rb @@ -0,0 +1,16 @@ +module Puppet::Parser::Functions + newfunction(:load_module_metadata, :type => :rvalue, :doc => <<-EOT + EOT + ) do |args| + raise(Puppet::ParseError, "load_module_metadata(): Wrong number of arguments, expects one") unless args.size == 1 + mod = args[0] + module_path = function_get_module_path([mod]) + metadata_json = File.join(module_path, 'metadata.json') + + raise(Puppet::ParseError, "load_module_metadata(): No metadata.json file for module #{mod}") unless File.exists?(metadata_json) + + metadata = PSON.load(File.read(metadata_json)) + + return metadata + end +end diff --git a/lib/puppet/parser/functions/size.rb b/lib/puppet/parser/functions/size.rb index cc207e3..0d6cc96 100644 --- a/lib/puppet/parser/functions/size.rb +++ b/lib/puppet/parser/functions/size.rb @@ -2,11 +2,9 @@ # size.rb # -# TODO(Krzysztof Wilczynski): Support for hashes would be nice too ... - module Puppet::Parser::Functions newfunction(:size, :type => :rvalue, :doc => <<-EOS -Returns the number of elements in a string or array. +Returns the number of elements in a string, an array or a hash EOS ) do |arguments| @@ -29,13 +27,13 @@ Returns the number of elements in a string or array. Float(item) raise(Puppet::ParseError, 'size(): Requires either ' + - 'string or array to work with') + 'string, array or hash to work with') rescue ArgumentError result = item.size end - elsif item.is_a?(Array) + elsif item.is_a?(Array) || item.is_a?(Hash) result = item.size else raise(Puppet::ParseError, 'size(): Unknown type given') diff --git a/lib/puppet/parser/functions/union.rb b/lib/puppet/parser/functions/union.rb index c91bb80..6c5bb83 100644 --- a/lib/puppet/parser/functions/union.rb +++ b/lib/puppet/parser/functions/union.rb @@ -4,7 +4,7 @@ module Puppet::Parser::Functions newfunction(:union, :type => :rvalue, :doc => <<-EOS -This function returns a union of two arrays. +This function returns a union of two or more arrays. *Examples:* @@ -14,20 +14,15 @@ Would return: ["a","b","c","d"] EOS ) do |arguments| - # Two arguments are required + # Check that 2 or more arguments have been given ... raise(Puppet::ParseError, "union(): Wrong number of arguments " + - "given (#{arguments.size} for 2)") if arguments.size != 2 + "given (#{arguments.size} for < 2)") if arguments.size < 2 - first = arguments[0] - second = arguments[1] - - unless first.is_a?(Array) && second.is_a?(Array) - raise(Puppet::ParseError, 'union(): Requires 2 arrays') + arguments.each do |argument| + raise(Puppet::ParseError, 'union(): Every parameter must be an array') unless argument.is_a?(Array) end - result = first | second - - return result + arguments.reduce(:|) end end diff --git a/lib/puppet/parser/functions/unix2dos.rb b/lib/puppet/parser/functions/unix2dos.rb new file mode 100644 index 0000000..0bd9cd1 --- /dev/null +++ b/lib/puppet/parser/functions/unix2dos.rb @@ -0,0 +1,15 @@ +# Custom Puppet function to convert unix to dos format +module Puppet::Parser::Functions + newfunction(:unix2dos, :type => :rvalue, :arity => 1, :doc => <<-EOS + Returns the DOS version of the given string. + Takes a single string argument. + EOS + ) do |arguments| + + unless arguments[0].is_a?(String) + raise(Puppet::ParseError, 'unix2dos(): Requires string as argument') + end + + arguments[0].gsub(/\r*\n/, "\r\n") + end +end diff --git a/lib/puppet/parser/functions/upcase.rb b/lib/puppet/parser/functions/upcase.rb index 0226a88..44b3bcd 100644 --- a/lib/puppet/parser/functions/upcase.rb +++ b/lib/puppet/parser/functions/upcase.rb @@ -12,7 +12,7 @@ Converts a string or an array of strings to uppercase. Will return: - ASDF + ABCD EOS ) do |arguments| diff --git a/lib/puppet/parser/functions/validate_integer.rb b/lib/puppet/parser/functions/validate_integer.rb index 95da0c4..a950916 100644 --- a/lib/puppet/parser/functions/validate_integer.rb +++ b/lib/puppet/parser/functions/validate_integer.rb @@ -49,7 +49,7 @@ module Puppet::Parser::Functions Plus all of the above, but any combination of values passed as strings ('false' or "false"). Plus all of the above, but with incorrect combinations of negative integer values. - Plus all of the above, but with non-integer crap in arrays or maximum / minimum argument. + Plus all of the above, but with non-integer items in arrays or maximum / minimum argument. ENDHEREDOC diff --git a/lib/puppet/parser/functions/validate_slength.rb b/lib/puppet/parser/functions/validate_slength.rb index 7d534f3..47c7d4a 100644 --- a/lib/puppet/parser/functions/validate_slength.rb +++ b/lib/puppet/parser/functions/validate_slength.rb @@ -3,7 +3,7 @@ module Puppet::Parser::Functions newfunction(:validate_slength, :doc => <<-'ENDHEREDOC') do |args| Validate that the first argument is a string (or an array of strings), and less/equal to than the length of the second argument. An optional third - parameter can be given a the minimum length. It fails if the first + parameter can be given the minimum length. It fails if the first argument is not a string or array of strings, and if arg 2 and arg 3 are not convertable to a number. @@ -43,9 +43,7 @@ module Puppet::Parser::Functions min_length = 0 end - if min_length > max_length - raise Puppet::ParseError, "validate_slength(): Expected second argument to be larger than third argument" - end + raise Puppet::ParseError, "validate_slength(): Expected second argument to be equal to or larger than third argument" unless max_length >= min_length validator = lambda do |str| unless str.length <= max_length and str.length >= min_length diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb index c58e27e..aab6fe2 100644 --- a/lib/puppet/provider/file_line/ruby.rb +++ b/lib/puppet/provider/file_line/ruby.rb @@ -1,24 +1,31 @@ Puppet::Type.type(:file_line).provide(:ruby) do def exists? - lines.find do |line| - line.chomp == resource[:line].chomp + if resource[:replace].to_s != 'true' and count_matches(match_regex) > 0 + true + else + lines.find do |line| + line.chomp == resource[:line].chomp + end end end def create - if resource[:match] - handle_create_with_match - elsif resource[:after] - handle_create_with_after - else - append_line + unless resource[:replace].to_s != 'true' and count_matches(match_regex) > 0 + if resource[:match] + handle_create_with_match + elsif resource[:after] + handle_create_with_after + else + append_line + end end end def destroy - local_lines = lines - File.open(resource[:path],'w') do |fh| - fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join('')) + if resource[:match_for_absence].to_s == 'true' and resource[:match] + handle_destroy_with_match + else + handle_destroy_line end end @@ -32,10 +39,13 @@ Puppet::Type.type(:file_line).provide(:ruby) do @lines ||= File.readlines(resource[:path]) end + def match_regex + resource[:match] ? Regexp.new(resource[:match]) : nil + end + def handle_create_with_match() - regex = resource[:match] ? Regexp.new(resource[:match]) : nil regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil - match_count = count_matches(regex) + match_count = count_matches(match_regex) if match_count > 1 && resource[:multiple].to_s != 'true' raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'" @@ -43,7 +53,7 @@ Puppet::Type.type(:file_line).provide(:ruby) do File.open(resource[:path], 'w') do |fh| lines.each do |l| - fh.puts(regex.match(l) ? resource[:line] : l) + fh.puts(match_regex.match(l) ? resource[:line] : l) if (match_count == 0 and regex_after) if regex_after.match(l) fh.puts(resource[:line]) @@ -84,6 +94,25 @@ Puppet::Type.type(:file_line).provide(:ruby) do lines.select{|l| l.match(regex)}.size end + def handle_destroy_with_match + match_count = count_matches(match_regex) + if match_count > 1 && resource[:multiple].to_s != 'true' + raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'" + end + + local_lines = lines + File.open(resource[:path],'w') do |fh| + fh.write(local_lines.reject{|l| match_regex.match(l) }.join('')) + end + end + + def handle_destroy_line + local_lines = lines + File.open(resource[:path],'w') do |fh| + fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join('')) + end + end + ## # append the line to the file. # diff --git a/lib/puppet/type/file_line.rb b/lib/puppet/type/file_line.rb index 29f9538..446f103 100644 --- a/lib/puppet/type/file_line.rb +++ b/lib/puppet/type/file_line.rb @@ -34,6 +34,20 @@ Puppet::Type.newtype(:file_line) do In this code example match will look for a line beginning with export followed by HTTP_PROXY and replace it with the value in line. + Match Example With `ensure => absent`: + + file_line { 'bashrc_proxy': + ensure => absent, + path => '/etc/bashrc', + line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128', + match => '^export\ HTTP_PROXY\=', + match_for_absence => true, + } + + In this code example match will look for a line beginning with export + followed by HTTP_PROXY and delete it. If multiple lines match, an + error will be raised unless the `multiple => true` parameter is set. + **Autorequires:** If Puppet is managing the file that will contain the line being managed, the file_line resource will autorequire that file. @@ -55,6 +69,14 @@ Puppet::Type.newtype(:file_line) do ' match an exception will be raised. ' end + newparam(:match_for_absence) do + desc 'An optional value to determine if match should be applied when ensure => absent.' + + ' If set to true and match is set, the line that matches match will be deleted.' + + ' If set to false (the default), match is ignored when ensure => absent.' + newvalues(true, false) + defaultto false + end + newparam(:multiple) do desc 'An optional value to determine if match can change multiple lines.' + ' If set to false, an exception will be raised if more than one line matches' @@ -78,6 +100,12 @@ Puppet::Type.newtype(:file_line) do end end + newparam(:replace) do + desc 'If true, replace line that matches. If false, do not write line if a match is found' + newvalues(true, false) + defaultto true + end + # Autorequire the file resource if it's being managed autorequire(:file) do self[:path] diff --git a/manifests/init.pp b/manifests/init.pp index 87ea975..9ea22a7 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -14,5 +14,5 @@ # Requires: nothing # class stdlib { - include stdlib::stages + include ::stdlib::stages } diff --git a/metadata.json b/metadata.json index eb06d5b..dab84e5 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-stdlib", - "version": "4.6.0", + "version": "4.8.0", "author": "puppetlabs", "summary": "Standard library of resources for Puppet modules.", "license": "Apache-2.0", @@ -104,7 +104,7 @@ }, { "name": "puppet", - "version_requirement": ">=2.7.20 <4.0.0" + "version_requirement": ">=2.7.20 <5.0.0" } ], "description": "Standard Library for Puppet Modules", diff --git a/spec/acceptance/ensure_packages_spec.rb b/spec/acceptance/ensure_packages_spec.rb deleted file mode 100755 index aedcfb5..0000000 --- a/spec/acceptance/ensure_packages_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper_acceptance' - -describe 'ensure_packages function', :unless => fact('osfamily') =~ /windows/i do - describe 'success' do - it 'ensure_packages a package' do - apply_manifest('package { "rake": ensure => absent, provider => "gem", }') - pp = <<-EOS - $a = "rake" - ensure_packages($a,{'provider' => 'gem'}) - EOS - - apply_manifest(pp, :expect_changes => true) - end - it 'ensures a package already declared' - it 'takes defaults arguments' - end - describe 'failure' do - it 'handles no arguments' - it 'handles non strings' - end -end diff --git a/spec/acceptance/ensure_resource_spec.rb b/spec/acceptance/ensure_resource_spec.rb index 1cee53d..fe619a9 100755 --- a/spec/acceptance/ensure_resource_spec.rb +++ b/spec/acceptance/ensure_resource_spec.rb @@ -1,7 +1,7 @@ #! /usr/bin/env ruby -S rspec require 'spec_helper_acceptance' -describe 'ensure_resource function', :unless => fact('osfamily') =~ /windows/i do +describe 'ensure_resource function', :unless => fact('osfamily') =~ /(windows|Suse)/i do describe 'success' do it 'ensure_resource a package' do apply_manifest('package { "rake": ensure => absent, provider => "gem", }') diff --git a/spec/acceptance/fqdn_rand_string_spec.rb b/spec/acceptance/fqdn_rand_string_spec.rb index 881cff3..9c6d701 100644 --- a/spec/acceptance/fqdn_rand_string_spec.rb +++ b/spec/acceptance/fqdn_rand_string_spec.rb @@ -3,80 +3,59 @@ require 'spec_helper_acceptance' describe 'fqdn_rand_string function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do describe 'success' do - let(:facts_d) do - if fact('is_pe', '--puppet') == "true" - if fact('osfamily') =~ /windows/i - if fact('kernelmajversion').to_f < 6.0 - 'c:/documents and settings/all users/application data/puppetlabs/facter/facts.d' - else - 'c:/programdata/puppetlabs/facter/facts.d' - end - else - '/etc/puppetlabs/facter/facts.d' - end - else - '/etc/facter/facts.d' - end - end - after :each do - shell("if [ -f '#{facts_d}/fqdn.txt' ] ; then rm '#{facts_d}/fqdn.txt' ; fi") - end - before :each do - #no need to create on windows, pe creates by default - if fact('osfamily') !~ /windows/i - shell("mkdir -p '#{facts_d}'") + include_context "with faked facts" + context "when the FQDN is 'fakehost.localdomain'" do + before :each do + fake_fact("fqdn", "fakehost.localdomain") end - end - it 'generates random alphanumeric strings' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-eos - $l = 10 - $o = fqdn_rand_string($l) - notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) - eos - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rand_string is "7oDp0KOr1b"/) + it 'generates random alphanumeric strings' do + pp = <<-eos + $l = 10 + $o = fqdn_rand_string($l) + notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) + eos + + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rand_string is "7oDp0KOr1b"/) + end end - end - it 'generates random alphanumeric strings with custom charsets' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-eos - $l = 10 - $c = '0123456789' - $o = fqdn_rand_string($l, $c) - notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) - eos + it 'generates random alphanumeric strings with custom charsets' do + pp = <<-eos + $l = 10 + $c = '0123456789' + $o = fqdn_rand_string($l, $c) + notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) + eos - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rand_string is "7203048515"/) + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rand_string is "7203048515"/) + end end - end - it 'generates random alphanumeric strings with custom seeds' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-eos - $l = 10 - $s = 'seed' - $o = fqdn_rand_string($l, undef, $s) - notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) - eos + it 'generates random alphanumeric strings with custom seeds' do + pp = <<-eos + $l = 10 + $s = 'seed' + $o = fqdn_rand_string($l, undef, $s) + notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) + eos - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rand_string is "3HS4mbuI3E"/) + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rand_string is "3HS4mbuI3E"/) + end end - end - it 'generates random alphanumeric strings with custom charsets and seeds' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-eos - $l = 10 - $c = '0123456789' - $s = 'seed' - $o = fqdn_rand_string($l, $c, $s) - notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) - eos + it 'generates random alphanumeric strings with custom charsets and seeds' do + pp = <<-eos + $l = 10 + $c = '0123456789' + $s = 'seed' + $o = fqdn_rand_string($l, $c, $s) + notice(inline_template('fqdn_rand_string is <%= @o.inspect %>')) + eos - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rand_string is "3104058232"/) + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rand_string is "3104058232"/) + end end end end diff --git a/spec/acceptance/fqdn_rotate_spec.rb b/spec/acceptance/fqdn_rotate_spec.rb index f1a15d3..404351f 100755 --- a/spec/acceptance/fqdn_rotate_spec.rb +++ b/spec/acceptance/fqdn_rotate_spec.rb @@ -3,78 +3,57 @@ require 'spec_helper_acceptance' describe 'fqdn_rotate function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do describe 'success' do - let(:facts_d) do - if fact('is_pe', '--puppet') == "true" - if fact('osfamily') =~ /windows/i - if fact('kernelmajversion').to_f < 6.0 - 'C:/Documents and Settings/All Users/Application Data/PuppetLabs/facter/facts.d' - else - 'C:/ProgramData/PuppetLabs/facter/facts.d' - end - else - '/etc/puppetlabs/facter/facts.d' - end - else - '/etc/facter/facts.d' - end - end - after :each do - shell("if [ -f '#{facts_d}/fqdn.txt' ] ; then rm '#{facts_d}/fqdn.txt' ; fi") - end - before :each do - #No need to create on windows, PE creates by default - if fact('osfamily') !~ /windows/i - shell("mkdir -p '#{facts_d}'") + include_context "with faked facts" + context "when the FQDN is 'fakehost.localdomain'" do + before :each do + fake_fact("fqdn", "fakehost.localdomain") end - end - it 'rotates arrays' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-EOS - $a = ['a','b','c','d'] - $o = fqdn_rotate($a) - notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) - EOS - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rotate is \["d", "a", "b", "c"\]/) + it 'rotates arrays' do + pp = <<-EOS + $a = ['a','b','c','d'] + $o = fqdn_rotate($a) + notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) + EOS + + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rotate is \["d", "a", "b", "c"\]/) + end end - end - it 'rotates arrays with custom seeds' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-EOS - $a = ['a','b','c','d'] - $s = 'seed' - $o = fqdn_rotate($a, $s) - notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) - EOS + it 'rotates arrays with custom seeds' do + pp = <<-EOS + $a = ['a','b','c','d'] + $s = 'seed' + $o = fqdn_rotate($a, $s) + notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) + EOS - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rotate is \["c", "d", "a", "b"\]/) + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rotate is \["c", "d", "a", "b"\]/) + end end - end - it 'rotates strings' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-EOS - $a = 'abcd' - $o = fqdn_rotate($a) - notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) - EOS + it 'rotates strings' do + pp = <<-EOS + $a = 'abcd' + $o = fqdn_rotate($a) + notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) + EOS - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rotate is "dabc"/) + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rotate is "dabc"/) + end end - end - it 'rotates strings with custom seeds' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-EOS - $a = 'abcd' - $s = 'seed' - $o = fqdn_rotate($a, $s) - notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) - EOS + it 'rotates strings with custom seeds' do + pp = <<-EOS + $a = 'abcd' + $s = 'seed' + $o = fqdn_rotate($a, $s) + notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) + EOS - apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/fqdn_rotate is "cdab"/) + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/fqdn_rotate is "cdab"/) + end end end end diff --git a/spec/acceptance/pw_hash_spec.rb b/spec/acceptance/pw_hash_spec.rb index eddb782..cd4cb87 100644 --- a/spec/acceptance/pw_hash_spec.rb +++ b/spec/acceptance/pw_hash_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper_acceptance' # Windows and OS X do not have useful implementations of crypt(3) -describe 'pw_hash function', :unless => (UNSUPPORTED_PLATFORMS + ['windows', 'Darwin']).include?(fact('operatingsystem')) do +describe 'pw_hash function', :unless => (UNSUPPORTED_PLATFORMS + ['windows', 'Darwin', 'SLES']).include?(fact('operatingsystem')) do describe 'success' do it 'hashes passwords' do pp = <<-EOS diff --git a/spec/acceptance/union_spec.rb b/spec/acceptance/union_spec.rb index 6db8d0c..160fd7b 100755 --- a/spec/acceptance/union_spec.rb +++ b/spec/acceptance/union_spec.rb @@ -6,9 +6,10 @@ describe 'union function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('opera it 'unions arrays' do pp = <<-EOS $a = ["the","public"] - $b = ["art","galleries"] + $b = ["art"] + $c = ["galleries"] # Anagram: Large picture halls, I bet - $o = union($a,$b) + $o = union($a,$b,$c) notice(inline_template('union is <%= @o.inspect %>')) EOS diff --git a/spec/fixtures/lsuser/root b/spec/fixtures/lsuser/root new file mode 100644 index 0000000..afd59ca --- /dev/null +++ b/spec/fixtures/lsuser/root @@ -0,0 +1,2 @@ +#name:home +root:/root diff --git a/spec/functions/base64_spec.rb b/spec/functions/base64_spec.rb index 42512b3..c529e9e 100755 --- a/spec/functions/base64_spec.rb +++ b/spec/functions/base64_spec.rb @@ -10,6 +10,7 @@ describe 'base64' do it { is_expected.to run.with_params("encode", 2).and_raise_error(Puppet::ParseError, /second argument must be a string/) } it { is_expected.to run.with_params("encode", "thestring").and_return("dGhlc3RyaW5n\n") } + it { is_expected.to run.with_params("encode", "a very long string that will cause the base64 encoder to produce output with multiple lines").and_return("YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0\nIGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5l\ncw==\n") } it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n").and_return("thestring") } it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n\n").and_return("thestring") } end diff --git a/spec/functions/convert_base_spec.rb b/spec/functions/convert_base_spec.rb new file mode 100644 index 0000000..8ab2284 --- /dev/null +++ b/spec/functions/convert_base_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'convert_base' do + it { is_expected.not_to eq(nil) } + it { is_expected.to run.with_params().and_raise_error(ArgumentError) } + it { is_expected.to run.with_params("asdf").and_raise_error(ArgumentError) } + it { is_expected.to run.with_params("asdf","moo","cow").and_raise_error(ArgumentError) } + it { is_expected.to run.with_params(["1"],"2").and_raise_error(Puppet::ParseError, /argument must be either a string or an integer/) } + it { is_expected.to run.with_params("1",["2"]).and_raise_error(Puppet::ParseError, /argument must be either a string or an integer/) } + it { is_expected.to run.with_params("1",1).and_raise_error(Puppet::ParseError, /base must be at least 2 and must not be greater than 36/) } + it { is_expected.to run.with_params("1",37).and_raise_error(Puppet::ParseError, /base must be at least 2 and must not be greater than 36/) } + + it "should raise a ParseError if argument 1 is a string that does not correspond to an integer in base 10" do + is_expected.to run.with_params("ten",6).and_raise_error(Puppet::ParseError, /argument must be an integer or a string corresponding to an integer in base 10/) + end + + it "should raise a ParseError if argument 2 is a string and does not correspond to an integer in base 10" do + is_expected.to run.with_params(100,"hex").and_raise_error(Puppet::ParseError, /argument must be an integer or a string corresponding to an integer in base 10/) + end + + it { is_expected.to run.with_params("11",'16').and_return('b') } + it { is_expected.to run.with_params("35",'36').and_return('z') } + it { is_expected.to run.with_params(5, 2).and_return('101') } +end diff --git a/spec/functions/dos2unix_spec.rb b/spec/functions/dos2unix_spec.rb new file mode 100644 index 0000000..9c84703 --- /dev/null +++ b/spec/functions/dos2unix_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe 'dos2unix' do + context 'Checking parameter validity' do + it { is_expected.not_to eq(nil) } + it do + is_expected.to run.with_params.and_raise_error(ArgumentError, /Wrong number of arguments/) + end + it do + is_expected.to run.with_params('one', 'two').and_raise_error(ArgumentError, /Wrong number of arguments/) + end + it do + is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) + end + it do + is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError) + end + it do + is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) + end + end + + context 'Converting from dos to unix format' do + sample_text = "Hello\r\nWorld\r\n" + desired_output = "Hello\nWorld\n" + + it 'should output unix format' do + should run.with_params(sample_text).and_return(desired_output) + end + end + + context 'Converting from unix to unix format' do + sample_text = "Hello\nWorld\n" + desired_output = "Hello\nWorld\n" + + it 'should output unix format' do + should run.with_params(sample_text).and_return(desired_output) + end + end +end diff --git a/spec/functions/load_module_metadata.rb b/spec/functions/load_module_metadata.rb new file mode 100755 index 0000000..ba542eb --- /dev/null +++ b/spec/functions/load_module_metadata.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe 'load_module_metadata' 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("one", "two").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) } + + it "should json parse the file" do + allow(scope).to receive(:function_get_module_path).with(['science']).and_return('/path/to/module/') + allow(File).to receive(:exists?).with(/metadata.json/).and_return(true) + allow(File).to receive(:read).with(/metadata.json/).and_return('{"name": "spencer-science"}') + + result = subject.call(['science']) + expect(result['name']).to eq('spencer-science') + end +end diff --git a/spec/functions/size_spec.rb b/spec/functions/size_spec.rb index 6b64866..c0047ee 100755 --- a/spec/functions/size_spec.rb +++ b/spec/functions/size_spec.rb @@ -8,15 +8,18 @@ describe 'size' do is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) } it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Unknown type given/) } - it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Unknown type given/) } it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Unknown type given/) } - it { is_expected.to run.with_params('1').and_raise_error(Puppet::ParseError, /Requires either string or array to work/) } - it { is_expected.to run.with_params('1.0').and_raise_error(Puppet::ParseError, /Requires either string or array to work/) } + it { is_expected.to run.with_params('1').and_raise_error(Puppet::ParseError, /Requires either string, array or hash to work/) } + it { is_expected.to run.with_params('1.0').and_raise_error(Puppet::ParseError, /Requires either string, array or hash to work/) } it { is_expected.to run.with_params([]).and_return(0) } it { is_expected.to run.with_params(['a']).and_return(1) } it { is_expected.to run.with_params(['one', 'two', 'three']).and_return(3) } it { is_expected.to run.with_params(['one', 'two', 'three', 'four']).and_return(4) } + it { is_expected.to run.with_params({}).and_return(0) } + it { is_expected.to run.with_params({'1' => '2'}).and_return(1) } + it { is_expected.to run.with_params({'1' => '2', '4' => '4'}).and_return(2) } + it { is_expected.to run.with_params('').and_return(0) } it { is_expected.to run.with_params('a').and_return(1) } it { is_expected.to run.with_params('abc').and_return(3) } diff --git a/spec/functions/union_spec.rb b/spec/functions/union_spec.rb index 970e1fe..cfd38b6 100755 --- a/spec/functions/union_spec.rb +++ b/spec/functions/union_spec.rb @@ -5,10 +5,9 @@ describe 'union' 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('one').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) } - it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) } - it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError, /Requires 2 arrays/) } - it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError, /Requires 2 arrays/) } - it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError, /Requires 2 arrays/) } + it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError, /Every parameter must be an array/) } + it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError, /Every parameter must be an array/) } + it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError, /Every parameter must be an array/) } end it { is_expected.to run.with_params([], []).and_return([]) } @@ -19,5 +18,7 @@ describe 'union' do it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three']).and_return(['one', 'two', 'three']) } it { is_expected.to run.with_params(['one', 'two', 'two', 'three'], ['two', 'three']).and_return(['one', 'two', 'three']) } it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'two', 'three']).and_return(['one', 'two', 'three']) } + it { is_expected.to run.with_params(['one', 'two'], ['two', 'three'], ['one', 'three']).and_return(['one', 'two', 'three']) } + it { is_expected.to run.with_params(['one', 'two'], ['three', 'four'], ['one', 'two', 'three'], ['four']).and_return(['one', 'two', 'three', 'four']) } it 'should not confuse types' do is_expected.to run.with_params(['1', '2', '3'], [1, 2]).and_return(['1', '2', '3', 1, 2]) end end diff --git a/spec/functions/unix2dos_spec.rb b/spec/functions/unix2dos_spec.rb new file mode 100644 index 0000000..8537a26 --- /dev/null +++ b/spec/functions/unix2dos_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe 'unix2dos' do + context 'Checking parameter validity' do + it { is_expected.not_to eq(nil) } + it do + is_expected.to run.with_params.and_raise_error(ArgumentError, /Wrong number of arguments/) + end + it do + is_expected.to run.with_params('one', 'two').and_raise_error(ArgumentError, /Wrong number of arguments/) + end + it do + is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) + end + it do + is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError) + end + it do + is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) + end + end + + context 'Converting from unix to dos format' do + sample_text = "Hello\nWorld\n" + desired_output = "Hello\r\nWorld\r\n" + + it 'should output dos format' do + should run.with_params(sample_text).and_return(desired_output) + end + end + + context 'Converting from dos to dos format' do + sample_text = "Hello\r\nWorld\r\n" + desired_output = "Hello\r\nWorld\r\n" + + it 'should output dos format' do + should run.with_params(sample_text).and_return(desired_output) + end + end +end diff --git a/spec/functions/validate_slength_spec.rb b/spec/functions/validate_slength_spec.rb index 391f83a..5a8fa6a 100755 --- a/spec/functions/validate_slength_spec.rb +++ b/spec/functions/validate_slength_spec.rb @@ -10,7 +10,7 @@ describe 'validate_slength' do it { is_expected.to run.with_params('', -1).and_raise_error(Puppet::ParseError, /second argument to be a positive Numeric/) } it { is_expected.to run.with_params('', 1, '').and_raise_error(Puppet::ParseError, /third argument to be unset or a positive Numeric/) } it { is_expected.to run.with_params('', 1, -1).and_raise_error(Puppet::ParseError, /third argument to be unset or a positive Numeric/) } - it { is_expected.to run.with_params('', 1, 2).and_raise_error(Puppet::ParseError, /argument to be larger than third argument/) } + it { is_expected.to run.with_params('', 1, 2).and_raise_error(Puppet::ParseError, /argument to be equal to or larger than third argument/) } end context "with a maximum length of 10" do diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 39d2d52..f784112 100755 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,28 +1,10 @@ #! /usr/bin/env ruby -S rspec require 'beaker-rspec' +require 'beaker/puppet_install_helper' UNSUPPORTED_PLATFORMS = [] -unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no' - foss_opts = { - :default_action => 'gem_install', - :version => (ENV['PUPPET_VERSION'] || '3.8.1'), - } - - if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end - - hosts.each do |host| - if host['platform'] !~ /windows/i - if host.is_pe? - on host, 'mkdir -p /etc/puppetlabs/facter/facts.d' - else - on host, "/bin/touch #{host['puppetpath']}/hiera.yaml" - on host, "mkdir -p #{host['distmoduledir']}" - on host, 'mkdir -p /etc/facter/facts.d' - end - end - end -end +run_puppet_install_helper RSpec.configure do |c| # Project root @@ -50,3 +32,35 @@ def is_future_parser_enabled? end return false end + +RSpec.shared_context "with faked facts" do + let(:facts_d) do + puppet_version = (on default, puppet('--version')).output.chomp + if fact('osfamily') =~ /windows/i + if fact('kernelmajversion').to_f < 6.0 + 'C:/Documents and Settings/All Users/Application Data/PuppetLabs/facter/facts.d' + else + 'C:/ProgramData/PuppetLabs/facter/facts.d' + end + elsif Puppet::Util::Package.versioncmp(puppet_version, '4.0.0') < 0 and fact('is_pe', '--puppet') == "true" + '/etc/puppetlabs/facter/facts.d' + else + '/etc/facter/facts.d' + end + end + + before :each do + #No need to create on windows, PE creates by default + if fact('osfamily') !~ /windows/i + shell("mkdir -p '#{facts_d}'") + end + end + + after :each do + shell("rm -f '#{facts_d}/fqdn.txt'", :acceptable_exit_codes => [0,1]) + end + + def fake_fact(name, value) + shell("echo #{name}=#{value} > '#{facts_d}/#{name}.txt'") + end +end diff --git a/spec/unit/facter/root_home_spec.rb b/spec/unit/facter/root_home_spec.rb index 98fe141..ac5160a 100755 --- a/spec/unit/facter/root_home_spec.rb +++ b/spec/unit/facter/root_home_spec.rb @@ -49,4 +49,17 @@ describe 'root_home', :type => :fact do end end + context "aix" do + before do + Facter.fact(:kernel).stubs(:value).returns("AIX") + Facter.fact(:osfamily).stubs(:value).returns("AIX") + end + let(:expected_root_home) { "/root" } + sample_lsuser = File.read(fixtures('lsuser','root')) + + it "should return /root" do + Facter::Util::Resolution.stubs(:exec).with("lsuser -C -a home root").returns(sample_lsuser) + expect(Facter.fact(:root_home).value).to eq(expected_root_home) + end + end end diff --git a/spec/unit/puppet/provider/file_line/ruby_spec.rb b/spec/unit/puppet/provider/file_line/ruby_spec.rb index 8fe3932..23e649c 100755 --- a/spec/unit/puppet/provider/file_line/ruby_spec.rb +++ b/spec/unit/puppet/provider/file_line/ruby_spec.rb @@ -36,7 +36,58 @@ describe provider_class do expect(File.read(tmpfile).chomp).to eq('foo') end end + context 'when using replace' do + before :each do + # TODO: these should be ported over to use the PuppetLabs spec_helper + # file fixtures once the following pull request has been merged: + # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files + tmp = Tempfile.new('tmp') + @tmpfile = tmp.path + tmp.close! + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo = bar', + :match => '^foo\s*=.*$', + :replace => false, + } + ) + @provider = provider_class.new(@resource) + end + + it 'should not replace the matching line' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo=blah\nfoo2\nfoo3") + end + expect(@provider.exists?).to be_truthy + @provider.create + expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo=blah\nfoo2\nfoo3") + end + + it 'should append the line if no matches are found' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo2") + end + expect(@provider.exists?).to be_nil + @provider.create + expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo2\nfoo = bar") + end + it 'should raise an error with invalid values' do + expect { + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo = bar', + :match => '^foo\s*=.*$', + :replace => 'asgadga', + } + ) + }.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./) + end + end context "when matching" do before :each do # TODO: these should be ported over to use the PuppetLabs spec_helper @@ -290,4 +341,100 @@ describe provider_class do expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n") end end + + context "when removing with a match" do + before :each do + # TODO: these should be ported over to use the PuppetLabs spec_helper + # file fixtures once the following pull request has been merged: + # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files + tmp = Tempfile.new('tmp') + @tmpfile = tmp.path + tmp.close! + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo2', + :ensure => 'absent', + :match => 'o$', + :match_for_absence => true, + } + ) + @provider = provider_class.new(@resource) + end + + it 'should remove one line if it matches' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo\nfoo2") + end + @provider.destroy + expect(File.read(@tmpfile)).to eql("foo1\nfoo2") + end + + it 'should raise an error if more than one line matches' do + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") + end + expect { @provider.destroy }.to raise_error(Puppet::Error, /More than one line/) + end + + it 'should remove multiple lines if :multiple is true' do + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo2', + :ensure => 'absent', + :match => 'o$', + :multiple => true, + :match_for_absence => true, + } + ) + @provider = provider_class.new(@resource) + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") + end + @provider.destroy + expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n") + end + + it 'should ignore the match if match_for_absense is not specified' do + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo2', + :ensure => 'absent', + :match => 'o$', + } + ) + @provider = provider_class.new(@resource) + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo\nfoo2") + end + @provider.destroy + expect(File.read(@tmpfile)).to eql("foo1\nfoo\n") + end + + it 'should ignore the match if match_for_absense is false' do + @resource = Puppet::Type::File_line.new( + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo2', + :ensure => 'absent', + :match => 'o$', + :match_for_absence => false, + } + ) + @provider = provider_class.new(@resource) + File.open(@tmpfile, 'w') do |fh| + fh.write("foo1\nfoo\nfoo2") + end + @provider.destroy + expect(File.read(@tmpfile)).to eql("foo1\nfoo\n") + end + + end + end diff --git a/spec/unit/puppet/type/file_line_spec.rb b/spec/unit/puppet/type/file_line_spec.rb index 410d0bf..f1430f2 100755 --- a/spec/unit/puppet/type/file_line_spec.rb +++ b/spec/unit/puppet/type/file_line_spec.rb @@ -49,6 +49,9 @@ describe Puppet::Type.type(:file_line) do it 'should default to ensure => present' do expect(file_line[:ensure]).to eq :present end + it 'should default to replace => true' do + expect(file_line[:replace]).to eq :true + end it "should autorequire the file it manages" do catalog = Puppet::Resource::Catalog.new diff --git a/tests/init.pp b/tests/init.pp deleted file mode 100644 index 9675d83..0000000 --- a/tests/init.pp +++ /dev/null @@ -1 +0,0 @@ -include stdlib |